操作系统第3次实验报告:管道

  • 袁祎琦
  • 201821121033
  • 计算1812

1. 编写程序

  创建命名管道是用FIFO.c文件实现,对管道进行写是FIFOwrite.c来实现的,对管道进行读是FIFOread.c来实现的。

1、如果创建成功,那么mkfifo()返回0,如果失败,那么返回-1。

2、后面的操作,把这个命名管道当作文件进行操作,包括:open(),write(),read(),close()。

3、打开命名管道 int fd = open(char name,int how);

  name表示文件名字字符串,how指的是打开的模式:

  O_RDONLY(只读),
  O_WRONLY(只写),
  O_RDWR (可读可写),成功的话返回一个正整数,失败的话返回-1

注意:使用open()打开命名管道时可能会导致阻塞,如果同时用读写方式(O_RDWR)打开,则一定不会导致阻塞。

用法:对于下面三个文件,首先编译并运行FIFO.c文件(功能是创建命名通道),然后编译FIFOwrite.c和FIFOread.c文件,运行这两个文件生成的可执行程序,然后在write端发送信息,看read端是否可以接收到。

 1 //FIFO.c文件
 2 //此文件的功能是创建管道,这样在后续的读写代码中就不用判断管道是否存在。
 3 #include <stdio.h>
 4 #include <unistd.h>
 5 #include <sys/types.h>
 6 #include <sys/stat.h>
 7  
 8  //创建命名管道
 9 int main(){
10    int  ret = mkfifo("fifo2",0777);
11    if(ret == -1){
12       perror("mkfifo");
13       return -1;  
14    }  
15    return 0;
16 }

 

 1 //FIFOwrite.c文件
 2 #include <stdio.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <string.h>
 7 #include <fcntl.h>
 8 #define SIZE 1024
 9 //从终端输入,并将输入写入管道
10 int main(){
11      int fd = open("fifo2", O_WRONLY);//以只写的方式打开命名管道文件  
12      if (fd== -1){
13           perror ("mkfifo");
14           return -1;
15       }
16       char buf[SIZE];
17       while (1){
18           fgets (buf, SIZE, stdin);
19           write (fd, buf, strlen(buf));//写数据
20       }
21       return 0;
22  }

 

 1 //FIFOread.c文件
 2 #include <stdio.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <string.h>
 7 #include <fcntl.h>
 8 #define SIZE 1024
 9 
10 //从管道内读数据
11 int main(){
12      int fd = open("fifo2", O_RDONLY);//以只读的方式打开命名管道
13      if (fd == -1){
14          perror ("mkfifo");
15          return -1;
16      }
17      char buf[SIZE];
18      while (1){
19          int ret = read (fd, buf, SIZE);//读数据
20          buf[ret] = '\0';
21          printf ("读到 %d 字节: %s\n", ret, buf); 
22      }
23       return 0;
24 }

2. 分析运行结果

        这个管道的读和写类似于聊天,一段“发送”,一端“接收”,在“写端”中输入需要传输到“读端”的内容,通过创建的管道,我创建的管道名为fifo2,然后“读端”接受“写端”输入的数据,另外还对输入的字符长度进行了统计。

  只有在“写端”写入内容并,“读端”才会接收到内容。

 

 

3. 通过该实验产生新的疑问及解答

1、open()调用的阻塞是怎么回事?

答:对于只读方式,如果是open(char name,O_RDONLY),除非有一个进程以写的方式打开同一个命名管道,否则不返回;如果是open(char name,O_RDONLY | O_NONBLOCK),则即使没有其他进程以写的方式打开同一个命名管道,open()的调用也会成功并立即返回。

类似的,对于只写方式,如果open(char name,O_WRONLY),除非有一个进程以只读方式打开同一命名管道,否则open()调用将被阻塞;如果是open(char name,O_WRONLY|O_NONBLOCK),open()会立即返回,但要是没有其他进程以只读方式打开同一命名管道,open()将返回-1。

2、三个及三个以上的进程在命名管道进行通信,会不会信息混乱?

答:前面的例子是两个进程之间的通信问题,如果要是有多个进程同时向同一个FIFO写数据,而只有一个读进程在同一个FIFO内读取数据。

比如一个人输入:你好小明,另一个人输入:妈妈,那么那个read端本来是小明操作,但是他接收到的是:你好小明妈妈。这样是不是会很尴尬,当然,这是我个人的设想,我一个人无法同时发送这两句话,所以这个验证没有成功。感觉理论上是会发生的,因为,如下,两个write都输入一句话,read都接收到了,如果两个write同时输入,是不是就……

 

3、想结束这个通信进程的话要怎么做?

答:由于对终端的操作还不是很熟练,上面的write端一直回车就是不结束,后面在网上搜索到ctrl+c可以结束进程。

 

4. 加分项

上述代码实现的是单程通信,即只有在“写端”写入内容时“读端”才接收消息,能否改造上述代码,使之实现双向通信?

思路是,一方先发起通信,将输入通道打开并且输入数据之后,立即关闭输入通道,然后打开接收通道,等待接收对方的信息;然后另一方打开接收通道接收对方发送的信息,接收成功后关闭接收通道,然后打开写入通道回复对方消息。所以,以下的程序只支持每次一条信息的发送,除非一行输入好几句话再回车。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <fcntl.h>
 4 #include <sys/stat.h>
 5 #include <sys/types.h>
 6 #include <unistd.h>
 7 int main(){
 8      int fd;
 9      char * myfifo = "/home/yuanyiqi/fifo3";//FIFO路径
10      mkfifo(myfifo, 0666);
11      char read1[100], write1[100];//两个数组存储双方的字符
12      while (1){
13          fd = open(myfifo, O_WRONLY);//只写打开FIFO
14          fgets(write1, 100, stdin);//write先发出信息
15          write(fd, write1, strlen(write1)+1);//写入缓冲
16          close(fd);//write关闭
17          fd = open(myfifo, O_RDONLY);//只读打开FIFO
18          read(fd, read1, sizeof(read1));//读取对方数据
19          printf("User2: %s\n", read1);//显示对方发送内容
20          close(fd);
21      }
22      return 0;
23  }
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <fcntl.h>
 4 #include <sys/stat.h>
 5 #include <sys/types.h>
 6 #include <unistd.h>
 7 int main(){
 8      int fd1;
 9      char * myfifo = "/home/yuanyiqi/fifo3";//FIFO路径
10      mkfifo(myfifo, 0666);
11      char read1[100], write1[100];//两个数组存储双方的字符
12      while (1){ //跟write相反
13          fd1 = open(myfifo,O_RDONLY);//只读打开FIFO
14          read(fd1, read1, 100);//读取对方发送的信息
15          printf("User1: %s\n", read1);//显示对方发送内容
16          close(fd1);//read关闭
17          fd1 = open(myfifo,O_WRONLY);//只写打开FIFO
18          fgets(write1, 100, stdin);//恢复对方
19          write(fd1, write1, strlen(write1)+1);//写数据
20          close(fd1);
21      }
22      return 0;
23  }

 

参考链接:

https://blog.csdn.net/daaikuaichuan/article/details/82827994

https://blog.csdn.net/maizi_hsx/article/details/78645791

posted @ 2020-04-16 01:58  DAY--BY--DAY  阅读(330)  评论(0编辑  收藏  举报