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

时间:2013-10-29 14:02:00

标签: c low-level low-level-code low-level-io

在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?
}

3 个答案:

答案 0 :(得分:6)

最简单的方法可能就是检查第一个close的返回值。

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

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


仅在单线程代码中,没有任何东西可以在关闭和检查之间回收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,但我们只会在errno返回非零时阅读close,这意味着它已被设置。

答案 1 :(得分:2)

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

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

  

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

     

[...]

     

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

     

[EBADF]

     

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

答案 2 :(得分: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. */
}