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

基于双信号量与单管道的父子进程双向通信同步问题求助

问题描述

我正在完成一项任务:使用两个信号量实现同步,通过单管道完成父子进程的双向通信。尝试许久仍未成功,期望输出为:

parent: a
child: b
parent: c
child: d
.....

但我的程序仅输出:

parent:a 
child: b

之后便停止运行,希望能得到技术帮助,谢谢!

附相关代码:

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

int main(void)
{
    int fdP2C[2];
    char c = 0;
    int i;
    sem_t parent_sem, child_sem;

    if (pipe(fdP2C) != 0) {
        perror("Could not create pipes");
        return 1;
    }

    sem_init(&parent_sem, 0, 1);
    sem_init(&child_sem, 0, 0);

    if (fork() != 0) {
        // 父进程
        close(fdP2C[0]);
        c = 'a';

        for (i = 0; i < 10; i++) {
            //sem_post(&child_sem);
            //sem_wait(&parent_sem);
            write(fdP2C[1], &c, sizeof(c));
            read(fdP2C[1], &c, sizeof(c));
            sem_wait(&parent_sem);
            printf("Parent: %c\n", c);
            c++;
            sem_post(&child_sem);

        }

        close(fdP2C[1]);
        wait(NULL);
    } else {
        // 子进程
        close(fdP2C[1]);

        for (i = 0; i < 10; i++) {
            //sem_wait(&child_sem);
            sem_post(&parent_sem);
            write(fdP2C[0], &c, sizeof(c));
            read(fdP2C[0], &c, sizeof(c));

            c++;
            //sem_post(&parent_sem);
            printf("Child: %c\n", c);
            //sem_post(&parent_sem);
            //sem_wait(&child_sem);
            sem_post(&parent_sem);
            sem_wait(&child_sem);
        }

        close(fdP2C[0]);
    }

    sem_destroy(&parent_sem);
    sem_destroy(&child_sem);

    return 0;
}
问题分析与修复

你的代码存在三个核心错误,导致程序阻塞且无法按预期运行:

1. 管道读写逻辑完全错误

单管道的fd[1]是写端,fd[0]是读端,数据只能从写端流向读端。但你在父进程中尝试从写端fdP2C[1]读取数据,子进程尝试向读端fdP2C[0]写入数据,这违背了管道的单向通信特性,直接导致进程阻塞。

2. 信号量未正确共享

sem_init的第二个参数设为0时,信号量是进程私有的,子进程无法访问父进程创建的信号量,同步逻辑完全失效。必须将该参数设为1,让信号量存储在共享内存中,确保父子进程都能访问。

3. 同步顺序混乱

信号量的wait(获取)和post(释放)顺序颠倒,没有形成父→子→父的交替执行链条,导致进程互相等待死锁。


以下是修复后的完整代码:

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

int main(void)
{
    int fd[2]; // 单管道:fd[1]为写端,fd[0]为读端
    char c;
    int i;
    sem_t parent_sem, child_sem;

    // 创建管道
    if (pipe(fd) != 0) {
        perror("管道创建失败");
        return 1;
    }

    // 初始化信号量:第二个参数设为1,实现跨进程共享
    sem_init(&parent_sem, 1, 1); // 父进程初始可执行
    sem_init(&child_sem, 1, 0);  // 子进程初始等待

    pid_t pid = fork();
    if (pid > 0) {
        // 父进程逻辑:关闭读端,仅向子进程写数据
        close(fd[0]);
        c = 'a';

        for (i = 0; i < 10; i++) {
            sem_wait(&parent_sem); // 获取父进程信号量,进入临界区

            // 发送字符给子进程并输出
            write(fd[1], &c, sizeof(c));
            printf("Parent: %c\n", c);
            c++;

            sem_post(&child_sem); // 释放子进程信号量,唤醒子进程
        }

        close(fd[1]);
        wait(NULL); // 等待子进程退出
    } else if (pid == 0) {
        // 子进程逻辑:关闭写端,仅读取父进程数据
        close(fd[1]);

        for (i = 0; i < 10; i++) {
            sem_wait(&child_sem); // 等待父进程唤醒

            // 读取父进程的字符,处理后输出
            read(fd[0], &c, sizeof(c));
            c++;
            printf("Child: %c\n", c);

            sem_post(&parent_sem); // 释放父进程信号量,唤醒父进程
        }

        close(fd[0]);
    } else {
        perror("进程创建失败");
        return 1;
    }

    // 销毁信号量
    sem_destroy(&parent_sem);
    sem_destroy(&child_sem);

    return 0;
}

修复说明

  1. 管道逻辑修正:父进程关闭读端仅写,子进程关闭写端仅读,符合管道单向通信的特性。
  2. 信号量共享:将sem_init的第二个参数设为1,确保信号量在父子进程间共享。
  3. 同步链条梳理:父进程先执行→唤醒子进程→子进程执行→唤醒父进程,形成严格的交替执行逻辑,完美匹配期望输出。

运行修复后的代码,即可得到交替输出的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:15:30