编写一个管道程序,由父进程创建一个管道,然后再创建 3 个子进程, 并由这三个子进程利用管道与父进程之间进行通信:子进程发送随机长度的信息 内容给父进程,父进程等三个子进程全部发完消息后再接收信息,请用到sem_wait,sem_post等函数以及Linux最后编译语句
时间: 2024-02-18 13:03:39 浏览: 68
好的,下面是一个使用信号量实现的管道程序,满足您的要求:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#define MSG_SIZE 50 // 定义消息的最大长度
int main() {
int fd[2]; // 管道文件描述符
pid_t pid[3]; // 子进程 ID
int status; // 子进程退出状态
int i;
srand(time(NULL)); // 随机数种子
if (pipe(fd) < 0) { // 创建管道
perror("pipe");
exit(1);
}
// 创建信号量
sem_t *sem_send = sem_open("sem_send", O_CREAT | O_EXCL, 0666, 0);
sem_t *sem_recv = sem_open("sem_recv", O_CREAT | O_EXCL, 0666, 0);
if (sem_send == SEM_FAILED || sem_recv == SEM_FAILED) {
perror("sem_open");
exit(1);
}
for (i = 0; i < 3; i++) { // 创建 3 个子进程
pid[i] = fork();
if (pid[i] < 0) {
perror("fork");
exit(1);
} else if (pid[i] == 0) { // 子进程
close(fd[0]); // 关闭管道的读端
char msg[MSG_SIZE];
int len = rand() % MSG_SIZE; // 随机生成消息长度
int j;
for (j = 0; j < len; j++) { // 随机生成消息内容
msg[j] = 'A' + rand() % 26;
}
msg[len] = '\0'; // 字符串结束符
printf("Child %d sends message: %s\n", i, msg);
sem_wait(sem_send); // 等待发送信号量
write(fd[1], msg, strlen(msg) + 1); // 发送消息
sem_post(sem_recv); // 发送接收信号量
exit(0);
}
}
// 父进程
close(fd[1]); // 关闭管道的写端
for (i = 0; i < 3; i++) { // 发送发送信号量
sem_post(sem_send);
}
for (i = 0; i < 3; i++) { // 等待 3 个子进程全部发完消息
waitpid(pid[i], &status, 0);
}
char recv_msg[MSG_SIZE];
int total_len = 0;
for (i = 0; i < 3; i++) { // 接收接收信号量
sem_wait(sem_recv);
while (read(fd[0], recv_msg + total_len, MSG_SIZE - total_len) > 0) { // 接收消息
total_len = strlen(recv_msg) + 1;
}
}
printf("Parent receives message: %s\n", recv_msg);
// 关闭并删除信号量
sem_close(sem_send);
sem_close(sem_recv);
sem_unlink("sem_send");
sem_unlink("sem_recv");
return 0;
}
```
您可以将上面的代码保存到一个名为 `pipe.c` 的文件中,然后使用以下命令编译:
```
gcc pipe.c -o pipe -lpthread
```
这将生成一个名为 `pipe` 的可执行文件。注意,由于使用了信号量,因此需要链接 pthread 库(使用 `-lpthread` 选项)。您可以运行它来测试管道程序的运行结果。
注意:由于随机数种子使用了当前时间,因此每次运行结果可能会不同。
阅读全文