Новые файловые дескрипторы создаются при успешном выполнении вызова 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) {
/*…обработка ошибки…*/
}
}