You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求多进程暂停与恢复程序示例:实现非定时触发式暂停与继续执行

实现程序的手动暂停与继续(非定时sleep)

我懂你想要的是那种能手动触发暂停、再手动恢复的程序控制,而不是固定时长的sleep对吧?你当前的代码卡在暂停后没法继续,核心问题出在信号处理逻辑上——你用了sigsuspend(&to_stop)但to_stop是空信号集,意味着任何信号都能唤醒它,但大多数默认信号(比如Ctrl+C)会直接终止程序,根本没机会执行后面的printf("AFTER SIGSUSPEND")。

下面给你两种实用的实现方案,分别对应不同的需求场景:

方案一:利用系统原生信号(最简单)

Linux系统自带SIGSTOP和SIGCONT信号,专门用来暂停和恢复进程,是系统级别的控制,不需要自己写复杂逻辑:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("程序已启动,PID:%d\n", getpid());
    printf("👉 暂停程序:在另一个终端执行 `kill -STOP %d`\n", getpid());
    printf("👉 恢复程序:在另一个终端执行 `kill -CONT %d`\n", getpid());
    
    for (int i = 0; i < 10; i++) {
        printf("正在执行:第 %d 次循环\n", i+1);
        sleep(1); // 模拟实际工作负载
    }
    
    printf("程序执行完毕\n");
    return 0;
}

使用方法:

  1. 编译运行程序,记下输出的PID;
  2. 打开另一个终端,执行kill -STOP <你的PID>,程序会立刻暂停;
  3. 执行kill -CONT <你的PID>,程序会从暂停的位置继续往下跑。

方案二:自定义信号控制(更灵活)

如果需要更个性化的控制(比如暂停时输出提示、或者绑定其他操作),可以自己定义信号处理逻辑,用一个全局变量标记暂停状态,配合sigsuspend等待恢复信号:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

// volatile防止编译器优化,确保主循环能及时感知变量变化
volatile int paused = 0;

// 信号处理函数:切换暂停/恢复状态
void toggle_pause(int sig) {
    if (sig == SIGUSR1) {
        paused = 1;
        printf("\n✅ 程序已暂停,发送 SIGUSR2 恢复\n");
    } else if (sig == SIGUSR2) {
        paused = 0;
        printf("\n✅ 程序已恢复执行\n");
    }
}

int main() {
    struct sigaction sa;
    sa.sa_handler = toggle_pause;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    // 注册SIGUSR1(暂停)和SIGUSR2(恢复)的处理函数
    if (sigaction(SIGUSR1, &sa, NULL) == -1 || sigaction(SIGUSR2, &sa, NULL) == -1) {
        perror("注册信号处理失败");
        exit(EXIT_FAILURE);
    }

    printf("程序已启动,PID:%d\n", getpid());
    printf("👉 暂停程序:`kill -USR1 %d`\n", getpid());
    printf("👉 恢复程序:`kill -USR2 %d`\n", getpid());

    for (int i = 0; i < 10; i++) {
        // 如果处于暂停状态,等待SIGUSR2信号
        while (paused) {
            sigset_t wait_mask;
            sigemptyset(&wait_mask);
            sigaddset(&wait_mask, SIGUSR2);
            // 只等待SIGUSR2信号,其他信号暂时屏蔽
            sigsuspend(&wait_mask);
        }

        printf("正在执行:第 %d 次循环\n", i+1);
        sleep(1);
    }

    printf("程序执行完毕\n");
    return 0;
}

针对你原代码的修改建议

你的原代码还有两个小问题:fflush(stdout)后面缺分号,以及没有指定唤醒信号。修改后可以正常运行:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <sys/wait.h>

struct sigaction act;
sigset_t to_start, to_stop;

// 空处理函数,仅用来唤醒sigsuspend
void wake_up(int sig) {}

int main(int argc, char *argv[]) {
    int i=0;
    // 注册SIGUSR1信号处理
    act.sa_handler = wake_up;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGUSR1, &act, NULL) == -1) {
        perror("sigaction failed");
        exit(EXIT_FAILURE);
    }

    printf("BEFORE SIGSUSPEND\n");
    // 设置信号掩码:只允许SIGUSR1唤醒,其他信号屏蔽
    sigfillset(&to_stop);
    sigdelset(&to_stop, SIGUSR1);
    sigsuspend(&to_stop); // 等待SIGUSR1信号
    
    printf("AFTER SIGSUSPEND\n");
    fflush(stdout); // 补上分号
    return 0;
}

运行后,在另一个终端执行kill -USR1 <PID>,程序就会从sigsuspend唤醒,执行后面的printf。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:44:49