问题
What is the meaning of F_GETFD in fcntl() function in unix ?, From what I understand it should return -1 if there is no file descriptor in the position specified.. If that's true, when would it happen ? when doing close to a file descriptor in that posstion, F_GETFD doesn't return -1 either..
This is a part of a program using F_GETFD and it will not return -1 if I close the x fd (thid fd entered 0 in the fd table since we closed 0 beforehand and did 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);
}
When will F_GETFD return -1 ?
回答1:
From the man page of fcntl():
File descriptor flags
The following commands manipulate the flags associated with a file descriptor. Currently, only one such flag is defined: FD_CLOEXEC, the close-on-exec flag. If the FD_CLOEXEC bit is set, the file descriptor will automatically be closed during a successful execve(2).F_GETFD (void)
Return (as the function result) the file descriptor flags; arg is ignored.
(Or see the POSIX standard text for fctnl(), if you care.)
So, fnctl(fd, F_GETFD)
tells you if the file descriptor stays open over an execve()
or not.
The usual error cases for fcntl()
apply, so it would e.g. return -1 and set errno
to EBADF
if the fd you gave wasn't open. In your code, you called fcntl()
on fd 0, which holds the dup'ed copy of x
, and so is open. fcntl()
would return -1 for the fd x
, though, that's the one you explicitly closed.
回答2:
Inspecting the implementation of do_fcntl in the Linux kernel, we can see that:
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)
may return only FD_CLOEXEC
or 0.
The syscall definition from here can return -EBADF
in case of a bad file descriptor or the file descriptor was opened with O_PATH
.
Judging from that, the fcntl(F_GETFD)
will return only -1 with errno set to -9 (-EBADF
), or return 0 or 1 (FD_CLOEXEC
) on Linux 4.20. So the fcntl(F_GETFD)
will return -1
in case of a bad file descriptor or file descriptor opened with O_PATH
. Note that for other kernels it may be different and note that it can change over time.
来源:https://stackoverflow.com/questions/54656482/fcntl-f-getfd-meaning-in-unix