zoukankan      html  css  js  c++  java
  • 操作系统第3次实验报告:管道

    0.个人信息

    • 姓名 罗廷杨
    • 学号 201821121013
    • 班级 计算1811

    1. 编写程序

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

    1.fifo_write.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<string.h>
    #include<fcntl.h>
    #include<errno.h>
    #include<signal.h>
    #define MAX 128
    #define FIFO "./fifo"
    
    //写端
     void delSignal(int sig){
          printf("读端已经关闭!!SIGPIPE的信号值为%d
    ",sig);
         exit(-1);
     }
    
     int main(){
     
         //读端直接关闭,写端写完数据就会发送这个信号终止进程
         signal(SIGPIPE,delSignal);
         //建立自命名管道
         if(mkfifo(FIFO, 0640) == -1)
         {
             if(errno != EEXIST)//如果错误类型是fifo类型文件已经存在那么继续执行
             {
                 perror("mkfifo");
                 exit(-1);
             }
         }
          char buff[MAX];
          int fw=open(FIFO,O_WRONLY);//以只写的形式打开有名管道文件fifo
          if(fw==-1){//fifo文件打开失败
              printf("自命名管道文件打开失败!!!
    ");
              exit(-1);
          }
          //fifo文件打开成功
          printf("请输入要写入管道的内容(输入##结束)
    ");
         while(1){
              memset(buff, 0, sizeof(buff));
              fgets(buff,MAX,stdin);//获取用户输入一行的值
              if(strcmp(buff,"##
    ")==0){//判断是否结束写入
                  break;
              }
              write(fw,buff,strlen(buff));//将用户输入的值将写入fifo
          }
          close(fw);
          return 0;
      }

    2.fifo_read.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<errno.h>
    #define MAX 128
    #define FIFO "./fifo"
    //读端
     int main(){
    
         if(mkfifo(FIFO, 0640) == -1)
          {
              if(errno != EEXIST)//如果错误类型是fifo类型文件已经存在那么继续执行
               {
                   perror("mkfifo");
                   exit(-1);
              }
           }
    
    
         char buff[MAX]={0};
         int count=0;
         int fr=open(FIFO,O_RDONLY);//以只读的形式打开有名管道文件fifo
         if(fr==-1){//fifo文件打开失败
             printf("自命名管道文件打开失败!!!
    ");
             exit(-1);
         }
         //fifo文件打开成功
         printf("从管道中读取的内容为
    ");
         while(read(fr,buff,MAX)!=0){//写入端还未关闭
             count++;
             printf("第%d次读取的内容:%s",count,buff);//取出写入端写入fifo中的内容
             memset(buff, 0, sizeof(buff));
         }
         printf("写文件端已经关闭!!!
    ");
         close(fr);
         return 0;
    }

    2. 分析运行结果

    1.正常执行情况下的运行结果

    ./write的运行结果

     ./read的运行结果

    当运行./write和./read但是还没有往管道里面写入数据时,./write和./read都会先处于阻塞状态,我们可以观察到两个程序都没有继续运行。当在./write程序中输入数据,这时./write程序就会往管道内写入数据,数据写入完成后就会被./read程序检测到,然后将数据读出显示到控制台中。当往./write中输入##那么写程序就结束执行,这样一来./read程序就无法在管道内读取到数据,因此也结束执行。

    2../write强制退出的运行结果

    ./write的运行结果

    ./read的运行结果

     

    ./write程序强制退出,也就是说没有程序往管道中写入数据了,那么./read就无法从管道中读取数据因此也随之结束运行。

    3../read强制退出的运行结果

    ./read的运行结果

    ./write的运行结果

     

     当./read程序强制退出之后,./write程序再往管道中写入数据那么就会产生异常,继而产生信号--SIGPIPE(13)来结束运行。

    说明

    创建命名管道的方式有两种,一种是在程序中创建,另一种是直接在命令行中创建。

    1.在程序中创建

    使用函数  int mkfifo(const char *filename, mode_t mode);

    其中mode(管道模式)有如下几种:

      O_RDONLY:读管道。

      O_WRONLY:写管道。

      O_RDWR:读写管道。

      O_NONBLOCK:非阻塞。

      O_CREAT:如果该文件不存在,就创建一个新的文件,并使用第3个参数为其设置权限。

      O_EXCL:测试文件是否存在。

    2.使用命令行创建

    mkfifo  filename

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

    疑问:signal(SIGPIPE,delSignal);的处理过程是什么样子的?

    解答:signal是一个带signum和handler两个参数的函数,需要处理的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出,此处signum对应于SIGPIPE,handler对应于delSignal。./write程序执行过程中,当./read进程结束信号没有发生时,./write进程正常运行,当信号发生时,./write进程的正常运行会被中断,然后去处理SIGPIPE信号,一看需要处理的信号是SIGPINE,就会从“信号处理方式登记表”中找到对应的信号处理函数,此处是delSignal函数,然后取出该函数的地址并执行该函数,从而打印出相应的提示信息并结束./write进程。

    参考文献

    【1】https://blog.csdn.net/qq_39755395/article/details/78568953

    【2】https://www.cnblogs.com/zhanggaofeng/p/6075725.html

  • 相关阅读:
    January 25th, 2018 Week 04th Thursday
    January 24th, 2018 Week 04th Wednesday
    January 23rd, 2018 Week 04th Tuesday
    January 22nd, 2018 Week 04th Monday
    January 21st, 2018 Week 3rd Sunday
    January 20th, 2018 Week 3rd Saturday
    January 19th, 2018 Week 3rd Friday
    January 18th, 2018 Week 03rd Thursday
    January 17th, 2018 Week 03rd Wednesday
    January 16th, 2018 Week 03rd Tuesday
  • 原文地址:https://www.cnblogs.com/lty1661489001/p/12708601.html
Copyright © 2011-2022 走看看