尝试linux下c编程之管道

今天试了下管道,感觉挺有意思的~ 现在才发现,原来进程也有这么多的功能可以实现。

管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道。

1   匿名管道:管道是父进程和子进程间,或是子进程与子进程间单向的通讯机制,即一个进程发送数据到管道,另外一个进程从管道中读出数据。如果需要双向,或是多项通信机制,则需要建立两个活多个管道.
    系统负责两件事:一是写入管道的数据和读出管道的数据的顺序是相同的,二是数据不会在管道中丢失,除非某个进程过早的退出.
   
    建立管道函数为
    int pipe(int pipe[2]);         //其中pipe[0]是读取数据的描述字,pipe[1]是写数据的描述字

    实例:
   
#include <stdio.h>
#include 
<sys/types.h>
#include 
<unistd.h>
#include 
<stdlib.h>

void read_data( int pipes[  ] )
{
  
int c;
  
int rc;
  
  close( pipes[ 
1 ] );                  //由于此函数只负责读,因此将写描述关闭(资源宝贵)
  while( (rc = read(pipes[ 0 ], &c, 1)) > 0 ){                      //阻塞,等待从管道读取数据
    putchar( c );                              //int 转为 unsiged char 输出到终端
  }


  exit( 
0 );
}




void write_data( int pipes[  ] )
{
  
int c;
  
int rc;

  close( pipes[  
0 ] );                          //关闭读描述字
  
  
while( (c=getchar()) > 0 ){
    rc 
= write( pipes[ 1 ], &c, 1 );            //写入管道
    if( rc == -1 ){
      perror (
"Parent: write");
      close( pipes[ 
1 ] );
      exit( 
1 );
    }

  }

 

  close( pipes[ 
1 ] );
  exit( 
0 );
  
}



int main( int argc, char *argv[  ] )
{
  
int pipes[ 2 ];
  pid_t pid;
  
int rc;

  rc 
= pipe( pipes );                   //创建管道
  if( rc == -1 ){
    perror( 
"pipes" );
    exit( 
1 );
  }


  pid 
= fork(  ); 
  
  
switch( pid ){
  
case -1:
    perror( 
"fork" );
    exit( 
1 );
  
case 0:
    read_data( pipes );                       
//相同的pipes
  default:
    write_data( pipes );                      
//相同的pipes
  }



  
return 0;
}



上述匿名管道是与进程密切相关的。只有有关系的进程才能使用他们。至于两个不相关的进程则需要用到有名字的管道,即命名管道。

2   命名管道:又称FIFO (FIRST IN FIRST OUT).  它是文件系统中的特殊文件(注意是文件哦,一般我们可以把它放在/tmp/xxxx里).  不同的进程打开相同的命名管道实现类似匿名管道的数据通信。

ps:  Unix/Linux 文件系统:包括普通文件,文件目录,与特殊文件(FIFO是其中之一),FIFO文件像普通文件一样,也有读写打开等常用功能。
管道文件删除:  程序中可使用unlink()
接触管道读写阻塞: 使用fcntl()

实例:先编译运行fifoW.c ,  再编译运行fifoW.c   fifoR的子进程接受管道数据,fifoW负责写
/*   fifoR.c   负责从管道文件中读取数据   */
#include  < unistd.h >
#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< sys / types.h >
#include 
< sys / stat.h >
#include 
< string .h >
#include 
< fcntl.h >
#include 
< sys / wait.h >
#include 
< signal.h >

#define  FIFO_NAME "/tmp/myfifo2"                     // 定义宏,指向管道文件的位置

void  read_pipe() {                       //子进程, 处理从管道中读数据

  
int pipe_fd;
  
int res;
  
int c;
  
int open_mode = O_RDONLY;                   //设置权限,为只读
  
  pipe_fd 
= open( FIFO_NAME, open_mode );              //打开管道文件,并设置打开权限,返回int
  
  
if( pipe_fd!=-1 ){
    
while(1){                     
      
      
while( (res = read( pipe_fd, &c, 1 )) > 0 ){              //从管道读数据
    putchar( c );
      }

      fflush( stdout );
    }

  }
else{
    exit( 
1 );
  }


  close(pipe_fd);

}


void  signal_handler(  int  n) {                                 //受到子进程退出信号,结束子进程
  int child_status;
  wait( 
&child_status );
  printf( 
"child exited. " );
}


int  main(  int  argc,  char   * argv[  ] )
{

  
int pid;
  
int child_status;
  
  signal(SIGCHLD, signal_handler);                    
//子进程退出时所发信号
  pid = fork();                                //创建子进程,使之读取管道数据
  int i = 0;
  
switch(pid){
  
case -1:
    printf(
"fork error");
    exit( 
1 );
  
case 0:
    read_pipe();
    exit( 
0 );
  
default:                              //做它自己无聊的事
    for(i;i<100;i++){
      printf(
"%d ", i);
      fflush( stdout );
      sleep(
2);
    }

  }



  
return 0;
}


/*   fifoW.c   负责向管道文件中写数据   */

#include  < unistd.h >
#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< sys / types.h >
#include 
< sys / stat.h >
#include 
< string .h >
#include 
< fcntl.h >
#define  FIFO_NAME "/tmp/myfifo2"                     // 定义宏,指向管道文件位置
#define  TEN_MEG ( 1024*1024*10 )                       // 文件缓冲区最大值


int  main(  int  argc,  char *  argv[  ] )
{

  
int res;
  
int c;
  
int pipe_fd;
  
int open_mode = O_WRONLY;                         //设置读写权限
  int bytes_send = 0;

  
if( access( FIFO_NAME, F_OK ) == -1 ) {       //F_OK : 检查是否有这个文件;  类似还有检查文件可读等,参见man中access中定义
    res = mkfifo( FIFO_NAME, 0777 );                  //创建管道文件,文件属性为0777,root可读写
    if( res != 0 ){                                 //管道文件不可重名
      printf( "Could not create fifo %s ", FIFO_NAME );
      exit( 
1 );
    }

  }


  pipe_fd 
= open( FIFO_NAME, open_mode );             //打开管道,并设置打开权限
  if( pipe_fd !=-1 ){

    
while( (c = getchar(  )) > 0 ){
      res 
= write( pipe_fd, &c, 1 );                       //向管道中写数据
      if( res == -1 ){
    perror( 
"write error" );
    close( pipe_fd );
    exit( 
1 );
      }

    }

    close( pipe_fd );
  }


  
  
return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值