在unix中fcntl()函数中F_GETFD的含义是什么?据我所知,如果在指定的位置没有文件描述符,它应该返回-1。如果这是真的,什么时候会发生?当在该情况下接近文件描述符时,F_GETFD也不返回-1。
这是使用F_GETFD的程序的一部分,如果我关闭x fd它将不会返回-1(因为我们事先关闭了0并且执行了dup(x),所以fd表中的fd输入为0):
#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?
文件描述符标志 以下命令处理与文件描述符关联的标志。目前,只定义了一个这样的标志:FD_CLOEXEC,close-on-exec标志。如果设置了FD_CLOEXEC位,则在成功执行期间将自动关闭文件描述符(2)。
F_GETFD(无效) 返回(作为函数结果)文件描述符标志; arg被忽略了。
(或者如果你在意的话,请参阅POSIX standard text for fctnl()。)
因此,fnctl(fd, F_GETFD)
会告诉您文件描述符是否在execve()
上保持打开状态。
适用于fcntl()
的常见错误情况,因此它会例如如果您给出的fd未打开,则返回-1并将errno
设置为EBADF
。在你的代码中,你在fd 0上调用了fcntl()
,它保存了x
的副本,因此是开放的。然而,fcntl()
将为fd x
返回-1,那是你明确关闭的那个。
在Linux内核中检查do_fcntl的实现,我们可以看到:
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。
here中的系统调用定义可以在文件描述符错误的情况下返回-EBADF
,或者使用O_PATH
打开文件描述符。
从这一点来看,fcntl(F_GETFD)
将仅返回-1,其中errno设置为-9(-EBADF
),或者在Linux 4.20上返回0或1(FD_CLOEXEC
)。因此,如果使用fcntl(F_GETFD)
打开了错误的文件描述符或文件描述符,-1
将返回O_PATH
。请注意,对于其他内核,它可能会有所不同,请注意它可能会随时间而变化。