浅谈linux系统下的进程通信之管道pipe

一、 浅谈进程通信和管道    
        谈到进程间通信,就是在数据上不同进程上的共享,让不同的进程看到同一份物理内存。此过程必须通过内核(就是同常意义上的操作系统),在内核中开辟一块缓冲区,把进程1的数据拷入内核的缓冲区,进程2再从内核的缓冲区读取数据,实现进程间通信IPC。
        而通过管道进行通信的实质是父进程通过fork()函数创建子进程,子进程获得了父进程的文件描述符的副本,从而共享数据,进程实现通信。



●文件描述符
    文件描述符是一个较小的正整数,标明每一个被打开进程的文件和socket,通过open()函数和creat()函数,获取或从父进程中继承,0表示标准输入stdin,1表示标准输出stdout,2表示标准错误 stderror.

●管道pipe
头文件:<unistd.h>
函数原型:int pipe (int fileds[2])
此函数是linux内核提供的系统接口,调用pipe()函数在内核中开辟一块缓冲区,通过fileds[]参数传入两个文件描述符,f[0]为读出端,f[1]为写入端。使用read()函数和write()函数对操作内核缓冲区。pipe()函数创建失败返回-1.



管道pipe的特点
1、管道是单向通信的,若要建立双向通信,需建立多个管道;
2、管道是基于字节流通信的;
3、生命周期依赖于文件系统,随进程的结束而结束;
4、自带有协调体同步,互斥效果,保证通信的完整性。
5、管道的容量一般为64k,随内核而改变,是由环形队列组成的。
6、只能作用于有血缘关系的进程,常用于父子进程。

代码实现
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
 int fds[2]={
  0,0
 };
 if(pipe(fds)<0)
 {
  printf("pipe error.%s\n",strerror(errno));
  return 2;
 }
 pid_t id=fork();           //创建子进程
 if(id==0)
 {
  close(fds[0]);           //子进程写数据
        int count=2;
  char* msg="hello world\n";
  while(count--)
  {
   write(fds[1],msg,strlen(msg));
   printf("write success. %d\n");
  }
  close(fds[1]);
 }
 else{
  close(fds[1]);          //父进程读数据
  int count=0;
  char buf[1024];
  while(count++<3){
   ssize_t s=read(fds[0],buf,sizeof(buf)-1);
   if(s>0)
   {
    buf[s]='\0';
   }
   printf("father msg :%s",buf);
   if(waitpid(id,NULL,0)<0)
   {
      return 3;
   }
  }
 }
 return 0;
}

●命名管道FIFO
可以使任意进程见通信,通过访问路径,按先进先出的方式处理数据
mkfifo函数的作⽤用是在⽂文件系统中创建⼀一个⽂文件,该⽂文件⽤用于提供FIFO功能,命名管道。 前边讲的那些管道都没有名字,因此它们被称为匿名管道,或简称管道。对⽂文件系统来说, 匿名管道是不可见的,它的作⽤用仅限于在⽗父进程和⼦子进程两个进程间进⾏行通信。⽽而命名管 道是⼀一个可见的⽂文件,因此,它可以⽤用于任何两个进程之间的通信。
头文件:
<sys/types.h>
<sys/stat.h>
创建命名管道函数原型:
int mkfifo(const char* pathname,mode_t mode)
pathname为路径,命名管道的名称,mode为访问权限


fifo为读端
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>


int main()
{  
  umask(0);
  if(mkfifo("./fifo",S_IFFO|0666)!=0)
 {
  perror("fifo error");
  return 1;
 }
    int fd=open("./fifo",O_RONLY);
  if(fd < 0)
{        
    printf("open  error!\n");    
                 return 1;                
  }           
     char buf[1024];        
     memset(buf, '\0', sizeof(buf));         
     while(1)
    {           
          int ret = read(fd, buf, sizeof(buf));    
          if (ret <= 0)     //error or end of file                    
          {                    
               printf("read error!\n");                               
               break;                          
          }                  
         printf("%s\n");    
         if( strncmp(buf, "quit", 4) == 0 ) 
            break;                                                
    }            
         close(fd);  
         return 0;       
   }

fifo为写端
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
int main()
{
 int fd=open("./fifo",O_WRONLY);
 if(fd>0)
 {
  perror("open error");
 }
 char arry[1024]
 while(1)
 {
  printf("start!\n");
  fflush(stdout);
  ssize_t r=read(0,arry,sizeof(arry)-1);
  if(r>0)
  {
   arry[r]='\0';
   write(fd,strlen(arry));
  }
  printf("quit");
  break;
 }
 return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值