linux 有P1,P2,P3三个进程,P1和P2负责从键盘接收字符串,均发送给P3,P3接收到字符串,根据发送方分别显示”P3 received *** from P1(或P2)" ;分别用管道通信,消息队列和共享存储三种通信方式实现。
时间: 2024-02-06 19:10:41 浏览: 66
使用管道通信方式实现:
首先创建两个管道,用于P1和P2分别向P3发送字符串,P3从这两个管道中读取数据。
```c
int fd1[2], fd2[2];
if (pipe(fd1) < 0 || pipe(fd2) < 0) {
perror("pipe error");
exit(1);
}
```
P1和P2的代码如下:
```c
char buf[1024];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
write(fd1[1], buf, strlen(buf));
}
close(fd1[1]);
```
P2的代码与P1的代码类似,这里不再赘述。
P3的代码如下:
```c
char buf[1024];
close(fd1[1]); // P1的写端不需要了
close(fd2[1]); // P2的写端不需要了
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd1[0], &read_fds);
FD_SET(fd2[0], &read_fds);
while (select(max(fd1[0], fd2[0]) + 1, &read_fds, NULL, NULL, NULL) > 0) {
if (FD_ISSET(fd1[0], &read_fds)) {
int n = read(fd1[0], buf, sizeof(buf));
if (n <= 0) {
break;
}
buf[n] = '\0';
printf("P3 received %s from P1\n", buf);
}
if (FD_ISSET(fd2[0], &read_fds)) {
int n = read(fd2[0], buf, sizeof(buf));
if (n <= 0) {
break;
}
buf[n] = '\0';
printf("P3 received %s from P2\n", buf);
}
FD_ZERO(&read_fds);
FD_SET(fd1[0], &read_fds);
FD_SET(fd2[0], &read_fds);
}
```
使用消息队列通信方式实现:
首先创建两个消息队列,用于P1和P2分别向P3发送字符串,P3从这两个消息队列中读取数据。
```c
int msqid1, msqid2;
if ((msqid1 = msgget(IPC_PRIVATE, IPC_CREAT | 0666)) < 0 || (msqid2 = msgget(IPC_PRIVATE, IPC_CREAT | 0666)) < 0) {
perror("msgget error");
exit(1);
}
```
P1和P2的代码如下:
```c
struct msgbuf msg;
msg.mtype = 1;
while (fgets(msg.mtext, sizeof(msg.mtext), stdin) != NULL) {
if (msgsnd(msqid1, &msg, strlen(msg.mtext), 0) < 0) {
perror("msgsnd error");
exit(1);
}
}
msgctl(msqid1, IPC_RMID, NULL);
```
P2的代码与P1的代码类似,这里不再赘述。
P3的代码如下:
```c
struct msgbuf msg;
int len;
while ((len = msgrcv(msqid1, &msg, sizeof(msg.mtext), 0, 0)) > 0) {
msg.mtext[len] = '\0';
printf("P3 received %s from P1\n", msg.mtext);
}
while ((len = msgrcv(msqid2, &msg, sizeof(msg.mtext), 0, 0)) > 0) {
msg.mtext[len] = '\0';
printf("P3 received %s from P2\n", msg.mtext);
}
msgctl(msqid1, IPC_RMID, NULL);
msgctl(msqid2, IPC_RMID, NULL);
```
使用共享存储通信方式实现:
首先创建一个共享内存,用于P1和P2向P3发送字符串,P3从这个共享内存中读取数据。
```c
int shmid;
if ((shmid = shmget(IPC_PRIVATE, sizeof(char) * 1024, IPC_CREAT | 0666)) < 0) {
perror("shmget error");
exit(1);
}
```
P1和P2的代码如下:
```c
char* shmaddr = (char*)shmat(shmid, NULL, 0);
if (shmaddr == (char*)-1) {
perror("shmat error");
exit(1);
}
while (fgets(shmaddr, sizeof(char) * 1024, stdin) != NULL) {
if (kill(getppid(), SIGUSR1) < 0) {
perror("kill error");
exit(1);
}
pause();
}
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
```
P2的代码与P1的代码类似,这里不再赘述。
P3的代码如下:
```c
char* shmaddr = (char*)shmat(shmid, NULL, 0);
if (shmaddr == (char*)-1) {
perror("shmat error");
exit(1);
}
signal(SIGUSR1, handler);
while (1) {
pause();
printf("P3 received %s from %s\n", shmaddr, sender);
if (kill(sender_pid, SIGUSR2) < 0) {
perror("kill error");
exit(1);
}
}
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
```
其中handler函数和sender和sender_pid变量的定义如下:
```c
void handler(int sig) {
if (sig == SIGUSR1) {
if (sender == NULL) {
sender = "P1";
sender_pid = p1_pid;
} else if (sender == "P1") {
sender = "P2";
sender_pid = p2_pid;
} else {
perror("unknown sender");
exit(1);
}
} else if (sig == SIGUSR2) {
// do nothing
} else {
perror("unknown signal");
exit(1);
}
}
```
完整代码如下:
阅读全文