Chinaunix首页 | 论坛 | 博客
  • 博客访问: 686301
  • 博文数量: 152
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1793
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 12:26
个人简介

相信自己,只有不想做的,没有做不到的。

文章分类

全部博文(152)

文章存档

2021年(1)

2015年(2)

2014年(74)

2013年(75)

分类: LINUX

2013-12-16 21:49:52

二 有名管道
特点:在文件系统中存在一个名字,管道存在于内核空间

A.创建有名管道
int mkfifo(char *filename,int mode)

例如:
//如果创建有名管道,是由于管道文件存在而失败
//,认为是正常的情况
if(mkfifo(filename,0666) < 0 && errno != EEXIST)
{
 .....
}

B.打开有名管道文件

注意:
1.有名管道一端以只读的方式打开,此时会阻塞,直到另一端以写的方式打开
2.有名管道一端以只写的方式打开,此时会阻塞,直到另一端以读的方式打开
3.如果以读写方式打开,此时不阻塞

三 管道特性(无名管道和有名管道)

A.读管道

1. 写端存在

读管道,管道中有数据,读取数据;管道中没有数据,阻塞。

2.写端不存在

读管道,管道中有数据读取数据,管道中没有数据的时候,不会阻塞,read立即返回0

B.写管道

1.读端存在
写管道,管道空闲,写入数据,管道满,写阻塞

2.读端不存在
写管道,此时写操作没有意义,内核会向写管道的进程发送SIGPIPE信号,此信号默认操作是杀死进程


用创建进程的方式来实现两个进程交谈

在A.c中代码如下

#include
#include
#include
#include
#include
#include
#include
#include
#include

int read_fifo(const char *filename)
{
 int n;
 char buf[1024];
 int fifo_fd;
 
 //打开有名管道
 if((fifo_fd = open(filename,O_RDONLY)) < 0)
 {
  fprintf(stderr,"Fail to open %s : %s.\n",filename,strerror(errno));
 }

 printf("Open fifo success for readonly.\n");

 //从管道中读取数据,并且打印,如果读"quit",结束进程
 while(1)
 {
  //读管道
  n = read(fifo_fd,buf,sizeof(buf) - 1);
  buf[n] = '\0';

  if(n == 0)
  {
   kill(getppid(),9);
   break;
  }
  printf("Read %d bytes : %s.\n",n,buf);
 }
 
 return 0;
}

int write_fifo(const char *filename,int pid)
{
 char buf[1024];
 int fifo_fd;
 
 //打开有名管道
 if((fifo_fd = open(filename,O_WRONLY)) < 0)
 {
  fprintf(stderr,"Fail to open %s : %s.\n",filename,strerror(errno));
 }

 while(1)
 {
  printf(">");
  fgets(buf,sizeof(buf),stdin);
  buf[strlen(buf) - 1] = '\0';
   
  //写管道
  write(fifo_fd,buf,strlen(buf));

  if(strncmp(buf,"quit",4) == 0)
  {
   kill(pid,9);
   break;
  }
 }
 return 0;
}

//./a.out FIFO1 FIFO2
int main(int argc, const char *argv[])
{
 pid_t pid;

 //创建有名管道文件
 if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
 {
  fprintf(stderr,"Fail to mkfifo %s : %s.\n",argv[1],strerror(errno));
  exit(EXIT_FAILURE);
 }

 //创建有名管道文件
 if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
 {
  fprintf(stderr,"Fail to mkfifo %s : %s.\n",argv[1],strerror(errno));
  exit(EXIT_FAILURE);
 }

 if((pid = fork()) < 0)
 {
  perror("Fail to fork");
  exit(EXIT_FAILURE);
 }

 if(pid == 0)
 {
  read_fifo(argv[2]);
  
 }

 if(pid > 0)
 {
  write_fifo(argv[1],pid);
  
 }

 exit(EXIT_SUCCESS);
}



在B.c中代码如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include

int read_fifo(const char *filename)
{
 int n;
 char buf[1024];
 int fifo_fd;
 
 //打开有名管道
 if((fifo_fd = open(filename,O_RDONLY)) < 0)
 {
  fprintf(stderr,"Fail to open %s : %s.\n",filename,strerror(errno));
 }

 printf("Open fifo success for readonly.\n");

 //从管道中读取数据,并且打印,如果读"quit",结束进程
 while(1)
 {
  //读管道
  n = read(fifo_fd,buf,sizeof(buf) - 1);
  buf[n] = '\0';

  if(n == 0)
  {
   kill(getppid(),9);
   break;
  }
  printf("Read %d bytes : %s.\n",n,buf);
 }
 
 return 0;
}

int write_fifo(const char *filename,int pid)
{
 char buf[1024];
 int fifo_fd;
 
 //打开有名管道
 if((fifo_fd = open(filename,O_WRONLY)) < 0)
 {
  fprintf(stderr,"Fail to open %s : %s.\n",filename,strerror(errno));
 }

 while(1)
 {
  printf(">");
  fgets(buf,sizeof(buf),stdin);
  buf[strlen(buf) - 1] = '\0';
   
  //写管道
  write(fifo_fd,buf,strlen(buf));

  if(strncmp(buf,"quit",4) == 0)
  { 
  kill(pid,9);
   break;
 }
 }
 return 0;
}

//./a.out FIFO1 FIFO2
int main(int argc, const char *argv[])
{
 pid_t pid;

 //创建有名管道文件
 if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
 {
  fprintf(stderr,"Fail to mkfifo %s : %s.\n",argv[1],strerror(errno));
  exit(EXIT_FAILURE);
 }

 //创建有名管道文件
 if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
 {
  fprintf(stderr,"Fail to mkfifo %s : %s.\n",argv[1],strerror(errno));
  exit(EXIT_FAILURE);
 }

 if((pid = fork()) < 0)
 {
  perror("Fail to fork");
  exit(EXIT_FAILURE);
 }

 if(pid == 0)
 {
  read_fifo(argv[1]);
 
 }

 if(pid > 0)
 {
  write_fifo(argv[2],pid);
  
 }

 exit(EXIT_SUCCESS);
}


 

阅读(753) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~