Каталоги похожи на обычные файлы в одном отношении; система
представляет
информацию в каталоге набором байтов, но эта информация включает в себя име-
на файлов в каталоге в объявленном формате для того, чтобы операционная сис-
тема и программы, такие как ls (выводит список имен и атрибутов
файлов),
могли их обнаружить.
Права доступа к файлу регулируются установкой специальных битов разреше-
ния доступа, связанных с файлом. Устанавливая биты разрешения доступа,
можно
независимо управлять выдачей разрешений на чтение, запись и выполнение
для
трех категорий пользователей: владельца файла, группового пользователя
и
прочих. Пользователи могут создавать файлы, если разрешен доступ к
каталогу.
Вновь созданные файлы становятся листьями в древовидной структуре
файловой
системы.
Для пользователя система UNIX трактует устройства так, как если бы
они
были файлами. Устройства, для которых назначены специальные файлы
устройств,
становятся вершинами в структуре файловой системы. Обращение программ к уст-
ройствам имеет тот же самый синтаксис, что и обращение к обычным файлам; се-
мантика операций чтения и записи по отношению к устройствам в большой степе-
ни совпадает с семантикой операций чтения и записи обычных файлов.
Способ
защиты устройств совпадает со способом защиты обычных файлов: путем соответ-
ствующей установки битов разрешения доступа к ним (файлам). Поскольку
имена
устройств выглядят так же, как и имена обычных файлов, и поскольку над
устройствами и над обычными файлами выполняются одни и те же операции,
большинству программ нет необходимости различать внутри себя типы
обрабатываемых файлов.
Например, рассмотрим программу на языке Си (Рисунок 1.3), в которой соз-
дается новая копия существующего файла. Предположим, что исполняемая
версия
программы имеет наименование copy. Для запуска программы пользователь
вводит
с терминала:
copy oldfile newfile
где oldfile - имя существующего файла, а newfile - имя создаваемого
файла.
Система выполняет процедуру main, присваивая аргументу argc значение
количест-ва параметров в списке argv, а каждому элементу массива argv
значение парамет-ра, сообщенного пользователем. В приведенном примере argc
имеет значение 3, элемент argv[0] содержит строку символов "copy" (имя
программы условно являет-ся нулевым параметром), argv[1] - строку
символов "oldfile", а argv[2] - строку символов "newfile". Затем программа
проверяет, правильное ли количество параметров было указано при ее
запуске. Если это так, запускается операция open (открыть) для файла
oldfile с параметром "read-only" (только для чтения), в случае успешного
выполнения которой запускается операция creat (открыть) для файла
newfile. Режим доступа к вновь созданному файлу описывается числом 0666 (в
восьмиричном коде), что означает разрешение доступа к файлу для чтения и
записи для всех пользователей. Все обращения к операционной системе в
случае неудачи возвращают код -1; если же неудачно завершаются операции
open и creat, программа выдает сообщение и запускает операцию exit
(выйти) с возвращением кода состояния, равного 1, завершая свою работу и
указывая на возникновение ошибки.
Операции open и creat возвращают целое значение, являющееся
дескриптором
файла и используемое программой в последующих ссылках на файлы. После
этого
программа вызывает подпрограмму copy, выполняющую в цикле операцию read (чи-
тать), по которой производится чтение в буфер порции символов из
существующего файла, и операцию write (писать) для записи информации в
новый файл.Операция read каждый раз возвращает количество прочитанных
байтов (0 – если достигнут конец файла). Цикл завершается, если достигнут
конец файла или если произошла ошибка при выполнении операции read
(отсутствует контроль возникновения ошибок при выполнении операции
write). Затем управление из подпрограммы copy возвращается в основную
программу и запускается операция exit с кодом состояния 0 в качестве
параметра, что указывает на успешное завершение выполнения программы.
Программа копирует любые файлы, указанные при ее вызове в качестве
аргумен-тов, при условии, что разрешено открытие существующего файла и
создание нового файла. Файл может включать в себя как текст, который может
быть выведен на печатающее устройство, например, исходный текст программы,
так и символы, не выводимые на печать, даже саму программу. Таким образом,
оба вызова:
copy copy.c newcopy.c
copy copy newcopy
являются допустимыми. Существующий файл также может быть каталогом.
Например, по вызову:
copy . dircontents
копируется содержимое текущего каталога, обозначенного символом ".", в обыч-
ный файл "dircontents"; информация в новом файле совпадает, вплоть до каждо-
го байта, с содержимым каталога, только этот файл обычного типа (для созда-
ния нового каталога предназначена операция mknod). Наконец, любой из
файлов
может быть файлом устройства. Например, программа, вызванная следующим обра-
зом:
#include
char buffer[2048];
int version = 1;
main(argc,argv)
int argc;
char *argv[];
{
int fdold,fdnew;
if (argc != 3)
{
printf("need 2 arguments for copy program\n);
exit(1);
}
fdold = open(argv[1],O_RDONLY); /* открыть исходный файл только
для чтения */
if (fdold == -1)
{
printf("cannot open file %s\n",argv[1]);
exit(1);
}
fdnew = creat(argv[2],0666); /* создать новый файл с
разрешением чтения и записи для всех
пользователей */
if (fdnew == -1)
{
printf("cannot create file %s\n",argv[2]);
exit(1);
}
copy(fdold,fdnew);
exit(0);
}
copy(old,new)
int old,new;
{
int count;
while ((count = read(old,buffer,sizeof(buffer))) > 0)
write(new,buffer,count);
}
Рисунок 1.3. Программа копирования файла
copy /dev/tty terminalread
читает символы, вводимые с терминала (файл /dev/tty соответствует
терминалу
пользователя), и копирует их в файл terminalread, завершая работу только
в
том случае, если пользователь нажмет. Похожая форма запуска
программы:
copy /dev/tty /dev/tty
вызывает чтение символов с терминала и их копирование обратно на терминал.
3.2 Среда выполнения процессов
Программой называется исполняемый файл, а процессом называется последо-
вательность операций программы или часть программы при ее выполнении. В сис-
теме UNIX может одновременно выполняться множество процессов (эту особен-
ность иногда называют мультипрограммированием или многозадачным
режимом),
при чем их число логически не ограничивается, и множество частей
программы
(такой как copy) может одновременно находиться в системе. Различные
системные операции позволяют процессам порождать новые процессы, завершают
процессы, синхронизируют выполнение этапов процесса и управляют реакцией
на наступле-ние различных событий. Благодаря различным обращениям к
операционной
системе, процессы выполняются независимо друг от друга.
Например, процесс, выполняющийся в программе, приведенной на
Рисунке
1.4, запускает операцию fork, чтобы породить новый процесс. Новый
процесс,
именуемый порожденным процессом, получает значение кода завершения
операции
fork, равное 0, и активизирует операцию execl, которая выполняет
программу
copy (Рисунок 1.3). Операция execl загружает файл "copy", который предполо-
жительно находится в текущем каталоге, в адресное пространство
порожденного
процесса и запускает программу с параметрами, полученными от пользователя.
В
случае успешного выполнения операции execl управление в вызвавший ее
процесс
не возвращается, поскольку процесс выполняется в новом адресном
пространстве. Тем временем, процесс, запустивший операцию fork
(родительский процесс), получает ненулевое значение кода завершения
операции, вызывает операцию wait, которая приостанавливает его выполнение
до тех пор, пока не закончится выполнение программы copy, и завершается
(каждая программа имеет выход в конце главной процедуры, после которой
располагаются программы стандартных библиотек Си, подключаемые в
процессе компиляции). Например, если исполняемая программа называется run,
пользователь запускает ее следующим образом:
main(argc,argv)
int argc;
char *argv[];
{
/* предусмотрено 2 аргумента: исходный файл и новый файл */
if (fork() == 0)
execl("copy","copy",argv[1],argv[2],0);
wait((int *)0)
printf("copy done\n");
}
Рисунок 1.4. Программа порождения нового процесса, выполняющего копиро-
вание файлов
run oldfile newfile
Процесс выполняет копирование файла с именем "oldfile" в файл с
именем
"newfile" и выводит сообщение. Хотя данная программа мало что добавила
к
программе "copy", в ней появились четыре основных обращения к
операционной
системе, управляющие выполнением процессов: fork, exec, wait и exit.
Вообще использование обращений к операционной системе дает
возможность
пользователю создавать программы, выполняющие сложные действия, и как следс-
твие, ядро операционной системы UNIX не включает в себя многие функции, яв-