Linux管道编程

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

1、匿名管道:管道是父进程和子进程间,或是子进程与子进程间单向的通讯机制,即一个进程发送数据到管道,另外一个进程从管道中读出数据。如果需要双向,或是多项通信机制,则需要建立两个活多个管道。系统负责两件事:一是写入管道的数据和读出管道的数据的顺序是相同的,二是数据不会在管道中丢失,除非某个进程过早的退出。

建立管道函数为

int pipe(int pipe[2]); //其中pipe[0]是读取数据的描述字,pipe[1]是写数据的描述字

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

 

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

Unix/Linux 文件系统包括普通文件,文件目录,与特殊文件(FIFO是其中之一),FIFO文件像普通文件一样,也有读写打开等常用功能。

建立命名管道的函数为mkfifo()

FIFO创建后,可以用open(),close(),read(),write(),unlink()等流操作函数操作。

特点:1.FIFO是作为一个特殊的设备文件存在;

2.不同祖先进程的进程之间可以共享数据;

3.使用完后FIFO将继续保存。


实例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命名管道。通常对命名管道的读在写之前。

读管道:

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"                                         //管道位置

main(int argc,char** argv)
{
	char buf_r[100];
	int  fd;
	int  nread;                                               
	
	if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))       //创建并执行
		printf("cannot create fifoserver\n");
	printf("Preparing for reading bytes...\n");
	
	memset(buf_r,0,sizeof(buf_r));
	fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);                      //readonly 不阻塞
	if(fd==-1)
	{
		perror("open");
		exit(1);	
	}
	while(1){
		memset(buf_r,0,sizeof(buf_r));
		
		if((nread=read(fd,buf_r,100))==-1){                //读取管道
			if(errno==EAGAIN)
				printf("no data yet\n");
		}
		printf("read %s from FIFO\n",buf_r);
		sleep(1);
	}	
	pause();
	unlink(FIFO);
}

写管道:

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"


int main(int argc,char** argv){
<span style="white-space:pre">	</span>int fd;
<span style="white-space:pre">	</span>char w_buf[100];
<span style="white-space:pre">	</span>int nwrite;

<span style="white-space:pre">	</span>fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0); //writeonly,管道已在read中创建,可以直接打开。
<span style="white-space:pre">	</span>if(fd==-1)
<span style="white-space:pre">		</span>if(errno==ENXIO)
<span style="white-space:pre">			</span>printf("open error; no reading process\n");
<span style="white-space:pre">	</span>if(argc==1)
<span style="white-space:pre">		</span>printf("Please send something\n");
<span style="white-space:pre">	</span>strcpy(w_buf,argv[1]);
<span style="white-space:pre">	</span>if((nwrite=write(fd,w_buf,100))==-1){                                  //write
<span style="white-space:pre">		</span>if(errno==EAGAIN)
<span style="white-space:pre">			</span>printf("The FIFO has not been read yet.Please try later\n");
<span style="white-space:pre">			</span>}
<span style="white-space:pre">	</span>else 
<span style="white-space:pre">		</span>printf("write %s to the FIFO\n",w_buf);
}

 








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值