进程间通信(管道)

进程间通信(ipc):管道 信号量 共享内存 消息队列 套接字

管道文件:本身在磁盘中,打开文件以后会在内存中分配空间.(写入的数据存放在内存中)

有名管道和无名管道的区别:

有名管道可以在任意两个进程间通信
无名管道只能在父子进程间使用

管道通信方式:半双工
写入管道的数据在内存中
有名管道:(1)有名管道,如果一个进程以只写方式打开,进程会在open阻塞运行,直到另一个进程以只读方式打开;同理,一个进程以只读方式打开,进程也会在open阻塞运行,直到另一个进程以只写方式打开;因此当管道文件同时已读写方式打开才有意义。
(2)read端会阻塞运行,直到写端写入数据或者写端关闭。

有名管道:mkfifo,mkfifo();
无名管道:pipe();

有名管道

在这里插入图片描述

管道为空,读会阻塞
管到写满,写会阻塞
管道写端关闭,读端返回为0
管道读端关闭,写端写入数据异常
利用管道实现进程间通信
一个进程向管道文件写数据一个文件从管道中读数据

向管道中写数据
 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<string.h>
 #include<assert.h>
 #include<fcntl.h>
 
 int main(){
 
     int fdw=open("fifo",O_WRONLY);//只写方式打开管道文件
     assert(fdw!=-1);
 
     printf("fdw=%d\n",fdw);
     while(1){
          char buff[128]={0};
          printf("input:\n");
          fgets(buff,128,stdin);//从键盘读入字符串
          if(strncmp(buff,"end",3)==0){//输入end是跳出循环,写端关闭
            break;
          }
 
          write(fdw,buff,strlen(buff));//向管道文件中写数据
      }
     close(fdw);//关闭管道文件
 
     exit(0);
 
 }

从管道中读数据
 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<string.h>
 #include<assert.h>
 #include<fcntl.h>
 
 int main(){
 
     int fdr=open("fifo",O_RDONLY);//以只读方式打开管道文件
     assert(fdr!=-1);
 
     printf("fdr=%d\n",fdr);
 
     while(1){
          char buff[128]={0};
          int n=read(fdr,buff,127);//从管道读数据并写到buff中
          if(n==0){
            break;
          }
          printf("buff=%s\n",buff);
     }
     close(fdr);//关闭管道文件
      
     exit(0);
 }

单独执行 读操作的进程和写操作的进程

在这里插入图片描述
可以看出a 和 b进程都没有执行。
因为,只有一个进程以读或者以写方式打开时会阻塞在open这块。只有两个进程分别以读或者以写方式打开时才会正常执行。

在这里插入图片描述
此时两个进程一起打开管道文件,一个写一个读(hello有换行是由于读入\n),进程才能正常执行。

管道写端关闭,读端返回0
在这里插入图片描述
写端关闭后,读端read返回值为0退出循环执行关闭文件。

管道读端关闭,写端写入数据触发异常。
在这里插入图片描述
关闭读端时,写端输入数据开始执行write时触发异常,此处通过发信号实现。

无名管道

int pipe(int pipefd[2]);
pipefd:用来存放PIPE的读写端描述符
pipe(fd) //fd[0]是读端口,fd[1]是写端口.

 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<string.h>
 #include<assert.h>
 #include<fcntl.h>
 #include<signal.h>
 
 int main(){
 
     int fd[2];
     int res=pipe(fd);  //创建无名管道
     assert(res!=-1);
 
     pid_t pid=fork();
     assert(pid!=-1);
 
     if(pid==0){//子进程负责读
     
         close(fd[1]);//关闭写端
         
         while(1){
         char buff[128]={0};
         int n=read(fd[0],buff,127);
         if(n==0) break;//读端关闭read返回值为0,退出循环
         printf("child buff=%s\n",buff);
         }
         
         close(fd[0]);//读完之后关闭读端
     }else{//父进程负责写端
         close(fd[0]);//关闭读端
         
         while(1){
         char buff[128]={0};
         printf("input:");
         fgets(buff,128,stdin);//从键盘获取数据
         if(strncmp("end",buff,3)==0) break;//输入为end执行结束,跳出循环关闭写端
         write(fd[1],buff,strlen(buff));
         }
         
         close(fd[1]);//关闭写端
     }
     exit(0);
 }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值