8

在 POSIX 环境中,当使用系统调用来操作文本文件 ( open(), close(), read(), write()) 时,有没有办法检查我在使用时是否真的关闭了文件描述符close(file_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?
}
4

3 回答 3

6

最简单的方法可能是检查 first 的返回值close

if (close(input_file)) {
    perror("close");
} else {
    // all good
}

这是唯一的线程安全方式。 在多线程程序中,另一个线程可以获得一个新的文件描述符,该描述符回收刚刚关闭的文件描述符的 fd 编号。


仅在单线程代码中,没有任何东西可以在 close 和 check 之间回收 fd

如果您想在之后检查文件描述符是否有效,那么您可以使用任何使用文件描述符的函数并检查它的错误代码。最不干涉和最轻的可能是fcntl/F_GETFL

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

您也可以只调用close第二次,它也可能因EBADF.

if (close(fd) && errno == EBADF) {
    // file descriptor is invalid or closed
} else {
    // we successfully closed fd *now* (e.g. first close failed with EINTR)
    // or there was a different error
}

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

于 2013-10-29T14:04:53.200 回答
2

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

来自http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html

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

[...]

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

[EBADF]

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

于 2013-10-29T14:06:29.520 回答
0

检查文件描述符是否无效的唯一保存方法是将其显式设置为(例如)-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. */
}
于 2013-10-29T18:46:38.453 回答