liunx下的管道----部分讲解

1 进程间使用管道通信
管道允许在进程之间按先进先出的方式传送数据,管道也能使进程同步执行。管道传统的实现方法是通过文件系统作为存储数据的地方。有两种类型的管道:一种是无名管道,简称为管道;另一种是有名管道,也称为FIFO。进程使用系统调用open来打开有名管道,使用系统调用pipe来建立无名管道。使用无名管道通讯的进程,必须是发出pipe调用的进程及其子进程。使用有名管道通讯的进程没有上述限制。在以后的叙述中,所有无名管道都简称为管道。下面来看一下系统调用pipe。

 

系统调用pipe是用来建立管道的。该调用的声明格式如下:
  
int pipe(int filedes[2]);

一个管道拥有两个文件描述符用来通信,它们指向一个管道的索引节点,该调用将这两文件描述符放在参数filedes中返回。现在的许多系统中管道允许数据双向流动,但一般习惯上,文件描述符filedes[0]用来读数据,filedes[1]用来写数据。如果要求程序的可移植性好,就按照习惯的用法来编程。调用成功时,返回值为0;错误时,返回-1,并设置错误代码errno:
EMFILE:进程使用了过多的文件描述符。
ENFILE:系统文件表满。
EFAULT:参数filedes无效。


下面介绍管道的操作的情况:
  
对于写管道:
    写入管道的数据按到达次序排列。如果管道满,则对管道的写被阻塞,直到管道的数据被读操作读取。对于写操作,如果一次write调用写的数据量小于管道容量,则写必须一次完成,即如果管道所剩余的容量不够,write被阻塞直到管道的剩余容量可以一次写完为止。如果write调用写的数据量大于管道容量,则写操作分多次完成。如果用fcntl设置管道写端口为非阻塞方式,则管道满不会阻塞写,而只是对写返回0。
  

对于读管道:
    读操作按数据到达的顺序读取数据。已经被读取的数据在管道内不再存在,这意味着数据在管道中不能重复利用。如果管道为空,且管道的写端口是打开状态,则读操作被阻塞直到有数据写入为止。一次read调用,如果管道中的数据量不够read指定的数量,则按实际的数量读取,并对read返回实际数量值。如果读端口使用fcntl设置了非阻塞方式,则当管道为空时,read调用返回0。
  
对于管道的关闭:
    如果管道的读端口关闭,那么在该管道上的发出写操作调用的进程将接收到一个SIGPIPE信号。关闭写端口是给读端口一个文件结束符的唯一方法。对于写端口关闭后,在该管道上的read调用将返回0。下面再来看看,系统调用pipe的例子。在下面的例子中,父进程通过管道向子进程发送了一个字符串。子进程将它显示出来:

 

 //一下是实例讲解

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

/*
 close pipe read part write to pipe cause
 pipe break out(关闭读端口,对写端口操作时,会发出SIGPIPE错误信号)
 */
void func(int signum)
{
 printf("pipe break out\n");
}

int main()
{
 const char *string =
 { "A sample message" };
 int ret, myPipe[2];
 char buffer[80 + 1];

signal (SIGPIPE, func);
 /*create a pipe */
 ret = pipe(myPipe);
 if (ret == -1)
 {
  perror("pipe error");
  exit(-1);
 }
 else if (ret == 0)
 {
  /*close pipe read part */
  close(myPipe[0]);//,在写端口操作之前,关闭读端口,会报错
  /*write to pipe */
  int bytes_write = write(myPipe[1], string, strlen(string));
  if (bytes_write == -1)
  {
   perror("write pipe error");
   exit(-1);
  }
  else
  {
   printf("bytes write is:%d\n", bytes_write);
  }
  
 }
 return 0;
}

 

//进程间通信

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <stdlib.h>

#define MAX_LINE        80

int main()
{
  int thePipe[2];
  char buf[MAX_LINE + 1];
   const char *testbuf = { "a test string." };
  /*create a pipe*/
  if (pipe(thePipe) == 0) {
    pid_t val = fork();
    if (val == 0) {
     /*child process part*/
      sleep(1);
      close(thePipe[1]);
      /*read from pipe*/
      int bytes_read = read(thePipe[0], buf, MAX_LINE);
      if (bytes_read == -1) {
 perror("read pipe error");
 exit(-1);
      }
      buf[bytes_read] = 0;
      printf("Child read %s\n", buf);
      close(thePipe[0]);
    } else if (val > 0) {
      /*parent part process*/
      close(thePipe[0]);
      /*write to pipe*/
      int bytes_write = write(thePipe[1], testbuf, strlen(testbuf));
      if (bytes_write == -1) {
 perror("write pipe error");
 exit(-1);
      }
      close(thePipe[1]);

     wait(&ret);
    }
  }
  return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值