我正在通过以下调用在文件描述符上使用fcntl():
Retval = select(
MaxSocketId + 1,
&ReadSocketSet,
(fd_set *)NULL,
(fd_set *)NULL,
(struct timeval *)NULL
);
if (Retval <= 0) {
for (lIndexFD = 3; lIndexFD < (MaxSocketId + 1); lIndexFD++) {
if ((lFlag = fcntl(lIndexFD, F_GETFD)) < 0) {
if (errno == 9) {
FD_CLR(lIndexFD, &ActiveSocketSet);
}
}
else
printf(" \n In fcntl Else cond %d ", lFlag);
}
continue;
}
但是在fcntl()的else条件下,我的过程陷入了无限循环。看来fcntl()返回0。
我想知道它在哪种条件下返回0,以及如何处理这种情况。
答案 0 :(得分:1)
更新:
if (Retval <= 0)
可能会更改为if (Retval < 0)
。
当Retval
为零时,select
运行正常。
当Retval
为-1且errno为EBADF
时,请使用fcntl检查fd是否有效。
您看到fcntl总是返回0,这是因为:
尚未设置fd的FD_CLOEXEC
标志
select
不会失败,fcntl也不会失败,因为所有fd都是有效的。
fcntl
有多种cmd
。使用F_GETFD
时,它意味着检索文件描述符标志。
请查看fcntl
的手册,此类型只有一个标志(FD_CLOEXEC)。因此,如果未为fd设置此标志,则F_GETFD
将返回值0。
文件描述符标志
以下命令操纵与文件描述符关联的标志。当前,仅定义了一个这样的标志:FD_CLOEXEC,执行时关闭标志。如果FD_CLOEXEC位为0,则文件 描述符将在execve(2)上保持打开状态,否则将关闭。
F_GETFD (void) Read the file descriptor flags; arg is ignored. F_SETFD (int) Set the file descriptor flags to the value specified by arg.
何时不返回0?
当open
一个文件时,标志FD_CLOEXEC
被默认禁用。您可以这样启用它。
fd = open(filepath, O_RDONLY | O_CLOEXEC)
调用fcntl(fd, F_SETFD, FD_CLOEXEC)
以启用标志FD_CLOEXEC
。