Манипуляция таблицей дескрипторов

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

Для закрытия дескриптора используется уже рассматривавшийся вызов close().

Кроме этого, очень важны еще два системных вызова, создающие синонимы существующих дескрипторов:

int dup (int fd);

int dup2(int fd, int new_fd);

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

Вызов dup2() отличается тем, что новый дескриптор создается под заданным номером (параметр new_fd). Если этот номер был связан с открытым дескриптором, тот дескриптор закрывается.

Рассмотрим пример. Допустим, у нас возникла потребность в программе на С смоделировать функционирование команды Shell:

>Ls –L –a –R/>filelist

(попросту говоря, сгенерировать файл filelist, содержащий список всех файлов в системе). Это можно сделать с помощью следующего фрагмента программы:

main() {

int pid, status;

pid = fork();

if(pid = = -1) { /*…обработка ошибки …*/ }

if(pid = = 0) { /*…дочерний процесс …*/

int fd = open(”filelist”, O_REAT|O_WRONLY|O_TRUNK, 0666);

if(fd = = -1) exit(1);

dup2(fd,1);

close(fd);

execlp(“ls”, “ls”, “-1”, “-a”, “-R”, “/”, NULL);

perror(“ls”);

exit(1);

}

/*родительский процесс */

wait(&status);

if(!WIFEXITED(status) || WEXITSTATUS(status)!=0) {

/*…обработка ошибки…*/

}

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: