Основы операционных систем
Изучение теорий операционных систем. Исследование принципов построения и особенностей проектирования современных ОС. Сущность виртуальной памяти и алгоритма синхронизации. Рассмотрение операционной и файловой системы, система управления вводом-выводом.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | книга |
Язык | русский |
Дата добавления | 12.01.2010 |
Размер файла | 2,6 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Отображение файла из пространства имен в адресное пространство процесса происходит в два этапа: сначала выполняется отображение в дисковое пространство, а уже затем из дискового пространства в адресное. Поэтому вначале файл необходимо открыть, используя обычный системный вызов open ( ) .
Вторым этапом является отображение файла целиком или частично из дискового пространства в адресное пространство процесса. Для этого используется системный вызов mmap (). Файл после этого можно и закрыть, выполнив системный вызов close(), так как необходимую информацию о расположении файла на диске мы уже сохранили в других структурах данных при вызове mmap ().
Системный вызов mmap()
Прототип системного вызова
#include <sys/types.h> #include <unistd.h>-#include <sys/imen.h>
void *ramap (void *start, size_t length, int prot, int flags, int fd, off_t offset);
Описание системного вызова
Системный вызов mmap служит для отображения предварительно открытого файла (например, с помощью системного вызова open ()) в адресное пространство вычислительной системы. После его выполнения файл может быть закрыт (например, системным вызовом close ()), что никак не повлияет на дальнейшую работу с отображенным файлом.
Настоящее описание не является полным описанием системного вызова, а предназначено только для использования в рамках данного курса. Для получения полной информации обращайтесь к UNIX Manual.
Параметр fd является файловым дескриптором для файла, который мы хотим отобразить в адресное пространство (т. е. значением, которое вернул системный вызов open ()).
Ненулевое значение параметра start может использоваться только очень квалифицированными системными пс<>граммистами, поэтому мы в семинарах будем всегда полагать его равным значению NULL, позволяя операционной системе самой выбрать начало области адресного пространства, в которую будет отображен файл.
В память будет отображаться часть файла, начиная с позиции внутри его, заданной значением параметра offset - смещение от начала файла в байтах, и длиной, равной значению параметра length (естественно, тоже в байтах). Значение параметра length может и превышать реальную длину от позиции offset до конца существующего файла. На поведении системного вызова это никак не отразится, но в дальнейшем при попытке доступа к ячейкам памяти, лежащим вне границ реального файла, возникнет сигнал SIGBUS (реакция на него по умолчанию - прекращение процесса с образованием core файла).
Параметр flags определяет способ отображения файла в адресное пространство. В рам-ках нашего курса мы будем использовать только два его возможных значения: MAP_SHARED иMAP_PRTVATE. Если в качестве его значения выбрано MAP_SHAKED, то полученное отображениефайла вгюследствии будет иотользоеатьга вызвавшими mmap для этого
файла с аналогичными значениями параметров, а все изменения, сделанные в отображенном файле, будут сохранены во вторичной памяти. Если в качестве значения параметра flags указано MAP_PRTVATE, то процесс получает отображение файла в свое монопольное распоряжение, но все изменения в нем не могут быть занесены во вторичную память (т. е., проще говоря, не сохранятся).
Параметр prot определяет разрешенные операции над областью памяти, в которую будет отображен файл. В качестве его значения мы будем использовать значения PR0T_READ (разрешено чтение), PR0T_WRITE (разрешена запись) или их комбинацию через операцию «побитовое или» - «I». Необходимо отметить две существенные особенности системного вызова, связанные с этим параметром:
Значение параметра prot не может быть шире, чем операции над файлом, заявленные при его открытии в параметре flags системного вызова open (). Например, нельзя открыть файл только для чтения, а при его отображении в память использовать значение prot = PR0T_READ I PROT_WRITE.
В результате ошибки в операционной системе Linux при работе на 486-х и 586-х процессорах попытка записать в отображение файла, открытое только для записи, более 32-х байт одновременно приводит к ошибке (возникает сигнал о нарушении защиты памяти).
Возвращаемое значение
При нормальном завершении системный вызов возвращает начальный адрес области памяти, в которую отображен файл (или его часть), при возникновении ошибки - специальное значение MAP_FAILED.
После этого с содержимым файла можно работать, как с содержимым обычной области памяти.
По окончании работы с содержимым файла необходимо освободить дополнительно выделенную процессу область памяти, предварительно синхронизировав содержимое файла на диске с содержимым этой области (если это, конечно, необходимо). Эти действия выполняет системный вызов типтар ().
Системный вызов munmap Прототип системного вызова
linclude <sys/types.h>
linclude <unistd.h>
#include <sys/mman.h>
int munmap (void *start, size_t length);
Описание системного вызова
Системный вызов munmap служит для прекращения отображения memory mapped файла в адресное пространство вычислительной системы. Если при системном вызове гитар () было задано значение параметра flags, равное MAP_SHARED, и в отображении файла была разрешена операция записи (в параметре prot использовалось значение PROT_WRITE), то munmap синхронизирует содержимое отображения с содержимым файла во вторичной памяти. После его выполнения области памяти, использовавшиеся для отображения файла, становятся недоступны текущему процессу.
Параметр start является адресом начала области памяти, выделенной для отображения файла, т. е. значением, которое вернул системный вызов mmap ().
Параметр length определяет ее длину, и его значение должно совпадать со значением соответствующего параметра в системном вызове татар ().
Возвращаемое значение
При нормальном завершении системный вызов возвращает значение 0, при возникновении ошибки - значение -1.
Анализ, компиляция и прогон программы для создания memory mapped файла и записи его содержимого
Для закрепления материала, изложенного в предыдущем разделе, рассмотрим пример программы:
/* Программа 11-1. с для иллюстрации работы с memory mapped файлом */ int main(void) {
int fd; /* Файловый дескриптор для файла, в котором будет храниться наша информация*/ size_t length;' /* Длина отображаемой части файла */ int i ;
/* Ниже следует описание типа структуры, которым мы
забьем файл, и двух указателей на подобный тип.
Указатель ptr будет использоваться в качестве
начального адреса выделенной области памяти,
а указатель tmpptr - для перемещения внутри этой
области. */
struct А {
double f;
double f2; } *ptr, tmpptr;
/* Открываем файл или сначала создаем его (если такого файла не было). Права доступа к файлу при создании определяем как read and write для всех категорий пользователей (0666). Из-за ошибки в Linux мы будем вынуждены ниже в системном вызове mmap() разрешить в отображении файла и чтение, и запись, хотя реально нам нужна только запись.
Поэтому и при открытии файла мы вынуждены задавать 0_RDWR. */
fd = open("mapped.dat", 0_RDWR I 0_CREAT, 0666); if( fd == -1) {
/* Если файл открыть не удалось, выдаем
сообщение об ошибке и завершаем работу */
printf("File open failed J\n");
exit(1);
}
/* Вычисляем будущую длину файла (мы собираемся
записать в него 100000 структур) */
length = 100000*sizeof(struct А);
/* Вновь созданный файл имеет длину 0. Если мы
его отобразим в память с такой длиной, то любая
попытка записи в выделенную память приведет к
ошибке. Увеличиваем длину файла с помощью вызова
ftruncate(). */
ftruncate(fd,length);
/* Отображаем файл в память. Разрешенные операции над отображением указываем как PROT_WRITE | PROT_READ по уже названным причинам. Значение флагов ставим в MAP_SHARED, так как мы хотим сохранить информацию, которую занесем в отображение, на диске. Файл отображаем с его начала (offset = 0) и до конца (length = длине файла). */ ptr = (struct A )mmap(NULL, length, PROT_WRITE I PROT_READ, MAP_SHARED, fd, 0);
/* Файловый дескриптор нам более не нужен, и мы его закрываем */ close(fd);
if( ptr == MAP_FAILED ){
/* Если отобразить файл не удалось, сообщаем об ошибке и завершаем работу */ printf("Mapping failed!\n"); exit(2);
}
/* В цикле заполняем образ файла числами от 1 до 100000 и их квадратами. Для перемещения по области памяти используем указатель tmpptr, так как указатель ptr на начало образа файла нам понадобится для прекращения отображения вызовом munmap(). */ tmpptr = ptr;
for(i = 1; i <=100000; i++){ tmpptr->f = i;
tmpptr->f2 = tmpptr->f*tmpptr->f; tmpptr++;
}
/* Прекращаем отображать файл в память, записываем содержимое отображения на диск и освобождаем память. */ munmap((void *)ptr, length); return 0;
}
Эта программа создает файл, отображает его в адресное пространство процесса и заносит в него информацию с помощью обычных операций языка С.
Обратите внимание на необходимость увеличения размера файла перед его отображением. Созданный файл имеет нулевой размер, и если его с этим размером отобразить в память, то мы сможем записать в него или прочитать из него не более 0 байт, т. е. ничего. Для увеличения размера файла использован системный вызов f truncate (), хотя это можно было бы сделать и любым другим способом.
При отображении файла мы вынуждены разрешить в нем и запись, и чтение, хотя реально совершаем только запись. Это сделано для того, чтобы избежать ошибки в операционной системе Linux, связанной с использованием 486-х и 586-х процессоров. Такой список разрешенных операций однозначно требует, чтобы при открытии файла системным вызовом open () файл открывался и на запись, и на чтение. Поскольку информацию мы желаем сохранить надиске, при отображении использовано значение флагов MAP_SHARED. Откомпилируйте эту программу и запустите ее.
Изменение предыдущей программы для чтения из файла, используя его отображение в память
Модифицируйте программу из предыдущего раздела так, чтобы она отображала файл, записанный программой из раздела «Анализ, компиляция и прогон программы для создания memory mapped файла и записи его содержимого», в память и считала сумму квадратов чисел от I до 100000, которые уже находятся в этом файле.
Задача повышенной сложности: напишите две программы, использующие memory mapped файл для обмена информацией при одновременной работе, подобно тому, как они могли бы использовать разделяемую память.
Семинары 12-13. Организация ввода-вывода в UNIX. Файлы устройств. Аппарат прерываний. Сигналы в UNIX
Понятие виртуальной файловой системы. Операции над файловыми системами. Монтирование файловых систем. Блочные, символьные устройства. Понятие драйвера. Блочные, символьные драйверы, драйверы низкого уровня. Файловый интерфейс. Аппаратные прерывания (interrupt), исключения (exception), программные прерывания (trap, software interrupt). Их обработка. Понятие сигнала. Способы возникновения сигналов и виды их обработки. Понятия группы процессов, сеанса, лидера группы, лидера сеанса, управляющего терминала сеанса. Системные вызовы getpgrpO, setpgrpO, getpgicM), setpgidO, getsid(), setsid(). Системный вызов kill () и команда kill (). Системный вызов signal (). Установка собственного обработчика сигнала. Восстановление предыдущей реакции на сигнал. Сигналы SIGUSR1 и SIGUSR2. Использование сигналов для синхронизации процессов. Завершение порожденного процесса. Системный вызов waitpidO. Сигнал SIGCHLD. Возникновение сигнала SIGPIPE при попытке записи в pipe или FIFO, который никто не собирается читать. Понятие надежности сигналов. POSIX-функции для работы с сигналами.
Ключевые слова: виртуальная файловая система, виртуальный узел (vnode), таблица виртуальных узлов открытых файлов, таблица операций, монтирование файловых систем, команды mount и umount, блочные и символьные устройства, драйверы устройств, коммутатор устройств, старший и младший номера устройств, аппаратные прерывания, исключения, программные прерывания, сигналы, группа процессов, сеанс, лидер группы процессов, лидер сеанса, системные вызовы getpgrp (), setpgrp (), getpgid (), setpgid (), gets id (), setsidf), управляющий терминал сеанса, текущая группа процессов, фоновая группа процессов, эффективный идентификатор пользователя (EUID), команда kill, системные вызовы kill(), signal (), сигналы SIGHUP, SIGQUIT, SIGINT, SIGCHLD, SIGPIPE, SIGUSR1, SIGUSR2, SIGKILL, SIGTERM, системные вызовы waitpidO и wait (), POSIX-сигналы.
Понятие виртуальной файловой системы
Семинары 10--11 были посвящены устройству файловой системы s5fs. Существуют и другие файловые системы, имеющие архитектуру, отличную от архитектуры s5fs (иные способы отображения файла на пространство
физического носителя, иное построение директорий и т. д.). Современные версии 1Ж1Х-подобных операционных систем умеют работать с разнообразными файловыми системами, различающимися своей организацией. Такая возможность достигается с помощью разбиения каждой файловой системы на зависимую и независимую от конкретной реализации части, подобно тому, как в лекции 13, посвященной вопросам ввода-вывода, мы отделяли аппаратно-зависимые части для каждого устройства -- драйверы -- от общей базовой подсистемы ввода-вывода. Независимые части всех файловых систем одинаковы и представляют для всех остальных элементов ядра абстрактную файловую систему, которую принято называть виртуальной файловой системой. Зависимые части для различных файловых систем могут встраиваться в ядро на этапе компиляции либо добавляться к нему динамически по мере необходимости, без перекомпиляции системы (как в системах с микроядерной архитектурой).
Рассмотрим схематично устройство виртуальной файловой системы. В файловой системе вбГв данные о физическом расположении и атрибутах каждого открытого файла представлялись в операционной системе структурой данных в таблице индексных узлов открытых файлов (см. семинар 10--11, раздел «Системные вызовы и команды для выполнения операций над файлами и директориями»), содержащей информацию из индексного узла файла во вторичной памяти. В виртуальной файловой системе, в отличие от вбГз, каждый файл характеризуется не индексным узлом тос!е, а некоторым виртуальным узлом Упос!е. Соответственно, вместо таблицы индексных узлов открытых файлов в операционной системе появляется таблица виртуальных узлов открытых файлов. При открытии файла в операционной системе для него заполняется (если, конечно, не был заполнен раньше) элемент таблицы виртуальных узлов открытых файлов, в котором хранятся, как минимум, тип файла, счетчик числа открытий файла, указатель на реальные физические данные файла и, обязательно, указатель на таблицу системных вызовов, совершающих операции над файлом, -- таблицу операций. Реальные физические данные файла (равно как и способ расположения файла на диске и т. п.) и системные вызовы, реально выполняющие операции над файлом, уже не являются элементами виртуальной файловой системы. Они относятся к одной из зависимых частей файловой системы, так как определяются ее конкретной реализацией.
При выполнении операций над файлами по таблице операций, чей адрес содержится в Упос!е, определяется системный вызов, который будет на самом деле выполнен над реальными физическими данными файла, чей адрес также находится в упос!е. В случае с 85Гв данные, на которые ссылается Упос!е, -- это как разданные индексного узла, рассмотренные на семинарах 10--11 и на лекции 12. Заметим, что таблица операций является общей для всех файлов, принадлежащих одной и той же файловой системе.
Операции над файловыми системами. Монтирование файловых систем
В материалах семинаров 11 --12 рассматривалась только одна файловая система, расположенная в одном разделе физического носителя. Как только мы переходим к сосуществованию нескольких файловых систем в рамках одной операционной системы, встает вопрос о логическом объединении структур этих файловых систем. При работе операционной системы нам изначально доступна лишь одна, так называемая корневая, файловая система. Прежде, чем приступить к работе с файлом, лежащим в некоторой другой файловой системе, мы должны встроить ее в уже существующий ациклический граф файлов. Эта операция -- операция над файловой системой -- называется монтированием файловой системы (mount).
Для монтирования файловой системы (см. лекцию 12, раздел «Монтирование файловых систем») в существующем графе должна быть найдена или создана некоторая пустая директория -- точка монтирования, к которой и присоединится корень монтируемой файловой системы. При операции монтирования в ядре заводятся структуры данных, описывающие файловую систему, а в vnode для точки монтирования файловой системы помещается специальная информация.
Монтирование файловых систем обычно является прерогативой системного администратора и осуществляется командой операционной системы mount в ручном режиме, либо автоматически при старте операционной системы. Использование этой команды без параметров не требует специальных полномочий и позволяет пользователю получить информацию обо всех смонтированных файловых системах и соответствующих им физических устройствах. Для пользователя также обычно разрешается монтирование файловых систем, расположенных на гибких магнитных дисках. Для первого накопителя на гибких магнитных дисках такая команда в Linux будет выглядеть следующим образом:
mount /dev/fdO <имя пустой директории>
где <имя пустой директории> описывает точку монтирования, а /dev/fdO -- специальный файл устройства, соответствующего этому накопителю (о специальных файлах устройств будет подробно рассказано в следующем разделе).
Команда mount
Синтаксис команды
mount [-hV]
mount [-rw] [-t fstype] device dir Описание команды
Настоящее описание не является полным описанием команды mount, а описывает только те ее опции (очень малую часть), которые используются в данном курсе. Для получения полного описания следует обратиться к UNIX Manual.
Команда mount предназначена для выполнения операции монтирования файловой системы и получения информации об уже смонтированных файловых системах.
Опции -h, -V используются при вызове команды без параметров и служат для следующих целей:
-h - вывести краткую инструкцию по пользованию командой; -V - вывести информацию о версии команды mount.
Команда mount без опций и без параметров выводит информацию обо всех уже смонтированных файловых системах.
Команда mount с параметрами служит для выполнения операции монтирования файловой системы.
Параметр device задает имя специального файла для устройства, содержащего файловую систему.
Параметр dir задает имя точки монтирования (имя некоторой уже существующей пустой директории). При монтировании могут использоваться следующие опции:
-г - смонтировать файловую систему только для чтения (read only);
-w - смонтировать файловую систему для чтения и для записи (read/write). Ис-
пользуется по умолчанию;
-t fstype - задать тип монтируемой файловой системы как fstype. Поддерживаемые типы файловых систем в операционной системе Linux: aofs, affs, autofs, coda, coherent, cramfs, devpts, efs, ext, ext2, ext3, Ms, hpfs, iso9660 (для CD), nrtinix, msdos, ncpfs, nfs, ntfs, proc, qnx4, reiseris, romfs, smbts, sysv, udf, ufs, umsdos, vfat, xenix, xfs, xiafs. При отсутствии явно заданного типа команда для большинства типов файловых систем способна опознать его автоматически.
Если мы не собираемся использовать смонтированную файловую систему в дальнейшем (например, хотим вынуть ранее смонтированную дискету), нам необходимо выполнить операцию логического разъединения смонтированных файловых систем (шпоиг^). Для этой операции, которая тоже, как правило, является привилегией системного администратора, используется команда штюиг^ (может выполняться в ручном режиме или автоматически при завершении работы операционной системы). Для пользователя обычно доступна команда отмонтирования файловой системы на дискете в форме
umount <имя точки монтирования>
где <имя точки монтирования> -- это <имя пустой директории>, использованное ранее в команде mount, или в форме
umount /dev/fdO
где /dev/f dO - специальный файл устройства, соответствующего первому накопителю на гибких магнитных дисках.
Заметим, что для последующей корректной работы операционной системы при удалении физического носителя информации обязательно необходимо предварительное логическое разъединение файловых систем, если они перед этим были объединены.
Команда umount
Синтаксис команды
umount [-hv] umount device umount dir
Описание команды
Настоящее описание не является полным описанием команды umount, а описывает только те ее опции (очень малую часть), которые используются в данном курсе. Для получения полного описания следует обратиться к UNK Manual (команда man).
Команда предназначена для вы смонтированных файловых систем.
Опции -h, -V используются при вызове команды без параметров и служат для следующих целей:
-h - вывести краткую инструкцию по пользованию командой; -V - вывести информацию о версии команды umount.
Команда umount с параметром служит для выполнения операции логического разъединения файловых систем. В качестве параметра может быть задано либо имя устройства, содержащего файловую систему - device, либо имя точки монтирования файловой системы (т. е. имя директории, которое указывалось в качестве параметра при вызове команды mount) - dir.
Заметим, что файловая система не может быть отмонтирована до тех пор, пока она находится в использовании (busy) -- например, когда в ней существуют открытые файлы, какой-либо процесс имеет в качестве рабочей директории директорию в этой файловой системе и т. д.
Блочные, символьные устройства. Понятие драйвера. Блочные, символьные драйверы, драйверы низкого уровня. Файловый интерфейс
Обремененные знаниями об устройстве современных файловых систем в UNIX, мы можем, наконец, заняться вопросами реализации подсистемы ввода-вывода.
В лекции 13 (раздел «Структура системы ввода-вывода») речь шла о том, что все устройства ввода-вывода можно разделить на относительно небольшое число типов, в зависимости от набора операций, которые могут ими выполняться. Такое деление позволяет организовать «слоистую» структуру подсистемы ввода-вывода, вынеся все аппаратно-зависимые части в драйверы устройств, с которыми взаимодействует базовая подсистема ввода-вывода, осуществляющая стратегическое управление всеми устройствами.
В операционной системе UNIX принята упрощенная классификация устройств (см. лекцию 13, раздел «Систематизация внешних устройств и интерфейс между базовой подсистемой ввода-вывода и драйверами»): все устройства разделяются по способу передачи данных на символьные и блочные. Символьные устройства осуществляют передачу данных байт за байтом, в то время как блочные устройства передают блок байт как единое целое. Типичным примером символьного устройства является клавиатура, примером блочного устройства -- жесткий диск. Непосредственное взаимодействие операционной системы с устройствами ввода-вывода обеспечивают их драйверы. Существует пять основных случаев, когда ядро обращается к драйверам.
Автоконфигурация. Происходит в процессе инициализации операционной системы, когда ядро определяет наличие доступных устройств.
Ввод-вывод. Обработка запроса ввода-вывода.
Обработка прерываний. Ядро вызывает специальные функции драйвера для обработки прерывания, поступившего от устройства, в том числе, возможно, для планирования очередности запросов к нему.
Специальные запросы. Например, изменение параметров драйвера или устройства.
5. Повторная инициализация устройства или останов операционной системы.
Так же как устройства подразделяются на символьные и блочные, драйверы тоже существуют символьные и блочные. Особенностью блочных устройств является возможность организации на них файловой системы, поэтому блочные драйверы обычно используются файловой системой UNIX. При обращении к блочному устройству, не содержащему файловой системы, применяются специальные драйверы низкого уровня, как правило, представляющие собой интерфейс между ядром операционной системы и блочным драйвером устройства.
Для каждого из этих трех типов драйверов были выделены основные функции, которые базовая подсистема ввода-вывода может совершать над устройствами и драйверами: инициализация устройства или драйвера, временное завершение работы устройства, чтение, запись, обработка прерывания, опрос устройства и т. д. (об этих операциях уже говорилось в лекции 13, раздел «Систематизация внешних устройств и интерфейс между базовой подсистемой ввода-вывода и драйверами»). Эти функции были систематизированы и представляют собой интерфейс между драйверами и базовой подсистемой ввода-вывода.
Каждый драйвер определенного типа в операционной системе UNIX получает собственный номер, который по сути дела является индексом в массиве специальных структур данных операционной системы -- коммутаторе устройств соответствующего типа. Этот индекс принято также называть старшим номером устройства, хотя на самом деле он относится не к устройству, а к драйверу. Несмотря на наличие трех типов драйверов, в операционной системе используется всего два коммутатора: для блочных и символьных драйверов. Драйверы низкого уровня распределяются между ними по преобладающему типу интерфейса (к какому типу ближе -- в такой массив и заносятся). Каждый элемент коммутатора устройств обязательно содержит адреса (точки входа в драйвер), соответствующие стандартному набору функций интерфейса, которые и вызываются операционной системой для выполнения тех или иных действий над устройством и/или драйвером.
Помимо старшего номера устройства существует еще и младший номер устройства, который передается драйверу в качестве параметра и смысл которого определяется самим драйвером. Например, это может быть номер раздела на жестком диске (partition), доступ к которому должен обеспечить драйвер (надо отметить, что в операционной системе UNIX различные разделы физического носителя информации рассматриваются как различные устройства). В некоторых случаях младший номер устройства может не использоваться, но для единообразия он должен присутствовать. Таким образом, пара драйвер--устройство всегда однозначно определяется в операционной системе заданием пары номеров (старшего и младшего номеров устройства) и типа драйвера (символьный или блочный).
Для связи приложений с драйверами устройств операционная система UNIX использует файловый интерфейс. В числе типов файлов на предыдущем семинаре упоминались специальные файлы устройств. Так вот, каждой тройке тип--драйвер--устройство в файловой системе соответствует специальный файл устройства, который не занимает на диске никаких логических блоков, кроме индексного узла. В качестве атрибутов этого файла помимо обычных атрибутов используются соответствующие старший и младший номера устройства и тип драйвера (тип драйвера определяется по типу файла: ибо есть специальные файлы символьных устройств и специальные файлы блочных устройств, а номера устройств занимают место длины файла, скажем, для регулярных файлов). Когда открывается специальный файл устройства, операционная система, в числе прочих действий, заносит в соответствующий элемент таблицы открытых виртуальных узлов указатель на набор функций интерфейса из соответствующего элемента коммутатора устройств. Теперь при попытке чтения из файла устройства или записи в файл устройства виртуальная файловая система будет транслировать запросы на выполнение этих операций в соответствующие вызовы нужного драйвера.
Мы не будем останавливаться на практическом применении файлового интерфейса для работы с устройствами ввода-вывода, поскольку это выходит за пределы нашего курса, а вместо этого приступим к изложению концепции сигналов в UNIX, тесно связанных с понятиями аппаратного прерывания, исключения и программного прерывания.
Аппаратные прерывания (interrupt), исключения (exception), программные прерывания (trap, software interrupt). Их обработка
В лекции 13 (раздел «Опрос устройств и прерывания. Исключительные ситуации и системные вызовы») уже вводились понятия аппаратного прерывания, исключения и программного прерывания. Кратко напомним сказанное.
После выдачи запроса ввода-вывода у процессора существует два способа узнать о том, что обработка запроса устройством завершена. Первый способ заключается в регулярной проверке процессором бита занятости в регистре состояния контроллера соответствующего устройства (polling). Второй способ заключается в использовании прерываний. При втором способе процессор имеет специальный вход, на который устройства ввода-вывода, используя контроллер прерываний или непосредственно, выставляют сигнал запроса прерывания (interrupt request) при завершении операции ввода-вывода. При наличии такого сигнала процессор после выполнения текущей команды не выполняет следующую, а, сохранив состояние ряда регистров и, возможно, загрузив в часть регистров новые значения, переходит к выполнению команд, расположенных по некоторым фиксированным адресам. После окончания обработки прерывания можно восстановить состояние процессора и продолжить его работу с команды, выполнение которой было отложено.
Аналогичный механизм часто используется при обработке исключительных ситуаций (exception), возникающих при выполнении команды процессором (неправильный адрес в команде, защита памяти, деление на ноль и т. д.). В этом случае процессор не завершает выполнение команды, а поступает, как и при прерывании, сохраняя свое состояние до момента начала ее выполнения.
Этим же механизмом часто пользуются и для реализации так называемых программных прерываний (software interrupt, trap), применяемых, например, для переключения процессора из режима пользователя в режим ядра внутри системных вызовов. Для выполнения действий, аналогичных действиям по обработке прерывания, процессор в этом случае должен выполнить специальную команду.
Необходимо четко представлять себе разницу между этими тремя понятиями, для чего не лишним будет в очередной раз обратиться к лекциям (лекция 13, раздел «Опрос устройств и прерывания. Исключительные ситуации и системные вызовы»).
Как правило, обработку аппаратных прерываний от устройств ввода-вывода производит сама операционная система, не доверяя работу с системными ресурсами процессам пользователя. Обработка же исключительных ситуаций и некоторых программных прерываний вполне может быть возложена на пользовательский процесс через механизм сигналов.
Понятие сигнала. Способы возникновения сигналов и виды их обработки
Сточки зрения пользователя получение процессом сигнала выглядит как возникновение прерывания. Процесс прекращает регулярное исполнение, и управление передается механизму обработки сигнала. По окончании обработки сигнала процесс может возобновить регулярное исполнение. Типы сигналов (их принято задавать номерами, как правило, в диапазоне от 1 до 31 включительно или специальными символьными обозначениями) и способы их возникновения в системе жестко регламентированы.
Процесс может получить сигнал от:
hardware (при возникновении исключительной ситуации);
другого процесса, выполнившего системный вызов передачи сигнала;
операционной системы (при наступлении некоторых событий);
терминала (при нажатии определенной комбинации клавиш);
системы управления заданиями (при выполнении команды kill -- мы рассмотрим ее позже).
Передачу сигналов процессу в случаях его генерации источниками 2, 3 и 5, т. е., в конечном счете, каким-либо другим процессом, можно рассматривать как реализацию в UNIX сигнальных средств связи, о которых рассказывалось в лекции 4.
Существует три варианта реакции процесса на сигнал:
Принудительно проигнорировать сигнал.
Произвести обработку по умолчанию: проигнорировать, остановить процесс (перевести в состояние ожидания до получения другого специального сигнала), либо завершить работу с образованием core файла или без него.
3. Выполнить обработку сигнала, специфицированную пользователем.Изменить реакцию процесса на сигнал можно с помощью специ-альных системных вызовов, которые мы рассмотрим позже. Реакция нанекоторые сигналы не допускает изменения, и они могут быть обработа-ны только по умолчанию. Так, например, сигнал с номером 9 -- SIGKILLобрабатывается только по умолчанию и всегда приводит к завершениюпроцесса.
Важным вопросом при программировании с использованием сигналов является вопрос о сохранении реакции на них при порождении нового процесса или замене его пользовательского контекста. При системном вызове fork () все установленные реакции на сигналы наследуются порожденным процессом.
При системном вызове exec () сохраняются реакции только для тех сигналов, которые игнорировались или обрабатывались по умолчанию.
Получение любого сигнала, который до вызова exec () обрабатывался пользователем, приведет к завершению процесса.
Прежде чем продолжить тему сигналов, нам придется подробнее остановиться на иерархии процессов в операционной системе.
Понятия группы процессов, сеанса, лидера группы, лидера сеанса, управляющего терминала сеанса. Системные вызовы getpgrp(), setpgrpQ, getpgid(), setpgid(), getsid(), setsid()
В лекции 2, раздел «Одноразовые операции», уже говорилось, что все процессы в системе связаны родственными отношениями и образуют генеалогическое дерево или лес из таких деревьев, где в качестве узлов деревьев выступают сами процессы, а связями служат отношения родитель-ребенок. Все эти деревья принято разделять на группы процессов, или семьи (см. рис. 12-13.1).
Группа процессов включает в себя один или более процессов и существует, пока в группе присутствует хотя бы один процесс. Каждый процесс обязательно включен в какую-нибудь группу. При рождении нового процесса он попадает в ту же группу процессов, в которой находится его родитель. Процессы могут мигрировать из группы в группу по своему желанию или по желанию другого процесса (в зависимости от версии UNIX). Многие системные вызовы могут быть применены не к одному конкретному процессу, а ко всем процессам в некоторой группе. Поэтому то, как именно следует объединять процессы в группы, зависит от того, как предполагается их использовать. Чуть позже мы поговорим об использовании групп процессов для передачи сигналов.
В свою очередь, группы процессов объединяются в сеансы, образуя, с родственной точки зрения, некие кланы семей. Понятие сеанса изначально было введено в UNIX для логического объединения групп процессов, созданных в результате каждого входа и последующей работы пользователя в системе. С каждым сеансом, поэтому, может быть связан в системе терминал, называемый управляющим терминалом сеанса, через который обычно и общаются процессы сеанса с пользователем. Сеанс не может иметь более одного управляющего терминала, и один терминал не может быть управляющим для нескольких сеансов. В то же время могут существовать сеансы, вообще не имеющие управляющего терминала.
Каждая группа процессов в системе получает собственный уникальный номер. Узнать этот номер можно с помощью системного вызова getpgid (). Используя его, процесс может узнать номер группы для себя самого или для процесса из своего сеанса. К сожалению, не во всех версиях UNIX присутствует данный системный вызов. Здесь мы сталкиваемся с тяжелым наследием разделения линий UNIX'ob на линию BSD и линию System V, которое будет нас преследовать почти на всем протяжении данной темы. Вместо вызова getpgid () в таких системах существует системный вызов getpgrp (), который возвращает номер группы только для текущего процесса.
Системный вызов деірдісІ() Прототип системного вызова
Ііпсіисіе <зу5/^урез.п>
#ІПСІиСІЄ <иПІ5ІСІ.1ї>
рісЦ: деірдісНрісЦ: ріс!) ; Описание системного вызова
Системний вызов getpgid возвращает идентификатор группы процессов для процесса с идентификатором рій
Узнать номер группы процесс может только для себя самого или для процесса из своего сеанса. При других значениях pid системный вызов возвращает значение -1.
Тип данных рісЦ: является синонимом для одного из целочисленных типов языка С.
Системный вызов getpgrpO Прототип системного вызова
#include <sys/types.h> #include <mistd.h> pid_t getpgrp(void);
Описание системного вызова
Системный вызов getpgrp возвращает идентификатор группы процессов для текущего процесса.
Тип данных pid_t является синонимом для одного из целочисленных типов языка С.
Для перевода процесса в другую группу процессов (возможно, с одновременным ее созданием) применяется системный вызов setpgid(). Перевести в другую группу процесс может либо самого себя (и то не во всякую и не всегда), либо свой процесс-ребенок, который не выполнял системный вызов exec (), т. е. не запускал на выполнение другую программу. При определенных значениях параметров системного вызова создается новая группа процессов с идентификатором, совпадающим с идентификатором переводимого процесса, состоящая первоначально только из одного этого процесса. Новая группа может быть создана только таким способом, поэтому идентификаторы групп в системе уникальны. Переход в другую группу без создания новой группы возможен лишь в пределах одного сеанса.
В некоторых разновидностях UNIX системный вызов setpgidO отсутствует, а вместо него используется системный вызов setpgrp (), способный только создавать новую группу процессов с идентификатором, совпадающим с идентификатором текущего процесса, и переводить в нее текущий процесс. (В ряде систем, где сосуществуют вызовы setpgrp () и setpgid(), например в Solaris, вызов setpgrp () ведет себя иначе -- он аналогичен рассматриваемому ниже вызову setsid().)
Системный вызов setpgidO
Прототип системного вызова
tinclude <sys/types.h>
#include <mistd.h>
int setpgid(pid_t pid, pid_t pgid);
Описание системного вызова
Системный вызов setpgid служит для перевода процесса из одной группы процессов в другую, а также для создания новой группы процессов.
Параметр pid является идентификатором процесса, который нужно перевести в другую группу, а параметр pgid - идентификатором группы процессов, в которую предстоит перевести этот процесс.
Не все комбинации этих параметров разрешены. Перевести в другую группу процесс может либо самого себя (и то не во всякую, и не всегда), либо свой процесс-ребенок, который не выполнял системный вызов exec (), т. е. не запускал на выполнение другую программу.
Если параметр pid равен 0, то считается, что процесс переводит в другую группу самого себя.
Если параметр pgid равен 0, то в Linux считается, что процесс переводится в группу с идентификатором, совпадающим с идентификатором процесса, определяемого первым параметром.
Если значения, определяемые параметрами pid и pgid, равны, то создается новая группа с идентификатором, совпадающим с идентификатором переводимого процесса, состоящая первоначально только из этого процесса. Переход в другую группу без создания новой группы возможен только в пределах одного сеанса.
В новую группу не может перейти процесс, являющийся лидером группы, т.е. процесс, идентификатор которого совпадает с идентификатором его группы.
Тип данных pid_t является синонимом для одного из целочисленных типов языка С.
Возвращаемое значение
Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.
Системный вызов setpgrp()
Прототип системного вызова
#include <sys/types.h> #include <unistd.h> int setpgrp(void) ;
Описание системного вызова
Системный вызов setpgrp служит для перевода текущего процесса во вновь создаваемую группу процессов, идентификатор которой будет совпадать с идентификатором текущего процесса.
Возвращаемое значение
Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.
Процесс, идентификатор которого совпадает с идентификатором его группы, называется лидером группы. Одно из ограничений на применение вызовов setpgid () и setpgrp () состоит в том, что лидер группы не может перебраться в другую группу.
Каждый сеанс в системе также имеет собственный номер. Для того чтобы узнать его, можно воспользоваться системным вызовом gets id (). В разных версиях UNIX на него накладываются различные ограничения. В Linux такие ограничения отсутствуют.
Системный вызов детзісЦ) Прототип системного вызова
#іпс1ис!е <зуз/1урез.п> #іпс1ис!е <ипізЬс1.п> рісП; десзісЦрісЦ: рісі);
Описание системного вызова
Системный вызов деЬрдіс! возвращает идентификатор сеанса для процесса с идентификатором рісі Если параметр рісі равен 0, то возвращается идентификатор сеанса для данного процесса. Тип данных рісЦ: является синонимом для одного из целочисленных типов языка С.
Использование системного вызова setsid() приводит к созданию новой группы, состоящей только из процесса, который его выполнил (он становится лидером новой группы), и нового сеанса, идентификатор которого совпадает с идентификатором процесса, сделавшего вызов. Такой процесс называется лидером сеанса. Этот системный вызов может применять только процесс, не являющийся лидером группы.
Системный вызов ве^сЦ) Прототип системного вызова
Мпс1ис1е <БуБ/1уреБ.П>
#1пс1ис1е <unistd.li>
1п1 SetSІd(VOІd) ;
Описание системного вызова
Этот системный вызов может применять только процесс, не являющийся лидером группы, т. е. процесс, идентификатор которого не совпадает с идентификатором его группы. Использование системного вызова зе1Б1с1 приводит к созданию новой группы, состоящей только из процесса, который его выполнил (он становится лидером новой группы), и нового сеанса, идентификатор которого совпадает с идентификатором процесса, сделавшего вызов.
Возвращаемое значение
Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.
Если сеанс имеет управляющий терминал, то этот терминал обязательно приписывается к некоторой группе процессов, входящей в сеанс. Такая группа процессов называется текущей группой процессов для данного сеанса. Все процессы, входящие в текущую группу процессов, могут совершать операции ввода-вывода, используя управляющий терминал. Все остальные группы процессов сеанса называются фоновыми группами, а процессы, входящие в них -- фоновыми процессами. При попытке ввода-вывода фонового процесса через управляющий терминал этот процесс получит сигналы, которые стандартно приводят к прекращению работы процесса. Передавать управляющий терминал от одной группы процессов к другой может только лидер сеанса. Заметим, что для сеансов, не имеющих управляющего терминала, все процессы являются фоновыми.
При завершении работы процесса -- лидера сеанса все процессы из текущей группы сеанса получают сигнал SIGHUP, который при стандартной обработке приведет к их завершению. Таким образом, после завершения лидера сеанса в нормальной ситуации работу продолжат только фоновые процессы.
Процессы, входящие в текущую группу сеанса, могут получать сигналы, инициируемые нажатием определенных клавиш на терминале -- SIGINT при нажатии клавиш <CTRL> и <С>, и SIGQUIT при нажатии клавиш <CTRL> и <4>. Стандартная реакция на эти сигналы -- завершение процесса (с образованием core файла для сигнала SIGQUIT).
Необходимо ввести еще одно понятие, связанное с процессом, -- эффективный идентификатор пользователя. В материалах первого семинара говорилось о том, что каждый пользователь в системе имеет собственный идентификатор -- UID. Каждый процесс, запущенный пользователем, задействует этот UID для определения своих полномочий. Однако иногда, если у исполняемого файла были выставлены соответствующие атрибуты, процесс может выдать себя за процесс, запущенный другим пользователем. Идентификатор пользователя, от имени которого процесс пользуется полномочиями, и является эффективным идентификатором пользователя для процесса -- EUID. За исключением выше оговоренного случая, эффективный идентификатор пользователя совпадает с идентификатором пользователя, создавшего процесс.
Системный вызов kill() и команда kill()
Из всех перечисленных ранее в разделе «Аппаратные прерывания (interrupt), исключения (exception), программные прерывания (trap, software interrupt). Их обработка» источников сигнала пользователю доступны только два -- команда kill и посылка сигнала процессу с помощью системного вызова kill (). Команда kill обычно используется в следующей форме:
kill [-номер] pid
Здесь pid -- это идентификатор процесса, которому посылается сигнал, а номер -- номер сигнала, который посылается процессу. Послать сигнал (если у вас нет полномочий суперпользователя) можно только процессу, у которого эффективный идентификатор пользователя совпадает с идентификатором пользователя, посылающего сигнал. Если параметр -номер отсутствует, то посылается сигнал SIGTERM, обычно имеющий номер 15, и реакция на него по умолчанию -- завершить работу процесса, который получил сигнал.
Команда kill
Синтаксис команды
kill [-signal] [--] pid kill -1
Описание команды
Команда kill предназначена для передачи сигнала одному или нескольким специфицированным процессам в рамках полномочий пользователя.
Параметр pid определяет процесс или процессы, которым будут доставляться сигналы. Он может быть задан одним из следующих четырех способов:
* Число п > 0 - определяет идентификатор процесса, которому будет доставлен сигнал. ¦ Число 0 - сигнал будет доставлен всем процессам текущей группы для данного управляющего терминала.
Число -1 с предваряющей опцией 1 --' - сигнал будет доставлен (если позволяют полномочия) всем процессам с идентификаторами, большими 1.
Число п < 0, где п не равно -1, с предваряющей опцией ' --1 - сигнал будет доставлен всем процессам из группы процессов, идентификатор которой равен -п.
Параметр -signal определяет тип сигнала, который должен быть доставлен, и может задаваться в числовой или символьной форме, например -9 или -SIGKILL. Если этот параметр опущен, процессам по умолчанию посылается сигнал SIGTERM.
Послать сигнал (не имея полномочий суперпользователя) можно только процессу, у которого эффективный идентификатор пользователя совпадает с идентификатором пользователя, посылающего сигнал.
Опция -1 используется для получения списка сигналов, существующих в системе в символьной и числовой формах.
Во многих операционных системах предусмотрены еще и дополнительные опции для команды kill.
При использовании системного вызова кШ() послать сигнал (не имея полномочий суперпользователя) можно только процессу или процессам, у которых эффективный идентификатор пользователя совпадает с эффективным идентификатором пользователя процесса, посылающего сигнал.
Системный вызов kill() Прототип системного вызова
finclude <sys/types.h>
finclude <signal.h>
int kill(pid_t pid, inc signal);
Описание системного вызова
Системный вызов kill () предназначен для передачи сигнала одному или нескольким специфицированным процессам в рамках полномочий пользователя.
Подобные документы
Основные понятия об операционных системах. Виды современных операционных систем. История развития операционных систем семейства Windows. Характеристики операционных систем семейства Windows. Новые функциональные возможности операционной системы Windows 7.
курсовая работа [60,1 K], добавлен 18.02.2012Понятие виртуальной памяти, ее реализация. Особенности страничной организации по требованию. Этапы обработки ситуации отсутствия страницы в памяти. Стратегии (алгоритмы) замещения страниц. Особенности некоторых операционных систем: Windows NT и Solaris.
презентация [2,2 M], добавлен 24.01.2014Изучение особенностей операционной системы, набора программ, контролирующих работу прикладных программ и системных приложений. Описания архитектуры и программного обеспечения современных операционных систем. Достоинства языка программирования Ассемблер.
презентация [1,3 M], добавлен 22.04.2014Общая характеристика преимуществ взаимодействующих процессов: модульность, ускорение вычислений. Знакомство с основами современных операционных систем. Анализ особенностей использования общего почтового ящика, рассмотрение способов создания и удаления.
презентация [1,6 M], добавлен 24.01.2014Характеристика сущности, назначения, функций операционных систем. Отличительные черты их эволюции. Особенности алгоритмов управления ресурсами. Современные концепции и технологии проектирования операционных систем, требования, предъявляемые к ОС XXI века.
курсовая работа [36,4 K], добавлен 08.01.2011Операционная система - программа, которая загружается при включении компьютера. Способы реализации интерфейса и классификация операционных систем. Организация файловой системы, типы файлов и их наименования. Понятие каталога, атрибуты файловой системы.
реферат [16,6 K], добавлен 25.02.2011Важность операционной системы для мобильных устройств. Популярность операционных систем. Доля LINUX на рынке операционных систем. История OS Symbian, BlackBerry OS, Palm OS. Отличия смартфона от обычного мобильного телефона. Учет ограничений по памяти.
презентация [477,3 K], добавлен 01.12.2015Основные понятия операционных систем. Современное оборудование компьютера. Преимущества и недостатки операционной системы Linux. Функциональные возможности операционной системы Knoppix. Сравнительная характеристика операционных систем Linux и Knoppix.
реферат [1,5 M], добавлен 17.12.2014Основные понятия операционных систем. Синхронизация и критические области. Сигналы и взаимодействие между процессами. Управление памятью. Драйверы устройств. Особенности современных операционных систем. Центральный процессор, микросхемы часов и таймеров.
учебное пособие [1,2 M], добавлен 24.01.2014Использование операционных систем Microsoft Windows. Разработка операционной системы Windows 1.0. Возможности и характеристика последующих версий. Выпуск пользовательских операционных систем компании, доработки и нововведения, версии Windows XP и Vista.
реферат [23,3 K], добавлен 10.01.2012