You need to enable JavaScript to run this app. C父子进程乒乓通信程序产生大量进程致Linux崩溃、磁盘占满如何解决?
优惠活动
大模型
产品
解决方案
定价
更多

C父子进程乒乓通信程序产生大量进程致Linux崩溃、磁盘占满如何解决?

问题背景

我编写了如下C语言程序,功能是实现父进程与子进程之间的“乒乓通信”。开发编译阶段我就发现电脑负载持续升高,但当时未重视,最终程序导致我的Linux系统崩溃,生成了大量异常进程拖慢整机运行速度,还产生了大量临时/日志文件,原本剩余35GB的磁盘仅剩200MB可用空间。

我需要解决以下问题:

  1. 如何修改程序避免其生成大量异常进程?
  2. 我已经尝试执行sudo apt autoremove、autoclean命令,还删除了/var/log目录下所有.gz后缀的文件,但磁盘剩余空间依然只有200MB,经查/var/log目录占用空间接近40GB,我不想删除该目录下的必要系统文件,该如何正确清理日志目录?
  3. 为什么我的程序会生成这么多临时文件或日志文件?

附问题代码

/******************************** Header Files ********************************/
    
#define _GNU_SOURCE 

#include <signal.h>
#include <stdio.h>      /*  printf                          */
#include <stdlib.h>     /*  exit                            */
#include <unistd.h>     /*  fork, getpid, sleep             */
#include <sys/wait.h>   /*  回收子进程需要引入该头文件         */

/**************************** Forward Declarations ****************************/

/*  exits the program with the given 'ret status' if 'is_bad' is true       */
void ExitIfBad(int is_bad, char *msg_to_print, int ret_stat);

void handle_siguser1(int signal_id);

void handle_siguser2(int signal_id);

void handle_sigint(int signal_id);

enum {CHILD = 0};

static int is_parent_turn = 1;
static pid_t global_pid; // 存储子进程pid用于退出时回收

/************************* Functions  Implementations *************************/
int main()
{
    /*  create a child process  */
    pid_t pid = fork();
    global_pid = pid;
    
    ExitIfBad(pid < 0, "Error: Could not create a process\n", 1);
    
    signal(SIGUSR1, handle_siguser1);
    signal(SIGUSR2, handle_siguser2);
    signal(SIGINT, handle_sigint); // 绑定终止信号处理逻辑
    
    /*  returned to the newly created child process. */
    if (CHILD == pid)
    {   
        while (1)
        {
            sleep(2);
            kill(getppid(), SIGUSR2);
        }
    }
        
    /* returned to parent */
    else
    {   
        while (1)
        {
            kill(getpid(), SIGUSR1);
            sleep(2); // 增加延迟,避免高频发信号
        }
    }
        
    return 0;   
}
/******************************************************************************/
void handle_siguser1(int signum)
{
    if (is_parent_turn)
    {
        printf("\n\nPING\n\n");
        is_parent_turn = 0;
    }
}
/******************************************************************************/
void handle_siguser2(int signum)
{
    if (!is_parent_turn)
    {
        printf("\n\nPONG\n\n");
        is_parent_turn = 1;
    }
}
/******************************************************************************/
void handle_sigint(int signum) {
    if (global_pid > 0) {
        kill(global_pid, SIGKILL);
        wait(NULL); // 回收子进程资源,避免孤儿进程残留
    }
    exit(0);
}
/******************************************************************************/
void ExitIfBad(int is_bad, char *msg_to_print, int ret_stat)
{
    if (is_bad)
    {
        puts(msg_to_print);
        exit(ret_stat);
    }
}
/******************************************************************************/
问题解答

1. 程序修改避免生成大量异常进程的方案

你原程序的核心问题有两个:一是父进程死循环无任何延迟,高频给自己发信号占满CPU;二是没有进程退出回收逻辑,父进程异常退出后子进程会变成孤儿进程反复运行,多启动几次就会残留大量异常进程。修改要点如下:

  • 父进程发送信号后增加2秒延迟,和子进程的发送节奏匹配,避免CPU跑满
  • 增加SIGINT信号处理逻辑,用户按Ctrl+C终止程序时,父进程主动杀死子进程并回收资源,不会残留孤儿进程
  • 移除信号处理函数里的sleep调用,sleep属于不可重入函数,放在信号处理函数中会导致逻辑异常,直接把延迟逻辑移到主循环即可

2. /var/log目录正确清理方案

首先用命令du -h /var/log | sort -hr | head -20定位占用最高的前20个日志文件,再针对性处理:

  • 不要直接删除正在被系统进程写入的大日志文件,直接删除不会释放文件句柄,空间不会回收,正确操作是用> 日志文件路径清空内容,比如> /var/log/syslog、> /var/log/journal/xxxxxx/system.journal
  • 执行sudo logrotate -f /etc/logrotate.conf强制触发系统自带的日志轮转,工具会自动压缩、删除过期日志,不会误删系统必要的日志文件
  • 如果是journal日志占用过高,可以执行sudo journalctl --vacuum-size=1G直接限制journal日志总大小为1G,自动清理旧日志
  • 清理完成后执行sudo sync刷新磁盘缓存,确认空间释放

3. 大量日志/临时文件生成原因

你的原程序父进程死循环无延迟,每秒可以触发上万次printf输出PING内容,所有的标准输出内容都会被系统日志服务(rsyslog/journald)收集写入/var/log目录下的日志文件,短时间内就能生成几十GB的日志,直接占满磁盘空间。

内容的提问来源于stack exchange,提问作者NoobCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 08:36:00