基于双信号量与单管道的父子进程双向通信同步问题求助
问题描述
我正在完成一项任务:使用两个信号量实现同步,通过单管道完成父子进程的双向通信。尝试许久仍未成功,期望输出为:
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; }
修复说明
- 管道逻辑修正:父进程关闭读端仅写,子进程关闭写端仅读,符合管道单向通信的特性。
- 信号量共享:将
sem_init的第二个参数设为1,确保信号量在父子进程间共享。 - 同步链条梳理:父进程先执行→唤醒子进程→子进程执行→唤醒父进程,形成严格的交替执行逻辑,完美匹配期望输出。
运行修复后的代码,即可得到交替输出的结果。
内容的提问来源于stack exchange,提问作者ruscanca
相关产品推荐
相关产品推荐

