Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

#include <unistd.h>

int dup2(int oldfd, int newfd);

Если

newfd
ссылается на уже открытый дескриптор, то он закрывается. Если вызов завершен успешно, он возвращает новый файловый дескриптор и
newfd
ссылается на тот же файл, что
oldfd
. Системный вызов
fcntl
представляет почти ту же функциональность командой
F_DUPFD
. Первый аргумент —
fd
— это уже открытый файловый дескриптор. Новый файловый дескриптор — это первый доступный дескриптор, равный или больший, чем значение последнего аргумента
fcntl
. (В этом состоит отличие
от работы
dup2
.) Вы можете реализовать
dup2
через
fcntl
следующим образом.

int dup2(int oldfd, int newfd) {

 close(newfd); /* ensure new fd is available */

 return fcntl(oldfd, F_DUPFD, newfd);

}

Создание двух файловых дескрипторов, ссылающихся на один и тот же файл — это не то же самое, что открытие файла дважды. Почти все атрибуты дублированных дескрипторов разделяются: они разделяют текущую позицию, режим доступа и блокировки. (Все это записывается в файловой структуре [50] , которая создается при каждом открытии файла. Файловый дескриптор ссылается на файловую структуру, и дескриптор, возвращенный

dup
, ссылается на одну и ту же структуру.) Единственный атрибут, который может независимо управляться в этих двух дескрипторах — это состояние "закрыть при выполнении". После того, как процесс вызывает
fork
, то файлы, открытые в родительском процессе, наследуются дочерним, и эти пары файловых дескрипторов (один в родительском процессе, другой — в дочернем) ведут себя так, будто файловые дескрипторы были дублированы с текущей позицией и другими разделенными атрибутами [51] .

50

В зависимости от операционной системы, файловые структуры также известны как позиции в таблице файлов или объекты открытых файлов.

51

Файловый дескриптор в каждом процессе ссылается на одну и ту же файловую структуру.

11.6. Создание неименованных каналов

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

Оболочки применяют неименованные каналы для выполнения команд вроде

ls | head
. Процесс
ls
пишет в тот канал, из которого
head
читает свой ввод, выдавая ожидаемый пользователем результат.

Создание неименованного канала выполняется по двум файловым дескрипторам, один из которых доступен только для чтения, а второй — только для записи.

#include <unistd.h>

int pipe(int fds[2]);

Единственный параметр-массив включает два файловых дескриптора —

fd[0]
для чтения и
fd[1]
для записи.

11.7. Добавление перенаправления для ladsh

Теперь, когда мы рассмотрели основные манипуляции с файлами, мы можем научить

ladsh
перенаправлению ввода и вывода через файлы и каналы.
ladsh2.с
, который мы представим здесь, работает с каналами (описанными символом
|
в командах
ladsh
, как это делается в большинстве командных оболочек) и перенаправление ввода и вывода в файловые дескрипторы. Мы покажем только модифицированные части кода здесь — полный исходный текст
ladsh2.с
доступен по упомянутым в начале книги адресам. Изменения
в
parseCommand
— это простое упражнение по разбору строк, поэтому мы не будем надоедать дискуссией об этом.

11.7.1. Структуры данных

Хотя код в

ladsh1.с
поддерживает концепцию задания как множества процессов (предположительно, объединенных вместе каналами), он не предоставляет способа указания того, какие файлы использовать для ввода и вывода. Чтобы позволить это, добавляются новые структуры данных и модифицируются существующие.

24: REDIRECT_APPEND};

25:

26: struct redirectionSpecifier {

27: enum redirectionTypetype; /* тип перенаправления */

28: int fd; /*перенаправляемый файловый дескриптор*/

29: char * filename; /* файл для перенаправления fd */

30: };

31:

32: struct childProgram {

33: pid_t pid; /* 0 если завершен */

34: char **argv; /* имя программы и аргументы */

35: int numRedirections; /* элементы в массиве перенаправлений */

36: struct redirectionSpecifier *redirections; /* перенаправления ввода-вывода*/

37: } ;

Структура

struct redirectionSpecifier
сообщает
ladsh2.с
о том, как установить отдельный файловый дескриптор. Она содержит
enum redirectionTypetype
, который указывает, является ли это перенаправление перенаправлением ввода, перенаправлением вывода, который должен быть добавлен к существующему файлу, либо перенаправлением вывода, которое заменяет существующий файл. Она также включает перенаправляемый файловый дескриптор и имя файла. Каждая дочерняя программа (
struct childProgram
) теперь специфицирует нужное ей количество перенаправлений.

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

tail < input-file | sort > output-file
.

Рис. 11.1. Структуры данных, описывающие задание для

ladsh2.с

11.7.2. Изменения в коде

Как только в

parseCommand
будут правильно отражены структуры данных, то запуск команд в правильном порядке становится довольно простым при достаточном внимании к деталям. Прежде всего, мы добавляем цикл в
parseCommand
для запуска дочерних процессов, поскольку теперь их может быть множество. Прежде чем войти в цикл, мы устанавливаем
nextin
и
nextout
, которые являются файловыми дескрипторами, используемыми в качестве стандартных потоков ввод и вывода для следующего запускаемого процесса. Для начала мы используем те же stdin и stdout, что и оболочка.

Теперь посмотрим, что происходит внутри цикла. Основная идея описана ниже.

1. Если это финальный процесс в задании, убедиться, что

nextout
указывает на stdout. В противном случае нужно подключить вывод этого задания к входному концу неименованного канала.

2. Породить новый процесс. Внутри дочернего перенаправить stdin и stdout, как указано с помощью

nextin
,
nextout
и всех специфицированных ранее перенаправлений.

3. Вернувшись обратно в родительский процесс, закрыть

nextin
и
nextout
, используемые только что запущенным дочерним процессом (если только они не являются потоками ввода и вывода самой оболочки).

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

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Охота на попаданку. Бракованная жена

Герр Ольга
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Охота на попаданку. Бракованная жена

Кай из рода красных драконов

Бэд Кристиан
1. Красная кость
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Кай из рода красных драконов

Хозяйка Проклятой Пустоши. Книга 2

Белецкая Наталья
2. Хозяйка Проклятой Пустоши
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка Проклятой Пустоши. Книга 2

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Потусторонний. Книга 2

Погуляй Юрий Александрович
2. Господин Артемьев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Потусторонний. Книга 2

Чапаев и пустота

Пелевин Виктор Олегович
Проза:
современная проза
8.39
рейтинг книги
Чапаев и пустота

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

Лютая

Шёпот Светлана Богдановна
Любовные романы:
любовно-фантастические романы
6.40
рейтинг книги
Лютая

Ведьмак (большой сборник)

Сапковский Анджей
Ведьмак
Фантастика:
фэнтези
9.29
рейтинг книги
Ведьмак (большой сборник)

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4

Ученик

Губарев Алексей
1. Тай Фун
Фантастика:
фэнтези
5.00
рейтинг книги
Ученик

Начальник милиции. Книга 5

Дамиров Рафаэль
5. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 5