如何用Semaphores实现两个Forked子进程交替执行?
解决方案:使用共享内存信号量实现 fork 子进程交替执行
没问题,我来帮你理清如何用共享内存里的信号量让两个 fork 出来的子进程交替执行任务。核心思路是用两个信号量分别控制两个子进程的执行时机,让它们互相"传递执行权",下面是具体实现步骤和代码示例:
关键思路
- 共享内存存储信号量:因为 fork 后的子进程拥有独立地址空间,所以信号量必须放在共享内存中,才能让两个子进程都访问到。
- 初始化信号量:让第一个子进程(child1)的信号量初始值为1(允许立即执行),第二个子进程(child2)的信号量初始值为0(阻塞等待)。
- 交替执行逻辑:每个子进程完成任务后,唤醒另一个子进程,然后自己进入等待状态,循环这个过程直到完成10次交替(每个子进程执行5次)。
完整代码示例
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #include <semaphore.h> #include <sys/wait.h> #include <errno.h> // 定义共享内存中的信号量结构体 typedef struct { sem_t sem_child1; sem_t sem_child2; } SharedSemaphores; // 两个子进程共用的执行函数 void execute_task(int child_id) { printf("子进程 %d 正在执行任务\n", child_id); // 这里替换成你实际的业务逻辑 sleep(1); // 模拟任务耗时 } int main() { // 创建共享内存段,大小为信号量结构体的大小 int shm_id = shmget(IPC_PRIVATE, sizeof(SharedSemaphores), IPC_CREAT | 0666); if (shm_id == -1) { perror("shmget 创建共享内存失败"); exit(EXIT_FAILURE); } // 将共享内存附加到当前进程的地址空间 SharedSemaphores *semaphores = (SharedSemaphores *)shmat(shm_id, NULL, 0); if (semaphores == (void *)-1) { perror("shmat 附加共享内存失败"); exit(EXIT_FAILURE); } // 初始化信号量:第二个参数为1表示信号量可在进程间共享 if (sem_init(&semaphores->sem_child1, 1, 1) == -1) { perror("sem_init 初始化 child1 信号量失败"); exit(EXIT_FAILURE); } if (sem_init(&semaphores->sem_child2, 1, 0) == -1) { perror("sem_init 初始化 child2 信号量失败"); exit(EXIT_FAILURE); } pid_t pid1, pid2; // 第一个子进程(child1) pid1 = fork(); if (pid1 == 0) { // 子进程1执行5次 for (int i = 0; i < 5; i++) { sem_wait(&semaphores->sem_child1); // 等待自己的信号量(获取执行权) execute_task(1); sem_post(&semaphores->sem_child2); // 释放子进程2的信号量(传递执行权) } shmdt(semaphores); // 脱离共享内存 exit(EXIT_SUCCESS); } else if (pid1 < 0) { perror("fork 创建子进程1失败"); exit(EXIT_FAILURE); } // 第二个子进程(child2) pid2 = fork(); if (pid2 == 0) { // 子进程2执行5次 for (int i = 0; i < 5; i++) { sem_wait(&semaphores->sem_child2); // 等待自己的信号量 execute_task(2); sem_post(&semaphores->sem_child1); // 传递执行权给子进程1 } shmdt(semaphores); // 脱离共享内存 exit(EXIT_SUCCESS); } else if (pid2 < 0) { perror("fork 创建子进程2失败"); exit(EXIT_FAILURE); } // 父进程等待两个子进程执行完毕 waitpid(pid1, NULL, 0); waitpid(pid2, NULL, 0); // 清理资源:销毁信号量、脱离并删除共享内存 sem_destroy(&semaphores->sem_child1); sem_destroy(&semaphores->sem_child2); shmdt(semaphores); shmctl(shm_id, IPC_RMID, NULL); printf("所有任务执行完毕\n"); return 0; }
注意事项
- 编译方式:编译时需要链接 pthread 库,命令如下:
gcc alternating_processes.c -o alternating_processes -pthread - 信号量共享属性:
sem_init的第二个参数必须设为1,否则信号量只能在同一进程的线程间共享,无法跨进程使用。 - 资源清理:父进程必须等待子进程全部结束后再销毁信号量和共享内存,避免出现资源泄漏或未定义行为。
内容的提问来源于stack exchange,提问作者hm1233
相关产品推荐
相关产品推荐

