面试题答案
一键面试可能出现的资源瓶颈
- 文件描述符限制:每个进程都有文件描述符限制,创建大量子进程可能导致文件描述符耗尽。因为每个进程在启动时会默认打开一些文件描述符(如标准输入、输出、错误),如果子进程中还打开了其他文件或进行网络连接等操作,很容易达到系统限制。
- 内存消耗:每个子进程都需要占用一定的内存空间,包括代码段、数据段、栈等。1000 个子进程会消耗大量内存,可能导致系统内存不足,影响系统整体性能甚至出现 OOM(Out Of Memory)错误。
- 进程表资源:操作系统维护进程表来管理所有进程,创建大量子进程会占用进程表资源,可能导致进程表满,无法创建新的进程。
优化方法
- 文件描述符优化:
- 确保在子进程中及时关闭不需要的文件描述符,避免浪费。
- 可以通过
ulimit -n
命令查看和调整文件描述符限制。
- 内存优化:
- 尽量减少子进程的内存使用,例如避免在子进程中分配大量不必要的内存。
- 对于一些可以共享的数据,考虑使用共享内存等机制,减少内存重复占用。
- 进程表资源优化:
- 合理安排子进程的生命周期,及时回收已完成的子进程,避免进程表中残留过多僵尸进程。
优化后的关键代码示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define CHILD_PROCESS_COUNT 1000
int main() {
for (int i = 0; i < CHILD_PROCESS_COUNT; i++) {
pid_t pid = fork();
if (pid == 0) {
// 子进程逻辑
// 这里及时关闭不需要的文件描述符(示例)
// close(STDIN_FILENO);
// close(STDOUT_FILENO);
// close(STDERR_FILENO);
exit(EXIT_SUCCESS);
} else if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
}
// 父进程等待所有子进程完成
for (int i = 0; i < CHILD_PROCESS_COUNT; i++) {
pid_t pid = wait(NULL);
if (pid < 0) {
perror("wait");
exit(EXIT_FAILURE);
}
}
return 0;
}
在上述代码中,通过 fork
创建多个子进程,子进程中及时关闭不需要的文件描述符(注释部分为示例),父进程通过 wait
函数等待所有子进程完成。这样可以有效地管理资源,避免资源瓶颈。