Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

2. Один процесс открывает дескриптор при помощи вызова любой из функций Unix, возвращающей дескриптор, например

open
,
piре
,
mkfifo
,
socket
или
accept
. От одного процесса к другому можно передать дескриптор любоготипа, поэтому мы называем эту технологию «передачей дескриптора», а не «передачей дескриптора файла».

3. Отправляющий процесс строит структуру

msghdr
(см. раздел 14.5), содержащую дескриптор, который нужно передать. В POSIX определено, что дескриптор должен отправляться как вспомогательные данные (элемент
msg_control
структуры
msghdr
, см. раздел 14.6), но более старые реализации используют элемент
msg_accrights
. Отправляющий процесс вызывает функцию
sendmsg
для отправки дескриптора через доменный сокет Unix, созданный на шаге 1. На этом этапе мы говорим, что дескриптор находится «в полете». Даже если отправляющий процесс закроет дескриптор после вызова функции
sendmsg
, но до вызова принимающим процессом функции
recvmsg
, дескриптор останется открытым для принимающего процесса. Отправка дескриптора увеличивает счетчик ссылок дескриптора на единицу.

4. Принимающий процесс вызывает функцию

recvmsg
для получения дескриптора через доменный сокет Unix, созданный на шаге 1. Номер дескриптора в принимающем процессе может отличаться от номера дескриптора в отправляющем процессе. Передача дескриптора — это не передача номера дескриптора. Этот процесс включает создание нового дескриптора в принимающем процессе, который ссылается на ту же запись таблицы файлов в ядре, что и дескриптор, отправленный отправляющим процессом.

Клиент и сервер должны располагать некоторым протоколом уровня приложения, с тем чтобы получатель дескриптора имел информацию о времени его появления. Если получатель вызывает функцию

recvmsg
, не выделив места в памяти для получения дескриптора, и дескриптор передается как готовый для чтения, то передаваемый дескриптор закрывается [128, с. 518]. Кроме того, нужно избегать установки флага
MSG_PEEK
в функции
recvmsg
, если предполагается получение дескриптора, поскольку в этом случае результат непредсказуем.

Пример передачи дескриптора

Теперь мы представим пример передачи дескриптора. Мы напишем программу под названием

mycat
, которой в качестве аргумента командной строки передается полное имя файла. Эта программа открывает файл и копирует его в стандартный поток вывода. Но вместо вызова обычной функции Unix
open
мы вызываем нашу собственную функцию
my_open
. Эта функция создает потоковый канал и вызывает функции
fork
и
exec
для запуска другой программы, открывающей нужный файл. Эта программа должна затем передать дескриптор обратно родительскому процессу по потоковому каналу.

На рис. 15.1 показан первый шаг: наша программа

mycat
после создания потокового канала при помощи вызова функции
socketpair
. Мы обозначили два дескриптора, возвращаемых функцией
socketpair
, как
[0]
и
[1]
.

Рис. 15.1. Программа mycat после создания потокового канала при использовании функции socketpair

Затем процесс взывает функцию

fork
, и дочерний процесс вызывает функцию
exec
для выполнения программы
openfile
. Родительский процесс закрывает дескриптор
[1]
, а дочерний процесс закрывает дескриптор
[0]
. (Нет разницы, на каком конце потокового канала происходит закрытие. Дочерний процесс мог бы закрыть
[1]
, а родительский —
[0]
.) При этом получается схема, показанная на рис. 15.2.

Рис. 15.2. Программа mycat после запуска программы openfile

Родительский процесс должен передать программе

openfile
три фрагмента информации: полное имя открываемого файла, режим открытия (только чтение чтение и запись или только запись) и номер дескриптора, соответствующий его концу потокового канала (который мы обозначили
[1]
). Мы выбрали такой способ передачи этих трех элементов, как ввод аргументов командной строки при вызове функции
exec
. Альтернативным способом будет отправка этих элементов в качестве данных по потоковому каналу. Программа отправляет обратно открытый дескриптор по потоковому каналу и завершается. Статус выхода программы сообщает родительскому процессу, смог ли файл открыться, и если нет, то какого типа ошибка произошла.

Преимущество выполнения дополнительной программы для открытия файла заключается в том, что за счет приравнивания привилегий пользователя к привилегиям владельца файла мы получаем возможность открывать те файлы, которые не имеем права открывать в обычной ситуации. Эта программа позволяет расширить концепцию обычных прав доступа Unix (пользователь, группа и все остальные) и включить любые формы проверки прав доступа. Мы начнем с программы

mycat
, показанной в листинге 15.7.

Листинг 15.7. Программа mycat: копирование файла в стандартный поток вывода

//unixdomain/mycat.c

1 #include "unp.h"

2 int my_open(const char*, int);

3 int

4 main(int argc, char **argv)

5 {

6 int fd, n;

7 char buff[BUFFSIZE];

8 if (argc != 2)

9 err_quit("usage: mycat <pathname>");

10 if ((fd = my_open(argv[1], O_RDONLY)) < 0)

11 err_sys("cannot open %s", argv[1]);

12 while ((n = Read(fd, buff, BUFFSIZE)) > 0)

13 Write(STDOUT_FILENO, buff, n);

14 exit(0);

15 }

Если мы заменим вызов функции

my_open
вызовом функции
open
, эта простая программа всего лишь скопирует файл в стандартный поток вывода.

  • Читать дальше
  • 1
  • ...
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: