如何用fork创建可多次触发执行的等待子进程?
不用线程也能实现:fork子进程重复触发执行任务的方案
完全可以做到不用线程,通过fork创建的子进程保持存活,按需多次触发执行任务。你之前的问题是直接让子进程execve了myecho——execve会把整个子进程的程序空间替换掉,执行完就退出了,自然没法重复触发。下面给你两种靠谱的实现方式:
方式1:信号触发(最简单,适合无参数触发)
让子进程阻塞等待一个自定义信号(比如SIGUSR1),主进程每次要触发任务时就给子进程发这个信号,子进程收到后执行任务,完了继续回去等下一次信号。
示例代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> // 子进程要执行的任务逻辑 void run_task() { printf("子进程执行任务 | PID: %d\n", getpid()); // 用fork+execve调用myecho,确保myecho执行完后子进程仍能保持存活 pid_t grandkid = fork(); if (grandkid == 0) { execl("./myecho", "myecho", "任务触发", NULL); perror("调用myecho失败"); exit(1); } waitpid(grandkid, NULL, 0); // 等待myecho执行完成 } // 信号处理函数:收到SIGUSR1就执行任务 void handle_signal(int sig) { if (sig == SIGUSR1) { run_task(); } } int main() { pid_t child_pid = fork(); if (child_pid == -1) { perror("fork子进程失败"); exit(1); } if (child_pid == 0) { // 子进程:注册信号处理,进入无限等待状态 signal(SIGUSR1, handle_signal); while (1) { pause(); // 阻塞等待信号,不占用CPU资源 } exit(0); } else { // 主进程:按需发送信号触发任务 char input; printf("输入任意字符触发任务,输入q退出\n"); while (1) { scanf(" %c", &input); if (input == 'q') { kill(child_pid, SIGTERM); // 终止子进程 waitpid(child_pid, NULL, 0); break; } kill(child_pid, SIGUSR1); // 发送触发信号 } } return 0; }
方式2:管道触发(支持传参数,更灵活)
主进程和子进程建立管道,子进程阻塞读取管道内容,主进程每次要触发就往管道里写数据(可传递任务参数),子进程读到数据后执行任务,完成后继续等待下一次触发。
示例代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("创建管道失败"); exit(1); } pid_t child_pid = fork(); if (child_pid == -1) { perror("fork子进程失败"); exit(1); } if (child_pid == 0) { // 子进程:关闭写端,读取管道等待指令 close(pipefd[1]); char buf[256]; ssize_t read_len; while ((read_len = read(pipefd[0], buf, sizeof(buf)-1)) > 0) { buf[read_len] = '\0'; printf("子进程收到指令:%s,执行任务 | PID: %d\n", buf, getpid()); // 用fork+execve调用myecho,支持传递参数 pid_t grandkid = fork(); if (grandkid == 0) { execl("./myecho", "myecho", buf, NULL); perror("调用myecho失败"); exit(1); } waitpid(grandkid, NULL, 0); } close(pipefd[0]); exit(0); } else { // 主进程:关闭读端,写入指令触发任务 close(pipefd[0]); char cmd[256]; printf("输入触发指令(输入q退出):\n"); while (1) { fgets(cmd, sizeof(cmd), stdin); cmd[strcspn(cmd, "\n")] = '\0'; // 去掉换行符 if (strcmp(cmd, "q") == 0) { close(pipefd[1]); // 关闭管道让子进程读到EOF退出 waitpid(child_pid, NULL, 0); break; } write(pipefd[1], cmd, strlen(cmd)); } } return 0; }
关键提醒
- 不要直接让子进程
execve外部程序(比如myecho),否则子进程会被完全替换成该程序,执行完就直接退出,无法重复触发。要让子进程保持存活,需让它自身进入等待循环,每次触发时要么直接执行内嵌的代码逻辑,要么fork一个孙子进程去调用execve。 - 信号和管道的选择:信号适合简单的无参数触发,管道支持传递任务参数,灵活性更高。
内容的提问来源于stack exchange,提问作者jcarlosweb
相关产品推荐
相关产品推荐

