管道

管道

  • 匿名管道
  • 命名管道

    匿名管道:

    创建:命令|创建、函数int pipe(int pipefd[2]);创建
    pipe创建匿名管道:
    父进程fork出子进程,父进程关闭读端、子进程关闭写端。如图,
    这里写图片描述
    :0、1、2、3、4是文件描述符
    管道特点:

  • 只能用于具有亲缘关系的进程间通信
  • 管道提供流式服务
  • 管道生命随进程,即进程结束,管道释放
  • 一般情况下,内核对管道操作进行同步与互斥

    管道读写规则:

  • 没有数据可读
    不指定O_NONBLOCK:read调用阻塞,即进程暂停执行,一直等到有数据来为止。
    指定O_NONBLOCK:read调用返回-1,errno值为EAGAIN。

  • 当管道满的时候
    不指定O_NONBLOCK:write调用阻塞,知道有进程读走数据
    指定O_NONBLOCK:调用返回-1,errno值EAGAIN。

  • 如果写端文件描述符关闭,read返回为0;

  • 如果读端文件描述符关闭,写端产生SIGPIPE信号 ,导致写端进程退出。
    读端关闭时实现代码如下:
  1 #include<unistd.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<stdio.h>
  5 
  6 int main()
  7 {
  8     int fd[2];
  9     if(pipe(fd)<0)
 10     {
 11         perror("pipe");
 12         exit(1);
 13     }
 14     pid_t pid = fork();
 15     if(pid<0){perror("fork");exit(1);}
 16     if(pid==0)
 17     {
 18     close(fd[1]);
 19         int count = 0;
 20         while(1){
 21         char buf[1024] = {0};
 22         int s = read(fd[0],buf,sizeof(buf)-1);
 23         if(s>0)
 24         {
 25             count++;
 26             buf[s] = '\0';
 27             printf("child read # %s\n",buf);
 28             fflush(stdout);
 29         }
 30             if(count>5){
 31                 printf("child exit\n");
 32                 break;
 33         }
 39         }
 40         exit(0);
 41     }else
 42     {
 43         close(fd[0]);
 45         while(1){
 46         char buf[1024] = {0};
 47         sleep(1);
 50         printf("parent write#");
 51         fflush(stdout);
 52         scanf("%s",buf);
 53         write(fd[1],buf,strlen(buf));
 62     exit(0);
 63 }

结果如下:
这里写图片描述
写端关闭实现代码:

  1 #include<unistd.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<stdio.h>
  5 
  6 int main()
  7 {
  8     int fd[2];
  9     if(pipe(fd)<0)
 10     {
 11         perror("pipe");
 12         exit(1);
 13     }
 14     pid_t pid = fork();
 15     if(pid<0){perror("fork");exit(1);}
 16     if(pid==0)
 17     {
 18     close(fd[1]);
 19         while(1){
 20         char buf[1024] = {0};
 21         int s = read(fd[0],buf,sizeof(buf)-1);
 22         if(s>0)
 23         {
 24             buf[s] = '\0';
 25             printf("child read # %s\n",buf);
 26             fflush(stdout);
 27         }
 28         else
 29         {
 30             printf("child exit\n");
 31             break;
 32         }
 33         }
 34         exit(0);
 35     }else
 36     {
 37         close(fd[0]);
 38         int count = 0;
 39         while(1){
 40         char buf[1024] = {0};
 41         sleep(1);
 42         if(count<5)
 43         {
 44         printf("parent write#");
  44         printf("parent write#");
 45         fflush(stdout);
 46         scanf("%s",buf);
 47         write(fd[1],buf,strlen(buf));
 48         count++;
 49         }else
 50         {
 51             printf("parent exit");
 52             break;
 53         }
 54     }
 55     }
 56     exit(0);
 57 }

这里写图片描述

命名管道:

匿名管道只能在具有亲缘关系的进程之间传递通信,命名管道可以实行根本不相关的进程通信。
创建:mkfifo命令、int mkfifo(const char *pathname, mode_t mode);函数
这里写图片描述
这里写图片描述
匿名管道与命名管道之间唯一的区别是创建方式的不同,一旦这些工作完成后,具有相同的语义

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页