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

C语言程序死锁问题求助:需让子进程2先于子进程1执行

问题原因分析

你的代码死锁的核心问题是信号量没有在进程间真正共享:

  • 你在父进程的栈上定义了sem_t sem,调用fork()后,子进程会复制父进程的栈空间,所以子进程1和子进程2各自拥有一个独立的sem副本,完全没有关联。
  • 子进程2调用sem_post(&sem)是给自己的信号量加1,而子进程1等待的是自己那个初始值为0的信号量,永远不会被唤醒,最终导致死锁。
  • 另外,子进程1里调用sem_destroy(&sem)也不合理,信号量的销毁应该由最后使用它的进程(通常是父进程)来执行。
修复方案

要实现进程间信号量共享,需要将信号量放在进程共享的内存区域(比如共享内存、匿名映射内存),或者使用有名信号量。下面是基于匿名共享内存的修复版本:

#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>

int main() {
    int pid1, pid2;
    // 用mmap创建匿名共享内存,存放信号量
    sem_t *sem = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
                      MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (sem == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }

    // 初始化信号量,pshared设为1(进程间共享),初始值0
    sem_init(sem, 1, 0);
    pid1 = fork();

    if (pid1 == 0) { // child 1
        sem_wait(sem);
        printf("Child 1 PID: %d\n", getpid());
        munmap(sem, sizeof(sem_t)); // 释放映射
        return 0;
    } else { // parent
        pid2 = fork();
        if (pid2 == 0) { // child 2
            printf("Child 2 PID: %d\n", getpid());
            sem_post(sem);
            munmap(sem, sizeof(sem_t)); // 释放映射
            return 0;
        } else { // parent
            wait(NULL); // wait for child 2
            wait(NULL); // wait for child 1
            sem_destroy(sem); // 销毁信号量
            munmap(sem, sizeof(sem_t)); // 释放映射
            printf("Parent PID: %d\n", getpid());
        }
    }

    return 0;
}
关键修改点
  • 使用mmap创建匿名共享内存,让父子进程的信号量指向同一块内核内存区域,实现真正的进程间共享。
  • 移除子进程中的sem_destroy,由父进程在所有子进程结束后销毁信号量。
  • 每个进程结束前调用munmap释放共享内存映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:42:09