编译创建子进程的C代码后Linux系统意外关机的原因排查
代码导致Linux系统意外关机的原因及修复方案
我编写了一段简单的C代码,尝试创建10个子进程,让每个子进程独立执行打印时间的任务,之后在父进程中终止所有子进程。但运行该代码时,子进程输出内容后Linux系统会意外关机,需要重新输入用户密码启动。代码如下:
#include <stdio.h> #include <unistd.h> #include <sys/time.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <stdlib.h> #include <time.h> int main() { pid_t pids[10]; int i; int n= 10; for (i= 0; i<n; ++i) { if ((pids[i] = fork()) <0) { perror("fork"); abort(); } else if (pids[i] == 0) { struct timeval tv; time_t t; struct tm*info; char buffer[64]; gettimeofday(&tv,NULL); t = tv.tv_sec; info = localtime(&t); sleep(1); printf("CHILD PID: %d and the time is %s\n",getpid(),asctime(info)); } } int status; pid_t pid; sleep(5); while (n >0) { pid = wait(&status); kill((long)pid, SIGTERM); printf("CHILD %d killed.",pid); --n; } }
核心问题:子进程未退出引发「fork风暴」
- 子进程执行完
printf后没有调用exit()或_exit(),会继续执行父进程的后续代码——也就是for循环的剩余部分。每个子进程都会继续创建新的子进程,短时间内系统会被海量进程占满,直接耗尽CPU、内存等核心资源,触发系统OOM(内存不足)机制,甚至导致系统崩溃重启。 - 父进程的
wait()逻辑完全无效:wait()返回的是已经终止的子进程PID,此时调用kill()没有任何意义;如果PID被系统复用,还可能误杀其他正常进程,加重系统异常。
修复方案
- 子进程执行完任务后立即退出,避免执行父进程的后续代码。
- 父进程无需在
wait()后调用kill(),直接等待子进程自然终止即可;如果需要主动终止子进程,应先发送信号再等待退出状态。
修复后的代码(等待子进程自然终止)
#include <stdio.h> #include <unistd.h> #include <sys/time.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <time.h> int main() { pid_t pids[10]; int i; int n = 10; for (i = 0; i < n; ++i) { if ((pids[i] = fork()) < 0) { perror("fork"); abort(); } else if (pids[i] == 0) { struct timeval tv; time_t t; struct tm* info; gettimeofday(&tv, NULL); t = tv.tv_sec; info = localtime(&t); sleep(1); printf("CHILD PID: %d and the time is %s\n", getpid(), asctime(info)); // 子进程执行完任务后立即退出,避免执行父进程代码 exit(EXIT_SUCCESS); } } int status; pid_t pid; sleep(5); printf("开始等待子进程终止...\n"); while (n > 0) { pid = wait(&status); if (pid == -1) { perror("wait"); break; } printf("CHILD %d 已终止。\n", pid); --n; } return 0; }
主动终止子进程的版本
如果需要父进程主动发送终止信号,可修改父进程逻辑:
// 替换原父进程等待代码为: sleep(5); printf("主动终止所有子进程...\n"); for (i = 0; i < 10; ++i) { if (pids[i] > 0) { // 确保是有效的子进程PID kill(pids[i], SIGTERM); printf("已发送终止信号给 CHILD %d\n", pids[i]); } } // 等待所有子进程退出 int status; pid_t pid; while ((pid = wait(&status)) != -1) { printf("CHILD %d 已终止。\n", pid); }
内容的提问来源于stack exchange,提问作者ihatec
相关产品推荐
相关产品推荐

