Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Пример передачи дескриптора
Теперь мы представим пример передачи дескриптора. Мы напишем программу под названием 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 ");
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
, эта простая программа всего лишь скопирует файл в стандартный поток вывода.
Функция my_open
, показанная в листинге 15.8, должна выглядеть для вызывающего процесса как обычная функция Unix open
. Она получает два аргумента — полное имя и режим открытия (например, O_RDONLY
обозначает, что файл доступен только для чтения), открывает файл и возвращает дескриптор.
Листинг 15.8. Функция my_open: открытие файла и возвращение дескриптора
//unixdomain/myopen.c
1 #include "unp.h"
2 int
3 my_open(const char *pathname, int mode)
4 {
5 int fd, sockfd[2], status;
6 pid_t childpid;
7 char c, argsockfd[10], argmode[10];
8 Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
9 if ((childpid = Fork()) == 0) { /* дочерний процесс */
10 Close(sockfd[0]);
11 snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
12 snprintf(argmode, sizeof(argmode), "%d", mode);
13 execl("./openfile", "openfile", argsockfd, pathname, argmode,
14 (char*)NULL);
15 err_sys("execl error");
16 }
17 /* родительский процесс - ожидание завершения дочернего процесса */
18 Close(sockfd[1]); /* закрываем конец, который мы не используем */
19 Waitpid(childpid, &status, 0);
20 if (WIFEXITED(status) == 0)
21 err_quit("child did not terminate");
22 if ((status = WEXITSTATUS(status)) == 0)
23 Read_fd(sockfd[0], &c, 1, &fd);
24 else {
25 errno = status; /* установка значения errno в статус дочернего
процесса */
26 fd = -1;
27 }
28 Close(sockfd[0]);
29 return (fd);
30 }
8
Функция socketpair
создает потоковый канал. Возвращаются два дескриптора: sockfd[0]
и sockfd[1]
. Это состояние, которое мы показали на рис. 15.1.
9-16
Вызывается функция fork
, после чего дочерний процесс закрывает один конец потокового канала. Номер дескриптора другого конца потокового канала помещается в массив argsockfd
, а режим открытия помещается в массив argmode
. Мы вызываем функцию snprintf
, поскольку аргументы функции exec должны быть символьными строками. Выполняется программа openfile
. Функция execl
возвращает управление только в том случае, если она встретит ошибку. При удачном выполнении начинает выполняться функция main
программы openfile
.
17-22
Родительский процесс закрывает другой конец потокового канала и вызывает функцию waitpid
для ожидания завершения дочернего процесса. Статус завершения дочернего процесса возвращается в переменной status
, и сначала мы проверяем, что программа завершилась нормально (то есть не была завершена из-за возникновения какого-либо сигнала). Затем макрос WEXITSTATUS
преобразует статус завершения в статус выхода, значение которого должно быть между 0 и 255. Мы вскоре увидим, что если при открытии необходимого файла программой openfile
происходит ошибка, то эта программа завершается, причем статус ее завершения равен соответствующему значению переменной errno
.
23
Наша функция read_fd
, которую мы показываем в следующем листинге, получает дескриптор потокового канала. Кроме получения дескриптора мы считываем 1 байт данных, но ничего с этими данными не делаем.
Интервал:
Закладка: