C 如何检查文件描述符是否已关闭?

C 如何检查文件描述符是否已关闭?,c,low-level,low-level-code,low-level-io,C,Low Level,Low Level Code,Low Level Io,在POSIX环境中,当使用系统调用操作文本文件(open()、close()、read()、write())时,是否有方法检查在使用close(file\u descriptor)时是否确实关闭了文件描述符 示例: int main(int argc, char **argv) { int input_file; // file descriptor for input file int output_file; // file descriptor for output fil

在POSIX环境中,当使用系统调用操作文本文件(
open()、close()、read()、write()
)时,是否有方法检查在使用
close(file\u descriptor)
时是否确实关闭了文件描述符

示例

int main(int argc, char **argv)
{
    int input_file; // file descriptor for input file
    int output_file; // file descriptor for output file
    input_file = open(argv[1], O_RDONLY));
    ouput_file = open(argv[2], ...file properties & permissions and crap.....);

    // blah blah blah...

    close(input_file);
    close(output_file);

    // what can I code here to check if the file descriptor was actually closed?
}

最简单的方法可能是只检查第一次
关闭的返回值

if (close(input_file)) {
    perror("close");
} else {
    // all good
}
这是唯一的线程安全方式。在多线程程序中,另一个线程可以获得一个新的文件描述符,该描述符可以回收刚刚关闭的程序的fd号


仅在单线程代码中,在关闭和检查之间无法循环fd

int main(int argc, char **argv)
{
    int input_file; // file descriptor for input file
    int output_file; // file descriptor for output file
    input_file = open(argv[1], O_RDONLY));
    ouput_file = open(argv[2], ...file properties & permissions and crap.....);

    // blah blah blah...

    close(input_file);
    close(output_file);

    // what can I code here to check if the file descriptor was actually closed?
}
如果您希望检查文件描述符之后是否有效,那么您可以使用任何使用文件描述符的函数并检查其错误代码。最不干预、重量最轻的可能是
fcntl/F_GETFL

if (fcntl(fd, F_GETFL) < 0 && errno == EBADF) {
    // file descriptor is invalid or closed
}

close
在成功时不修改
errno
,但我们只在
close
返回非零时读取
errno
,这意味着它已被设置。

您可以检查
close()
的返回值和相应的错误号

成功完成后返回0;否则,-1应为 返回,并设置errno以指示错误

[……]

如果出现以下情况,close()函数将失败:

[EBADF]

fildes参数不是有效的文件描述符


检查文件描述符是否无效的唯一保存方法是在定义时显式将其设置为(例如)
-1
,并且每次成功关闭时都将其设置为

可以使用宏执行以下操作:

#define FD_INVALID (-1)

#define FD_CLOSE_AND_INVALIDATE(fd) \
do { \
  if (-1 == close(fd)) \
  { \
    perror("close failed"); \
  } \
  else \
  { \
    (fd) = FD_INVALID; \
  } \
} while (0)

int main(int argc, char ** argv)
{
  int input_file = FD_INVALID; /* Properly initialise file descriptor for input file */
  int output_file = FD_INVALID; /*  Properly initialise file descriptor for output file */

  input_file = open(argv[1], O_RDONLY));
  ouput_file = open(argv[2], ...);

  /* Do something. */

  FD_CLOSE_AND_INVALIDATE(input_file);
  FD_CLOSE_AND_INVALIDATE(output_file);

  /* To check if the file descriptor was actually closed just test for FD_INVALID. */
}

@SteveJobs:在多线程环境中,这些方法中的每一种都是危险的,因为所讨论的文件描述符可能已经被另一个线程回收,因为它上次被关闭了。应该是
errno==EBADF
@Isaac谢谢。好地方。更正了。在多线程程序中要小心。重新使用文件描述符。因此,如果另一个线程很快进入并打开另一个文件,则关闭一个FD可能会导致在
close()
之后打开另一个具有相同值的FD。唯一线程安全的方法是检查返回值。这个答案不能保证有效。如果
close()
成功,则不会修改
errno
<在调用
close()
之前,需要将code>errno
设置为
0
。对于多线程程序,或者在文件描述符可以重用的任何其他情况下,事后检查文件描述符是否有效也不起作用。如果系统有许多文件描述符,请维护文件描述符的哈希映射,并且每次关闭时,将其设置为-1。