fcntl (), значение F_GETFD в UNIX - PullRequest
       17

fcntl (), значение F_GETFD в UNIX

0 голосов
/ 12 февраля 2019

Что означает F_GETFD в функции fcntl () в unix? Как я понимаю, он должен возвращать -1, если в указанной позиции нет файлового дескриптора. Если это так, когда это произойдет?при выполнении в этом случае значения, близкого к файловому дескриптору, F_GETFD также не возвращает -1.

Это часть программы, использующей F_GETFD, и не возвращает -1, если я закрою x fd (thid fd ввел 0 в таблицу fd, так как мы предварительно закрыли 0 и сделали dup (x)):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>


void try(){
printf("got_sig\n");
}
int main(int argc, char *argv[]){
int x, stdout=1;
signal(SIGUSR1,&try);
x = open("t1.txt",O_RDWR|O_CREAT, 0666);
close(0);
dup(x);
close(x);
if (fcntl(0,F_GETFD)==-1)
printf("false\n");
kill(getpid(),SIGUSR1);
//close(x);
write(stdout,"BYE\n",4);
exit(0);
}

Когда F_GETFD вернет -1?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

На справочной странице функции fcntl () :

Флаги дескриптора файла
Следующие команды управляют флагами, связанными с дескриптором файла,В настоящее время определен только один такой флаг: FD_CLOEXEC, флаг закрытия при исполнении.Если бит FD_CLOEXEC установлен, дескриптор файла будет автоматически закрыт во время успешного выполнения execve (2).

F_GETFD (void)
Возврат (как результат функции) флаг дескриптора файла;arg игнорируется.

(Или см. стандартный текст POSIX для fctnl () , если вам не безразлично.)

Итак,fnctl(fd, F_GETFD) сообщает вам, если дескриптор файла остается открытым в течение execve() или нет.

Применяются обычные случаи ошибок для fcntl(), поэтому он, например, возвращает -1 и устанавливает errno в EBADF, если указанный вами файл не был открыт.В вашем коде вы вызвали fcntl() на fd 0, который содержит дублированную копию x, и поэтому открыт.fcntl() вернул бы -1 для fd x, но это тот, который вы явно закрыли.

0 голосов
/ 12 февраля 2019

Проверяя реализацию do_fcntl в ядре Linux, мы видим, что:

static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
        struct file *filp)
{
    long err = -EINVAL;
    switch (cmd) {
    ...
    case F_GETFD:
        err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
        break;
    ...
    }
    return err;
}

do_fcntl(F_GETFD) может возвращать только FD_CLOEXEC или 0.

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

Исходя из этого, fcntl(F_GETFD) будетвернуть только -1 с errno, установленным в -9 (-EBADF), или вернуть 0 или 1 (FD_CLOEXEC) в Linux 4.20.Таким образом, fcntl(F_GETFD) вернет -1 в случае плохого дескриптора файла или дескриптора файла, открытого с O_PATH.Обратите внимание, что для других ядер оно может отличаться, и обратите внимание, что со временем оно может измениться.

...