这篇博文记录操作系统实验之管道通信。

实验目的

编程实现进程的管道通信,通过观察、分析实验现象,深入理解进程管道通信的特点,掌握管道通信的同步和互斥机制。

实验准备

  1. 管道通信:
    所谓“管道”,是指用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件,又名pipe文件。向管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入管道;而接受管道输出的接收进程(即读进程),则从管道中接收(读)数据。由于发送进程和接收进程是利用管道进行通信的,故又称为管道通信。这种方式首创于UNIX系统,由于它能有效地传送大量数据,因而又被引入到许多其它操作系统中。
    为了协调双方的通信,管道机制必须提供以下三方面的协调能力:
    • 互斥,即当一个进程正在对pipe执行读/写操作时,其它(另一)进程必须等待。
    • 同步,指当写(输入)进程把一定数量(如4KB)的数据写入pipe,便去睡眠等待,直到读(输出)进程取走数据后,再把他唤醒。当读进程读一空pipe时,也应睡眠等待,直至写进程将数据写入管道后,才将之唤醒。
    • 确定对方是否存在,只有确定了对方已存在时,才能进行通信。
  2. Linux下的C程序设计-管道:
    管道是进程间通信的一种简单易用的方法。管道分为匿名管道和命名管道两种。下面首先介绍匿名管道。
    匿名管道只能用于父子进程之间的通信,它的创建使用系统调用pipe():int pipe(int fd[2])
    其中的参数fd用于描述管道的两端,其中fd[0]是读端,fd[1]是写端。两个进程分别使用读端和写端,就可以进行通信了。
    命名管道可以用于任何管道之间的通信。命名管道实际上就是一个FIFO文件,具有普通文件的所有性质,用ls命令也可以列表。但是,它只是一块内存缓冲区。

程序流程图

管道通信流程图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>
int pid1, pid2;
int main()
{
int fd[2];
char OutPipe[100], InPipe[100];
pipe(fd);
while ((pid1 = fork()) == -1);
if (pid1 == 0)
{
lockf(fd[1], 1, 0);
sprintf(OutPipe, "\n Child process 1 is sending message!\n");
write(fd[1], OutPipe, 50);
sleep(5);
lockf(fd[1], 0, 0);
exit(0);
}
else
{
while ((pid2 = fork()) == -1);
if (pid2 == 0)
{
lockf(fd[1], 1, 0);
sprintf(OutPipe, "\n Child process 2 is sending message!\n");
write(fd[1], OutPipe, 50);
sleep(5);
lockf(fd[1], 0, 0);
exit(0);
}
else
{
wait(0);
read(fd[0], InPipe, 50);
printf("%s\n", InPipe);
wait(0);
read(fd[0], InPipe, 50);
printf("%s\n", InPipe);
exit(0);
}
}
return 0;
}

运行结果

运行结果
符合预期!

end