Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 33 34 35 36 37 38 39  40 41 42 43 44 45 46 ... 87

                            /* Выделить последнюю компоненту пути from */
                            if((s = strrchr(from, '/')) && s[1])
                                    s++;
                            else    s = from;

                            dirname = to;

                            /* Целевой файл - файл в этом каталоге */
                            sprintf(newname, "%s/%s", to, s);
                            to = newname;

                            if(stat(to, &stt) < 0)
                                    goto not_exist;
                    }

                    if(stt.st_dev == stf.st_dev && stt.st_ino == stf.st_ino){
                            error("%s: cannot copy file to itself", from);
                            return (-3);
                    }
                    switch(stt.st_mode & S_IFMT){
                    case S_IFBLK:
                    case S_IFCHR:
                    case S_IFIFO:
                            break;

                    default:
                            printf("%s already exists, overwrite ? ", to);
                            fflush(stdout);

                            *answer = '\0';
                            gets(answer);

                            if(*answer != 'y'){     /* NO */
                                    close(fdin);
                                    return (-4);
                            }
                            break;
                    }
            }

А. Богатырев, 1992-95                  - 210 -                              Си в UNIX

    not_exist:
            printf("COPY %s TO %s\n", from, to);

            if((stf.st_mode & S_IFMT) == S_IFREG){
                    /* Проверка наличия свободного места в каталоге dirname */
                    struct statvfs fs;
                    char tmpbuf[MAXPATHLEN+1];

                    if(dirname == NULL){
                            /* То 'to' - это имя файла, а не каталога */
                            strcpy(tmpbuf, to);
                            if(s = strrchr(tmpbuf, '/')){
                                    if(*tmpbuf != '/' || s != tmpbuf){
                                            /* Имена "../xxx"
                                             * и второй случай:
                                             * абсолютные имена не в корне,
                                             * то есть не "/" и не "/xxx"
                                             */
                                            *s = '\0';
                                    }else{
                                            /* "/" или "/xxx" */
                                            if(s[1]) s[1] = '\0';
                                    }
                                    dirname = tmpbuf;
                            } else  dirname = ".";
                    }

                    if(statvfs(dirname, &fs) >= 0){
                            size_t size = (geteuid() == 0 ) ?
                                    /* Доступно суперпользователю: байт */
                                    fs.f_frsize * fs.f_bfree :
                                    /* Доступно обычному пользователю: байт */
                                    fs.f_frsize * fs.f_bavail;

                            if(size < stf.st_size){
                               error("Not enough free space on %s: have %lu, need %lu",
                                      dirname, size, stf.st_size);
                               close(fdin);
                               return (-5);
                            }
                    }
            }

            if((fdout = creat(to, stf.st_mode)) < 0){
                    error("Can't create %s", to);
                    close(fdin);
                    return (-6);
            } else {
                    fchmod(fdout, stf.st_mode);
                    fchown(fdout, stf.st_uid, stf.st_gid);
            }

А. Богатырев, 1992-95                  - 211 -                              Си в UNIX

            while (n = read (fdin, iobuf, sizeof iobuf)) {
                    if(n < 0){
                            error ("read error");
                            code = (-7);
                            goto done;
                    }
                    if(write (fdout, iobuf, n) != n) {
                            error ("write error");
                            code = (-8);
                            goto done;
                    }
            }

    done:
            close (fdin);
            close (fdout);

            /* Проверить: соответствует ли результат ожиданиям */
            if(stat(to, &stt) >= 0 && (stt.st_mode & S_IFMT) == S_IFREG){
                    if(stf.st_size < stt.st_size){
                            error("File has grown at the time of copying");
                    } else if(stf.st_size > stt.st_size){
                            error("File too short, target %s removed", to);
                            unlink(to);
                            code = (-9);
                    }
            }
            return code;
    }

    int main(int argc, char *argv[]){
            int i, code = 0;

            progname = argv[0];

            if(argc < 3){
                    error("Usage: %s from... to", argv[0]);
                    return 1;
            }
            for(i=1; i < argc-1; i++)
                    code |= copyFile(argv[argc-1], argv[i]) < 0 ? 1 : 0;
            return code;
    }

Возвращаемая структура struct statvfs содержит такие поля (в частности):

    Типа long:
    f_frsize                размер блока
    f_blocks                размер файловой системы в блоках
    f_bfree                 свободных блоков (для суперпользователя)
    f_bavail                свободных блоков (для всех остальных)

    f_files                 число I-nodes в файловой системе
    f_ffree                 свободных I-nodes (для суперпользователя)
    f_favail                свободных I-nodes (для всех остальных)

    Типа char *
    f_basetype              тип файловой системы: ufs, nfs, ...

А. Богатырев, 1992-95                  - 212 -                              Си в UNIX

По два значения дано потому, что операционная система резервирует часть файловой сис-
темы  для использования ТОЛЬКО суперпользователем (чтобы администратор смог распихать
файлы в случае переполнения диска, и имел резерв на это). ufs - это UNIX file  system
из BSD 4.x

6.4.  Сигналы.
     Процессы в UNIX используют много разных механизмов взаимодействия. Одним из  них
являются сигналы.
     Сигналы - это асинхронные события. Что это значит?  Сначала объясним, что  такое
синхронные события: я два раза в день подхожу к почтовому ящику и проверяю - нет ли в
нем почты (событий).  Во-первых, я произвожу опрос - "нет ли для  меня  события?",  в
программе  это выглядело бы как вызов функции опроса и, может быть, ожидания события.
Во-вторых, я знаю, что почта может ко мне прийти, поскольку я подписался на  какие-то
газеты. То есть я предварительно заказывал эти события.
     Схема с синхронными событиями очень распространена.  Кассир сидит у кассы и ожи-
дает,  пока  к нему в окошечко не заглянет клиент.  Поезд периодически проезжает мимо
светофора и останавливается, если горит красный.  Функция Си пассивно "спит"  до  тех
пор,  пока  ее  не вызовут; однако она всегда готова выполнить свою работу (обслужить
клиента).  Такое ожидающее  заказа  (события)  действующее  лицо  называется  сервер.
После  выполнения  заказа  сервер вновь переходит в состояние ожидания вызова.  Итак,
если событие ожидается в специальном месте и в определенные моменты времени (издается
некий  вызов  для  ОПРОСА)  -  это синхронные события.  Канонический пример - функция
gets, которая задержит выполнение программы,  пока  с  клавиатуры  не  будет  введена
строка.   Большинство  ожиданий внутри системных вызовов - синхронны.  Ядро ОС высту-
пает для программ пользователей в роли сервера, выполняющего  сисвызовы  (хотя  и  не
только  в этой роли - ядро иногда предпринимает и активные действия: передача процес-
сора другому процессу через определенное время (режим разделения  времени),  убивание
процесса при ошибке, и.т.п.).
     Сигналы - это асинхронные события. Они приходят неожиданно, в любой момент  вре-
мени  -  вроде  телефонного  звонка.  Кроме того, их не требуется заказывать - сигнал
процессу может поступить совсем без повода.  Аналогия из жизни такова: человек  сидит
и  пишет  письмо. Вдруг его окликают посреди фразы - он отвлекается, отвечает на воп-
рос, и вновь продолжает прерванное занятие. Человек  не  ожидал  этого  оклика  (быть
может,  он готов к нему, но он не озирался по сторонам специально).  Кроме того, сиг-
нал мог поступить когда он писал 5-ое предложение, а мог - когда 34-ое.  Момент  вре-
мени, в который произойдет прерывание, не фиксирован.
     Сигналы имеют номера, причем их количество ограничено - есть определенный список
допустимых  сигналов.  Номера  и  мнемонические имена сигналов перечислены в include-
файле  и имеют вид SIGнечто.  Допустимы сигналы с номерами  1..NSIG-1,  где
NSIG  определено  в  этом  файле.   При  получении сигнала мы узнаем его номер, но не
узнаем никакой иной информации: ни от кого поступил сигнал,  ни  что  от  нас  хотят.
Просто "звонит телефон". Чтобы получить дополнительную информацию, наш процесс должен
взять ее из другого известного места; например - прочесть заказ из некоторого  файла,
об  имени которого все наши программы заранее "договорились".  Сигналы процессу могут
поступать тремя путями:
-    От другого процесса, который явно посылает его нам вызовом
         kill(pid, sig);
     где pid - идентификатор (номер) процесса-получателя,  а  sig  -  номер  сигнала.
     Послать сигнал можно только родственному процессу - запущенному тем же пользова-
     телем.
-    От операционной системы. Система может посылать процессу ряд сигналов,  сигнали-
     зирующих  об ошибках, например при обращении программы по несуществующему адресу
     или при ошибочном номере системного вызова. Такие сигналы обычно прекращают  наш
     процесс.
-    От пользователя - с клавиатуры терминала можно нажимом некоторых клавиш  послать
     сигналы SIGINT и SIGQUIT.  Собственно, сигнал посылается драйвером терминала при
     получении им с клавиатуры определенных символов. Так можно прервать  зациклившу-
     юся или надоевшую программу.

Процесс-получатель должен как-то отреагировать на сигнал.  Программа может:

А. Богатырев, 1992-95                  - 213 -                              Си в UNIX

-    проигнорировать сигнал (не ответить на звонок);
-    перехватить сигнал (снять трубку), выполнить какие-то действия, затем продолжить
     прерванное занятие;
-    быть убитой сигналом (звонок был подкреплен броском гранаты в окно);

В большинстве случаев сигнал по умолчанию убивает процесс-получатель.  Однако процесс
может изменить это умолчание и задать свою реакцию явно. Это делается вызовом signal:

    #include 
    void (*signal(int sig, void (*react)() )) ();

Параметр react может иметь значение:
SIG_IGN
     сигнал sig будет отныне игнорироваться.  Некоторые  сигналы  (например  SIGKILL)
     невозможно перехватить или проигнорировать.
SIG_DFL
     восстановить реакцию по умолчанию (обычно - смерть получателя).
имя_функции
     Например

          void fr(gotsig){ ..... }  /* обработчик */
          ... signal (sig, fr); ... /* задание реакции */

     Тогда при получении сигнала sig будет вызвана функция fr, в которую  в  качестве
     аргумента  системой  будет  передан номер сигнала, действительно вызвавшего ее -
     gotsig==sig.  Это полезно, т.к. можно задать одну и ту  же  функцию  в  качестве
     реакции для нескольких сигналов:
Предыдущая страница Следующая страница
1 ... 33 34 35 36 37 38 39  40 41 42 43 44 45 46 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама