Руководство программиста для Linux


Ядро LINUX - часть 2


Поскольку файловый дескриптор 0 (stdin) был закрыт, вызов dup() дублировал дескриптор ввода канала (fd0) на его стандартный ввод. Затем мы сделали вызов execlp(), чтобы покрыть код потомка кодом программы sort. Поскольку стандартные потоки exec()-нутой программы наследуются от родителей, это означает, что вход канала ста для потомка стандартным вводом! Теперь все, что первоначальный процесс-родитель посылает в канал, идет в sort.

Существует другой системный вызов, dup2(), который также может использоваться. Этот особенный вызов произошел с Version 7 of UNIX и был поддержан BSD, и теперь требуется по стандарту POSIX. SYSTEM CALL: dup2(); PROTOTYPE: int dup2( int oldfd, int newfd ); RETURNS: новый дескриптор в случае успеха -1 в случае ошибки: errno = EBADF (oldfd некорректен) EBADF ($newfd is out of range$) EMFILE (слишком много дескрипторов для процесса) NOTES: старый дескриптор закрыл dup2()!

Благодаря этому особенному вызову мы имеем закрытую операцию и действующую копию за один системный вызов. Вдобавок, он гарантированно неделим, что означает, что он никогда не будет прерван поступающим сигналом. С первым системным вызовом dup() программисты были вынуждены предварительно выполнять операцию close(). Это приводило к наличию двух системных вызовов с малой степенью защищенности в краткий промежуток времени между ними. Если бы сигнал поступил в течение этого интервала времени, копия дескриптора не состоялась бы. dup2() разрешает для нас эту проблему.

Рассмотрим: . . childpid = fork(); if(childpid == 0) { /* Закрываем стандартный ввод, дублируем вход канала на стандартный ввод */ dup2(0, fd[0]); execlp("sort", "sort", NULL); . . }




Начало  Назад  Вперед



Книжный магазин