Linux——进程间通信之管道

作者:小 琛
欢迎转载,请标明出处

每一个进程都是拥有自己独立的虚拟地址空间和页表结构,促使了进程独立,这也导致了进程之间合作存在问题,为了解决该问题,产生了进程间的通信。

管道

管道的本质:管道其实是内核当中的一块内存,相当于为进程通信而创建的缓冲区。

  • 无名管道
  • 有名管道

无名管道

  1. 无名管道的特性:

1、用于具有亲缘关系的进程
2、半双工,即数据流向唯一,只能从写端到读端
3、提供字节服务,即读和写都仅仅有两种状态:成功和失败,不会出现读一半或写一半
4、当读端读取后,数据就直接被拿走,不再存在于管道中
5、生命周期伴随进程

当读端不读,写端一直在写,管道写满的时候,写端就进行阻塞。
当写端不屑,读端一直在读,管道为空的时候,读端就进行阻塞

  1. 创建无名管道的函数

int pipe(int fd[2]); 成功返回0,失败返回-1
fd[2]数组是一个出参,意味着我们在使用的时候要定义一个数组。该数组返回创建管道的读端、写端自身的文件描述符。
fd[0]为读端,fd[1]为写端

  1. 测试管道的大小:
//测试管道的大小
 17 void test2()
 18 {
 19     int fd[2];
 20     int ret = pipe(fd);
 21     if (ret < 0)
 22     {
 23        perror ("pipe");
 24     }
 25     int count=0;
 26     while (1)
 27     {
 28         int writesize=0;
 29         writesize=write(fd[1],"1",1);
 30         if (writesize < 0)
 31             break;
 32         printf("[%d]\n",count++);
 33     }
 34     
 35 }

结果:
在这里插入图片描述
也就是说,共65535个字节,即64个字节

  1. 无名管道应用简单例子
 39 void test3()
 40 {
 41     int fd[2];
 42     int ret=pipe(fd);
 43     if (ret < 0)
 44         perror("pipe");
 45     int temp=fork();
 46     if (temp < 0)
 47         perror("fork");
 48     if (temp == 0)
 49     {
 50         write(fd[1],"hello",5);
 51         //child
 52     }
 53     else
 54     {
 55         //father
 56         wait(NULL);
 57         char arr[10];
 58         read(fd[0],arr,5);
 59         printf("I read %s\n",arr);
 60     }                                                                                                                        
 61 }

在这里插入图片描述

有名管道

无名管道应用的一个最大限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,则无法支持。有名管道由此产生。

  1. 有名管道的创建

int mkfifo(const char *filename,mode_t mode);
filename:创建管道文件的名称 mode:权限

  1 #include "stdio.h"
  2 #include "unistd.h"
  3 #include "sys/types.h"
  4 #include "sys/wait.h"
  5 #include "sys/stat.h"
  6 
  7 int main()
  8 {
  9     int ret=mkfifo("myfifo",0664);                                                                                           
 10     if (ret < 0)
 11         perror("mkfifo");
 12     return 0;
 13 }

在这里插入图片描述
2. 借助有名管道实现两个终端的通信

创建一个server.c和一个client.c。利用有名管道,实现两个终端的通信。

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define ERR_EXIT(m) \
do{\
 perror(m);\
 exit(EXIT_FAILURE);\
}while(0)
int main()
{
 int wfd = open("mypipe", O_WRONLY);
 if(wfd < 0){
 ERR_EXIT("open");
 }
 char buf[1024];
 while(1){
 buf[0] = 0;
 printf("Please Enter# ");
 fflush(stdout);
 ssize_t s = read(0, buf, sizeof(buf)-1);
 if(s > 0 ){
 buf[s] = 0;
 write(wfd, buf, strlen(buf));
 }else if(s <= 0){
 ERR_EXIT("read");
 }
 }
 close(wfd);
 return 0; }

server.c

1 #include <stdio.h>                                                                                                           
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 #define ERR_EXIT(m) \
  8     do{\
  9      perror(m);\
 10      exit(EXIT_FAILURE);\
 11     }while(0)
 12 int main()
 13 {
 14      umask(0);
 15      if(mkfifo("mypipe", 0644) < 0){
 16           ERR_EXIT("mkfifo");
 17            
 18      }
 19       int rfd = open("mypipe", O_RDONLY);
 20       if(rfd < 0)
 21       {
 22           ERR_EXIT("open");      
 23       }
 24       char buf[1024];
 25       while(1)
 26       {
 27           buf[0] = 0;
 28           printf("Please wait...\n");
 29           ssize_t s = read(rfd, buf, sizeof(buf)-1);
 30           if(s > 0 )
 31           {
 32               buf[s-1] = 0;
 33               printf("client say# %s\n", buf);       
 34           }
 35           else if(s == 0)
 36           {
 37               printf("client quit, exit now!\n");
 38               exit(EXIT_SUCCESS);           
 39           }
 40           else
 41           {
 42               ERR_EXIT("read");
 43 
 44           }     
 45        }
 46         close(rfd);
 47         return 0; 
 48 }                        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值