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

如何用Semaphores实现两个Forked子进程交替执行?

解决方案:使用共享内存信号量实现 fork 子进程交替执行

没问题,我来帮你理清如何用共享内存里的信号量让两个 fork 出来的子进程交替执行任务。核心思路是用两个信号量分别控制两个子进程的执行时机,让它们互相"传递执行权",下面是具体实现步骤和代码示例:

关键思路

  1. 共享内存存储信号量:因为 fork 后的子进程拥有独立地址空间,所以信号量必须放在共享内存中,才能让两个子进程都访问到。
  2. 初始化信号量:让第一个子进程(child1)的信号量初始值为1(允许立即执行),第二个子进程(child2)的信号量初始值为0(阻塞等待)。
  3. 交替执行逻辑:每个子进程完成任务后,唤醒另一个子进程,然后自己进入等待状态,循环这个过程直到完成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:37:54