求多进程暂停与恢复程序示例:实现非定时触发式暂停与继续执行
实现程序的手动暂停与继续(非定时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; }
使用方法:
- 编译运行程序,记下输出的PID;
- 打开另一个终端,执行
kill -STOP <你的PID>,程序会立刻暂停; - 执行
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
相关产品推荐
相关产品推荐

