Главная страница Межпроцессное взаимодействие (состязание) Для того чтобы прояснить механизм системных вызовов, кратко рассмотрим системный вызов read. Как упоминалось выше, у него есть три параметра: первый служит для задания файла, второй указывает на буфер, третий задает количество байтов, которое нужно прочитать. Как практически все системные вызовы, он запускается из программы на С с помощью вызова библиотечной процедуры с тем же именем, что и системный вызов: read. Вызов из программы на С может выглядеть так: count = readCfd, buffer, nbytes): Системный вызов (и библиотечная процедура) возвращает количество действительно прочитанных байтов в переменной count. Обычно эта величина совпадает с параметром nbytes, но может быть меньше, если, например, в процессе чтения процедуре встретился конец файла. Если системный вызов не может быть выполнен или из-за неправильных параметров или из-за дисковой ошибки, значение счетчика count устанавливается равным -1, а номер ошибки помещается в глобальную переменную errno. Программы всегда должны проверять результат системного вызова, чтобы отслеживать появление ошибки. У MINIX в целом имеется 53 системных вызова. Те из них, которые перечислены в табл. 1.1, для удобства разбиты на шесть групп. В последующих секциях мы кратко рассмотрим каждый вызов, чтобы увидеть, что он делает. В целом, выполняемые этими системными вызовами функции определяют большую часть возможностей операционной системы, так как управление ресурсами на персональных компьютерах сведено к минимуму (по крайней мере, по сравнению с большими машинами, обслуживающими множество пользователей). Таблица 1.1. Некоторые из основных системных вызовов MINIX Вызов Описание Управление процессами pid = fork( ) Создает дочерний процесс, идентичный родительскому pid = waitpid(pid, &statloc, options) Ожидает завершения дочернего процесса S = wait(&status) Старая версия waitpid S = execve(name, argv, environp) Перемещает образ памяти процесса Exit(status) Завершает выполнение процесса и возвращает статус size = brk(addr) Устанавливает размер сегмента данных pid = getpidO Возвращает идентификатор процесса, сделавшего вызов pid = getgrpO Возвращает идентификатор группы процессов для сделавшего вызов процесса pid = setsidO Создает новую сессию и возвращает ее идентификатор группы процессов I = ptrace(req, pid, addr, data) Используется для отладки Сигналы S = sigaction(sig, &act, &oldact) Устанавливает реакцию на сигнал продолжением Таблица 1.1 {продолжение) Вызов Описвние S = sigreturn(&context) S = sigprocmask(howm &set, &old) s = sigpending(set) s = sigsuspend(sigmask) s = kill(pid, sig) residual = alarm(seconds) s = pauseO Управление файлами fd = creat(name, mode) fd =mknod(name, mode, addr) fd=open(file, how, ...) s = close(fd) n = read(fd, buffer, nbytes) n = write(fd, buffer, nbytes) pos = lseek(fd, offset, whence) s = stat(name, &buf) s = fstat(fd, &buf) fd = dup(fd) s = pipe(&fd[0]) s = ioctl(fd, request, argp) s = access(name, amode) s = rename(old, new) s = fcntl(fd, cmd, ...) Управление каталогами и файловой системой Возвращается из обработчика сигнала Определяет или устанавливает маску сигналов для процесса Определяет набор блокированных сигналов Устанавливает маску сигналов для процесса и приостанавливает его Посылает сигнал процессу Устанавливает сигнальный таймер Приостанавливает процесс до прихода следующего сигнала Устаревший способ создать файл Создает обычный, специальный или относящийся к директории i-узел Открывает файл для чтения, записи или того и другого Закрывает открытый файл Читает данные из файла в буфер Пишет данные из буфера в файл Передвигает указатель файла Получает информацию о состоянии файла Получает информацию о состоянии файла Закрепляет за открытым файлом новый дескриптор Создает канал Специальные действия с файлом Проверить доступность файла Переименовать файл Захват файла и другие действия S = mkdir(name, mode) s = rmdir(name) s = Iink(name1, name2) s = unlink(name) s = mount(special, name, flag) s = umount(speclal) s = syncO s = chdir(dirname) s = chroot(dirname) Защита s = chmod(name, mode) Создает новый каталог Удаляет пустой каталог Создает новый элемент с именем пате2, указывающий на name! Удаляет элемент каталога Монтирует файловую систему Демонтирует файловую систему Сбросить все кэшированные блоки на диск Изменяет рабочий каталог Изменяет корневую директорию Изменяет биты защиты файла Вызов Описание uid = getuidO gid = getgidO s = setuid(uid) s = setgid(gid) s = chown(name, owner, group) oldmask = umask(complmode) Работа CO временем seconds = time(&seconds) s = stime(tp) s = utime(file, timep) s = times(buffer) Определяет идентификатор сделавшего вызов Определяет идентификатор группы сделавшего вызов Устанавливает идентификатор пользователя Устанавливает идентификатор группы Меняет идентификатор владельца файла Устанавливает маскирование разрешений Получает время, прошедшее с 1 января 1970 года Устанавливает время, прошедшее с 1 января 1970 года Устанавливает время последнего доступа к файлу Определяет время работы пользовательского процесса и системы Возвращаемая величина s равна -1, если произошла ошибка. Возвращаемые коды выглядят так: pid выдает идентификатор процесса, fd - описатель файла, п - количество байтов, position - смещение в файле и seconds - прошедшее время. Параметры описываются дальше в тексте. Особое внимание следует обратить на то, что преобразование вызовов процедур POSIX в системные вызовы не является взаимно однозначным. Стандарт POSIX определяет ряд процедур, которые должны поддерживать совместимые системы, но он не указывает, являются ли они системными вызовами, библиотечными вызовами или чем-нибудь еще. В некоторых случаях, особенно когда требуемые процедуры являются всего лишь разновидностями друг друга, один системный вызов обрабатывает сразу несколько библиотечных вызовов. 1.4.1. Системные вызовы для управления процессами Первая группа в табл. 1.1 управляет процессами. Начнем рассмотрение с вызова fork. Системный вызов fork (разветвление) является единственным способом создания нового процесса в UNIX. Он создает точную копию исходного процесса, включая дескрипторы файла, регистры и т. п. После вызова fork исходный процесс и его копия (родительский и дочерний) развиваются по отдельности друг от друга. Все переменные имеют одинаковые величины во время вызова fork, но как только родительские данные скопированы для создания дочернего процесса, последующие изменения в одном из них уже не влияют на другой. (Текст программы, который не изменяется, распределяется между родительским и дочерним процессами.) Вызов fork возвращает величину, равную нулю в дочернем процессе и равную идентификатору дочернего процесса или PID в родительском. Используя возвращенный PID, два процесса могут различить, какой из них родительский, а какой - дочерний. В большинстве случаев после вызова fork дочернему процессу необходимо выполнить программный код, отличный от предназначенного для родительского процесса. Рассмотрим пример оболочки. Она читает команды с терминала, за-
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |