Методические указания к лабораторной работе

При выполнении операции перенаправления ввода-вывода важным моментом является наследование пользовательских дескрипторов, осуществляемое с помощью системных вызовов dup() и fcntl().

Системный вызов dup() обрабатывает свой единственный параметр как пользовательский дескриптор открытого файла и возвращает целое число, которое может быть использовано как еще один пользовательский дескриптор того же файла. С помощью копии пользовательского дескриптора файла к нему может быть осуществлен доступ того же типа и с использованием того же значения указателя записи-чтения, что и с помощью оригинального пользовательского дескриптора файла.

Системный вызов fcntl(), имеющий формат

int fcntl(int fd, char command, int argument),

выполняет действия по разделению пользовательских дескрипторов в зависимости от пяти значений аргумента command, специфицированных в файле <fcntl.h>. Например, при значении второго аргумента, равного F_DUPFD системный вызов fcntl() возвращает первый свободный дескриптор файла, значение которого не меньше значения аргумента argument. Этот пользовательский дескриптор файла должен быть копией пользовательского дескриптора файла, заданного аргументом fd.

С помощью системных вызовов dup() и fcntl() пользовательские программы, а также и интерпретатор команд Shell реализуют каналы и переназначение стандартного ввода и стандартного вывода на файл. Пусть, например, некоторая программа prog читает данные из стандартного входного потока и выводит результаты в стандартный выходной поток. Для того, чтобы та же программа читала данные из файла aa.txt, а осуществляла вывод в файл bb.txt, необходимо выполнить:

#include <fcntl.h>

...............

int fd,fd2;

fd=open("aa.txt",O_RDONLY);

close(0);

fcntl(fd,F_DUPFD,0);

fd=open("bb.txt",O_WRONLY|O_CREAT);

close(1);

fcntl(fd2,F_DUPFD,1);

execlp("prog","prog",0);

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

cat < a.txt | sort | pr

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