面试题答案
一键面试文件描述符在进程异常终止时的情况
当进程异常终止(如收到 SIGSEGV
信号)时,Linux 内核会自动关闭该进程打开的所有文件描述符。这是因为文件描述符是进程资源的一部分,当进程终止时,内核负责清理该进程所占用的所有资源,包括文件描述符。
确保文件描述符妥善释放的原理与方法
- 正常退出时:在正常退出的情况下,程序可以通过调用
close
函数来显式关闭文件描述符。这是一种良好的编程习惯,确保在进程结束前释放所有打开的资源。 - 异常终止时:为了在异常终止时也能妥善释放文件描述符,可以使用信号处理机制。通过注册信号处理函数,在收到特定信号(如
SIGSEGV
)时,处理函数可以关闭所有打开的文件描述符,然后再进行其他必要的清理工作。
代码示例
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
// 全局变量,用于存储文件描述符
int fd1, fd2;
// 信号处理函数
void signal_handler(int signum) {
// 关闭文件描述符
close(fd1);
close(fd2);
printf("Caught signal %d, file descriptors closed.\n", signum);
// 可以在这里添加其他清理工作
exit(1);
}
int main() {
// 打开文件
fd1 = open("file1.txt", O_RDWR | O_CREAT, 0666);
if (fd1 == -1) {
perror("open file1.txt");
return 1;
}
fd2 = open("file2.txt", O_RDWR | O_CREAT, 0666);
if (fd2 == -1) {
perror("open file2.txt");
close(fd1);
return 1;
}
// 注册信号处理函数
signal(SIGSEGV, signal_handler);
// 模拟异常操作,导致SIGSEGV信号
char *ptr = NULL;
*ptr = 'a';
// 正常关闭文件描述符(如果程序执行到这里)
close(fd1);
close(fd2);
return 0;
}
代码说明
- 文件打开:使用
open
函数打开两个文件,并获取对应的文件描述符fd1
和fd2
。 - 信号处理函数:定义
signal_handler
函数,用于处理SIGSEGV
信号。在函数中关闭所有打开的文件描述符,并打印一条消息。 - 信号注册:使用
signal
函数注册signal_handler
作为SIGSEGV
信号的处理函数。 - 异常操作:通过尝试访问空指针,模拟一个会导致
SIGSEGV
信号的异常操作。 - 正常关闭:在正常情况下,程序会在结束前显式关闭文件描述符。但由于异常操作,程序会在到达这里之前触发信号处理函数。
通过这种方式,可以确保无论是正常退出还是异常终止,文件描述符都能得到妥善释放。