Морис Бах - Архитектура операционной системы UNIX
Программа на Рисунке 5.18 иллюстрирует искусственное использование каналов. Процесс создает канал и входит в бесконечный цикл, записывая в канал строку символов «hello» и считывая ее из канала. Ядру не нужно ни знать о том, что процесс, ведущий запись в канал, является и процессом, считывающим из канала, ни проявлять по этому поводу какое-либо беспокойство.
char string[] = "hello";
main() {
char buf[1024];
char *cp1,*cp2;
int fds[2];
cp1 = string;
cp2 = buf;
while(*cp1) *cp2++ = *cp1++;
pipe(fds);
for (;;) {
write(fds[1], buf, 6);
read(fds[0], buf, 6);
}
}
Рисунок 5.18. Чтение из канала и запись в канал
Процесс, выполняющий программу, которая приведена на Рисунке 5.19, создает поименованный канал с именем «fifo». Если этот процесс запущен с указанием второго (формального) аргумента, он постоянно записывает в канал строку символов «hello»; будучи запущен без второго аргумента, он ведет чтение из поименованного канала. Два процесса запускаются по одной и той же программе, тайно договорившись взаимодействовать между собой через поименованный канал «fifo», но им нет необходимости быть родственными процессами. Другие пользователи могут выполнять программу и участвовать в диалоге (или мешать ему).
#include ‹fcntl.h›
char string[] = "hello";
main(argc, argv)
int argc;
char *argv[];
{
int fd;
char buf[256];
/* создание поименованного канала с разрешением чтения и записи для всех пользователей */
mknod("fifo", 010777, 0);
if (argc == 2) fd = open("fifo", O_WRONLY);
else fd = open("fifo", O_RDONLY);
for (;;)
if (argc == 2) write(fd, string, 6);
else read(fd, buf, 6);
}
Рисунок 5.19. Чтение и запись в поименованный канал
5.13 DUР
Системная функция dup копирует дескриптор файла в первое свободное место в таблице пользовательских дескрипторов файла, возвращая новый дескриптор пользователю. Она действует для всех типов файла. Синтаксис вызова функции:
newfd = dup(fd);
где fd — дескриптор файла, копируемый функцией, а newfd — новый дескриптор, ссылающийся на файл. Поскольку функция dup дублирует дескриптор файла, она увеличивает значение счетчика в соответствующей записи таблицы файлов — записи, на которую указывают связанные с ней точки входа в таблице файловых дескрипторов, которых теперь стало на одну больше. Например, обзор структур данных, изображенных на Рисунке 5.20, показывает, что процесс вызывает следующую последовательность функций: он открывает (open) файл с именем «/etc/passwd» (файловый дескриптор 3), затем открывает файл с именем «local» (файловый дескриптор 4), снова файл с именем «/etc/passwd» (файловый дескриптор 5) и, наконец, дублирует (dup) файловый дескриптор 3, возвращая дескриптор 6.
Рисунок 5.20. Структуры данных после выполнения функции dup
Возможно, dup — функция, не отличающаяся изяществом, поскольку она предполагает, что пользователь знает о том, что система возвратит свободную точку входа в таблице пользовательских дескрипторов, имеющую наименьший номер. Однако, она служит важной задаче конструирования сложных программ из более простых конструкционных блоков, что, в частности, имеет место при создании конвейеров, составленных из командных процессоров.
Рассмотрим программу, приведенную на Рисунке 5.21. В переменной i хранится дескриптор файла, возвращаемый в результате открытия файла «/etc/passwd», а в переменной j — дескриптор файла, возвращаемый системой в результате дублирования дескриптора i с помощью функции dup. В адресном пространстве процесса оба пользовательских дескриптора, представленные переменными i и j, ссылаются на одну и ту же запись в таблице файлов и поэтому используют одно и то же значение смещения внутри файла. Таким образом, первые два вызова процессом функции read реализуют последовательное считывание данных, и в буферах buf1 и buf2 будут располагаться разные данные. Совсем другой результат получается, когда процесс открывает один и тот же файл дважды и читает дважды одни и те же данные (раздел 5.2). Процесс может освободить с помощью функции close любой из файловых дескрипторов по своему желанию, и ввод-вывод получит нормальное продолжение по другому дескриптору, как показано на примере. В частности, процесс может «закрыть» дескриптор файла стандартного вывода (файловый дескриптор 1), снять с него копию, имеющую то же значение, и затем рассматривать новый файл в качестве файла стандартного вывода. В главе 7 будет представлен более реалистический пример использования функций pipe и dup при описании особенностей реализации командного процессора.
#include ‹fcntl.h›
main() {
int i, j;
char buf1[512], buf2[512];
i = open("/etc/passwd", O_RDONLY);
j = dup(i);
read(i, buf1, sizeof(buf1));
read(j, buf2, sizeof(buf2));
close(i);
read(j, buf2, sizeof(buf2));
}
Рисунок 5.21. Программа на языке Си, иллюстрирующая использование функции dup
5.14 МОНТИРОВАНИЕ И ДЕМОНТИРОВАНИЕ ФАЙЛОВЫХ СИСТЕМ
Физический диск состоит из нескольких логических разделов, на которые он разбит дисковым драйвером, причем каждому разделу соответствует файл устройства, имеющий определенное имя. Процессы обращаются к данным раздела, открывая соответствующий файл устройства и затем ведя запись и чтение из этого «файла», представляя его себе в виде последовательности дисковых блоков. Это взаимодействие во всех деталях рассматривается в главе 10. Раздел диска может содержать логическую файловую систему, состоящую из блока начальной загрузки, суперблока, списка индексов и информационных блоков (см. главу 2). Системная функция mount (монтировать) связывает файловую систему из указанного раздела на диске с существующей иерархией файловых систем, а функция umount (демонтировать) выключает файловую систему из иерархии. Функция mount, таким образом, дает пользователям возможность обращаться к данным в дисковом разделе как к файловой системе, а не как к последовательности дисковых блоков.
Синтаксис вызова функции mount:
mount(special pathname, directory pathname, options);
где special pathname — имя специального файла устройства, соответствующего дисковому разделу с монтируемой файловой системой, directory pathname — каталог в существующей иерархии, где будет монтироваться файловая система (другими словами, точка или место монтирования), а options указывает, следует ли монтировать файловую систему «только для чтения» (при этом не будут выполняться такие функции, как write и creat, которые производят запись в файловую систему). Например, если процесс вызывает функцию mount следующим образом:
mount("/dev/dsk1", "/usr', 0);
ядро присоединяет файловую систему, находящуюся в дисковом разделе с именем «/dev/dsk1», к каталогу «/usr» в существующем дереве файловых систем (см. Рисунок 5.22). Файл «/dev/dsk1» является блочным специальным файлом, т. е. он носит имя устройства блочного типа, обычно имя раздела на диске. Ядро предполагает, что раздел на диске с указанным именем содержит файловую систему с суперблоком, списком индексов и корневым индексом. После выполнения функции mount к корню смонтированной файловой системы можно обращаться по имени «/usr». Процессы могут обращаться к файлам в монтированной файловой системе и игнорировать тот факт, что система может отсоединяться. Только системная функция link контролирует файловую систему, так как в версии V не разрешаются связи между файлами, принадлежащими разным файловым системам (см. раздел 5.15).
Рисунок 5.22. Дерево файловых систем до и после выполнения функции mount
Ядро поддерживает таблицу монтирования с записями о каждой монтированной файловой системе. В каждой записи таблицы монтирования содержатся:
• номер устройства, идентифицирующий монтированную файловую систему (упомянутый выше логический номер файловой системы);
• указатель на буфер, где находится суперблок файловой системы;
• указатель на корневой индекс монтированной файловой системы («/» для файловой системы с именем «/dev/dsk1» на Рисунке 5.22);
• указатель на индекс каталога, ставшего точкой монтирования (на Рисунке 5.22 это каталог «usr», принадлежащий корневой файловой системе).
Связь индекса точки монтирования с корневым индексом монтированной файловой системы, возникшая в результате выполнения системной функции mount, дает ядру возможность легко двигаться по иерархии файловых систем без получения от пользователей дополнительных сведений.
алгоритм mount
входная информация: