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

 零、个人信息

  • 姓名:陈韵
  • 学号:201821121053
  • 班级:计算1812

 一、编写程序

   在服务器上用Vim编写程序:创建一个命名管道,创建两个进程分别对管道进行读 fifo_read.c 与写 fifo_write.c。给出源代码如下

   fifo_read.c:

 1 #include <stdio.h>
 2 #include <sys/stat.h>
 3 #include <stdlib.h> // exit
 4 #include <fcntl.h>  //权限
 5 #include <errno.h>
 6 int main()
 7 {
 8     int fd;
 9     int count = 0;  //用于存储读取到的数据个数
10     int len;        //从fifo中读取的数据长度
11     char buf[1024]; //数据流
12     //创建fifo管道
13     //创建fifo 授予可读可写的权限,同时确认是fifo创建失败而非文件已经存在。
14     if (mkfifo("fifo", 0666) < 0 && errno != EEXIST)
15     {
16         perror("创建fifo失败!");
17     }
18     //创建成功 以只读方式打开fifo
19     if ((fd = open("fifo", O_RDONLY)) < 0)
20     {
21         perror("打开fifo失败!");
22         exit(1);
23     }
24     //读取fifo管道
25     while ((len = read(fd, buf, 1024)) > 0)
26     {
27         count++;
28         printf("读取到的信息%d为:%s\n", count, buf);
29     }
30     printf("写入端关闭!");
31     close(fd);
32     return 0;
33 }

 

   fifo_write.c:

 1 #include <stdio.h>
 2 #include <sys/stat.h>
 3 #include <stdlib.h> // exit
 4 #include <fcntl.h>  //权限
 5 
 6 int main()
 7 {
 8     int fd;         //存放open的返回值
 9     char buf[1024]; //存放数据流
10 
11     printf("我是进程:%d,现在开始写入数据。\n若想停止输入请按~。 \n", getpid());
12     //以只写打开fifo
13     if ((fd = open("fifo", O_WRONLY)) < 0)
14     {
15         perror("打开fifo失败!");
16         exit(1);
17     }
18     //打开fifo成功  开始写入数据
19     while (1)
20     {
21         scanf("%s", buf);
22         //用于判断是否停止读入
23         if (strcmp(buf, "~") == 0)
24             break;
25         //根据输入的值 写入fifo中
26         if (write(fd, buf, strlen(buf) + 1) < 0)
27         {
28             perror("写入fifo失败!");
29             close(fd); //关闭打开的fifo
30             exit(1);
31         }
32         printf("写入FIFO:%s\n", buf);
33     }
34     close(fd);
35     return (0);
36 }

 

 二、分析运行结果

   1、先确保打开2个命令行窗口,一个用于读入,一个用于写入。并分别编译 fifo_read.cfifo_write.c

    

     

 

 2、先运行读端:fifo_read.c。此时用ls命令会发现fifo_read.c运行时所创建的FIFO文件

 

   后运行写端:fifo_write.c。开始键入数据,最后以 " ~ " 停止输入。

 

 

    3、过程分析

    • 当运行fifo_read.c与fifo_write.c后,因为写端还没有写入数据,此时的读端会处于阻塞状态,以等待写端的数据写入。于此同时写端也在等待用户键入数据。  
    • 当用户从写端键入数据后,写端的控制台会显示用户已经写入FIFO的数据,于此同时读端也会马上读取到用户刚刚写入的数据,并显示出来。
    • 当用户键入“ ~ ” 后,写端停止写入,并关闭打开的FIFO,进程结束。与此同时读端因为没有读取到数据,打印出写入端关闭,进程结束

   4、小结:  

    • 使用FIFO进行通信,每次传输的数据一定要在大小之内。 
    • 对FIFO的访问实际上可以转化成对文件的访问,诸如open/write/read等都是行得通滴。
    • open以及mkfifo的第二个参数为文件的权限,常见的有:
      •     O_RDONLY          以只读的方式打开
      •     O_WRONLY          以只写的方式打开
      •     O_RDWR              以可读写的方式打开
    • 同时注意open一个FIFO,根据是否设置非阻塞标志,有不同的情况:
      • 默认为没有指定非阻塞标志,如本次实验。
        • 只读open要阻塞到某个进程为写,才打开FIFO。
        • 只写open同样要阻塞到某个进程为读,才打开它。
      • 若指定了非阻塞标志
        • 只读open立即返回。
        • 只写open将出错,并返回-1。
    • 使用到FIFO的情况:
      •  如本次实验,一个进程读数据,一个进程写数据。
      •     实现client/server架构,客户端和服务端进行通信。

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

  1.管道pipe和命名管道FIFO,他们之间的差异是什么?是什么导致了这个差异???

   FIFO可以用于任意2个进程的通信,而pipe只能用于父子进程、兄弟进程等具有血缘关系的进程之间的通信。

   我们可以通过ls命令查看FIFO在文件系统中对应的inode,就是因为有了名字,所以它可用于任意两个进程之间的通信。而pipe没有名           字,在现有的文件系统中,都无法查找到它的存在。

    

 

 

   2.如果FIFO可以实现C/S架构,那么可不可以实现多个客户端向同一个服务端发送信息?

   可见目前的FIFO有多个写进程。问题来了,服务器端如何把回答送至各个对应的客户端呢?很显然此时不能再利用单个FIFO了。通过查  阅相关资料发现了一种可行的解决办法:每个客户进程都在请求中包含他自己的进程ID,然后服务器进程为每个客户进程独立创建一个            FIFO。

 

posted @ 2020-04-17 17:16  韵韵韵  阅读(266)  评论(0编辑  收藏  举报