KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Андрей Робачевский - Операционная система UNIX

Андрей Робачевский - Операционная система UNIX

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Андрей Робачевский, "Операционная система UNIX" бесплатно, без регистрации.
Перейти на страницу:

Символическая связь позволяет косвенно адресовать другой файл файловой системы. Системный вызов symlink(2) служит для создания символической связи. Этим вызовом, кстати, пользуется команда ln -s.

#include <unistd.h>


int symlink (const char *name, const char *synmame);

После создания символической связи, доступ к целевому файлу name может осуществляться с помощью symname. При этом, функция open(2), принимая в качестве аргумента имя символической связи, на самом деле открывает целевой файл. Такая особенность называется следованием символической связи. Не все системные вызовы обладают этим свойством. Например, системный вызов unlink(2), удаляющий запись в каталоге, действует только на саму символическую связь. В противном случае, мы не имели бы возможности удалить ее. В табл. 2.11 показано, как работают с символическими связями различные системные вызовы.


Таблица 2.11. Интерпретация символической связи различными системными вызовами

Системный вызов Следует символической связи Не следует символической связи access(2) + chdir(2) + chmod(2) + chown(2) + lchown(2) + creat(2) + exec(2) + link(2) + mkdir(2) + mknod(2) + open(2) + readlink(2) + rename(2) + stat(2) + lstat(2) + unlink(2) +

Для чтения содержимого файла — символической связи используется системный вызов readlink(2):

#include <unistd.h>


int readlink(const char *path, void *buf, size_t bufsiz);

Аргумент path содержит имя символической связи. В буфере buf размером bufsiz возвращается содержимое файла — символической связи.

Для иллюстрации к вышеприведенным рассуждениям приведем пример программы, которая сначала выводит содержимое символической связи, а затем — целевого файла, пользуясь в обоих случаях символическим именем:

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>


#define BUFSZ 256


/* В качестве аргумента программа принимает имя

   символической связи */

main(int argc, char *argv[]) {

 char buf[BUFSZ+1];

 int nread, fd;

 /* Прочитаем содержимое самой символической связи */

 printf("Читаем символическую связьn");

 nread = readlink(argv[1], buf, BUFSZ);

 if (nread < 0) {

  perror("readlink");

  exit(1);

 }

 /* readlink не завершает строку '' */

 printf("Символическая связь:n %sn", buf);

 /* Теперь прочитаем содержимое целевого файла */

 printf("Читаем целевой файлn");

 fd = open(argv[1], O_RDONLY);

 if (fd < 0) {

  perror("open");

  exit(2);

 }

 nread = read(fd, buf, BUFSIZ);

 if (nread < 0) {

  perror("read");

  exit(3);

 }

 buf[nread] = '';

 printf("Целевой файл:n %sn", buf);

 close(fd);

 exit(0);

}

Перед тем как запустить программу, создадим символическую связь с файлом unix0.txt:

$ ln -s unix0.txt symlink.txt

$ ls -l

lrwxrwxrwx 1 andy user  10 Jan 6 09:54 symlink.txt -> unix0.txt

-rw-r--r-- 1 andy user 498 Jan 6 09:53 unix0.txt

$ a.out symlink.txt

Читаем символическую связь

Символическая связь:

unix0.txt

Читаем целевой файл

Целевой файл:

Начиная с 1975 года фирма AT&T начала предоставлять лицензии на

использование операционной системы как научно-образовательным

учреждениям, так и коммерческим организациям. Поскольку основная

часть системы поставлялась в исходных текстах, написанных на

языке С, опытным программистам не требовалось детальной

документации, чтобы разобраться в архитектуре UNIX. С ростом

популярности микропроцессоров

...

Файлы, отображаемые в памяти

Системный вызов mmap(2) предоставляет механизм доступа к файлам, альтернативный вызовам read(2) и write(2). С помощью этого вызова процесс имеет возможность отобразить участки файла в собственное адресное пространство. После этого данные файла могут быть получены или записаны путем чтения или записи в память. Функция mmap(2) определяется следующим образом:

#include <sys/types.h>

#include <sys/mman.h>


caddr_t mmap(caddr_t addr, size_t len, int prot,

 int flags, int fildes, off_t off);

Этот вызов задает отображение len байтов файла с дескриптором fildes, начиная со смещения off, в область памяти со стартовым адресом addr. Разумеется, перед вызовом mmap(2) файл должен быть открыт с помощью функции open(2). Аргумент prot определяет права доступа к области памяти, которые должны соответствовать правам доступа к файлу, указанным в системном вызове open(2). В табл. 2.12 приведены возможные значения аргумента prot и соответствующие им права доступа к файлу. Возможно логическое объединение отдельных значений prot. Так значение PROT_READ | PROT_WRITE соответствует доступу O_RDWR к файлу.


Таблица 2.12. Права доступа к области памяти

Значение аргумента prot Описание Права доступа к файлу PROT_READ Область доступна для чтения r PROT_WRITE Область доступна для записи w PROT_EXEC Область доступна для исполнения x PROT_NONE Область недоступна -

Обычно значение addr задается равным 0, что позволяет операционной системе самостоятельно выбрать виртуальный адрес начала области отображения. В любом случае, при успешном завершении возвращаемое системным вызовом значение определяет действительное расположение области памяти.

Операционная система округляет значение len до следующей страницы виртуальной памяти.[19] Например, если размер файла 96 байтов, а размер страницы 4 Кбайт, то система все равно выделит область памяти размером 4096 байтов. При этом 96 байтов займут собственно данные файла, а остальные 4000 байтов будут заполнены нулями. Процесс может модифицировать и оставшиеся 4000 байтов, но эти изменения не отразятся на содержимом файла. При обращении к участку памяти, лежащему за пределами файла, ядро отправит процессу сигнал SIGBUS[20]. Несмотря на то что область памяти может превышать фактический размер файла, процесс не имеет возможности изменить его размер.

Использование права на исполнение (prot = PROT_EXEC) позволяет процессу определить собственный механизм загрузки кода. В частности, такой подход используется редактором динамических связей при загрузке динамических библиотек, когда библиотека отображается в адресное пространство процесса. Значение PROT_NONE позволяет приложению определить собственные механизмы контроля доступа к разделяемым объектам (например, к разделяемой памяти), разрешая или запрещая доступ к области памяти.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*