免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 867 | 回复: 0
打印 上一主题 下一主题

进程通信---FIFO [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-29 22:51 |只看该作者 |倒序浏览

                管道没有名字,所以只能在具有血缘关系的进程间使用,而在无名管道发展出来的有名管道FIFO,则有路径名与之相关联,以一种特殊设备文件形式存在于文件系统中,从而允许无亲缘关系的进程访问FIFO,下面看FIFO的详细操作
1.FIFO的建立
FIFO是存在于文件系统的文件节点,所以我们可以建立文件节点的mknod系统用来建立它,也可以mkfifo系统调用
mkfifo说明:
#include
#include
int mkfifo(char *path,mode_t mode);
说明:path:路径名,mode:指定文件存取权标志,mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,系统调用已经指定O_CREATE|O_EXCL
返回:若成功则返回0,否则返回-1,错误原因存于errno中。
错误代码
EACCESS 参数pathname所指定的目录路径无可执行的权限
EEXIST 参数pathname所指定的文件已存在。
ENAMETOOLONG 参数pathname的路径名称太长。
ENOENT 参数pathname包含的目录不存在
ENOSPC 文件系统的剩余空间不足
ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
EROFS 参数pathname指定的文件存在于只读文件系统内。
2.FIFO使用
创建后,在读写前,要先打开它,用open系统调用
当使用open()来打开 FIFO文件时,O_NONBLOCK旗标会有影响
1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。
2、没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。
下面练习,分别写两个程序,一个是服务器程序,不断从管道读取客户发送的信息;另一个是客户程序,在命令行输入信息并从管道发送:
客户程序(写管道)
/*fifo_write.c*/  #include   #include   #include   #include   #include   #include   #include     /*FIFO管道路径*/  #define FIFO_SERVER "/tmp/myfifo"    main(int argc,char** argv)  {      int fd = 0;      char w_buf[100];      int nwrite;      /*打开FIFO管道*/      fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);      if(fd==-1)          if(errno==ENXIO)              printf("open error; no reading process\n");      /*判断有没有参数输入*/      if(argc==1)          printf("Please send something\n");      /*复制参数输入*/      strcpy(w_buf,argv[1]);      /*写到FIFO去*/      if((nwrite=write(fd,w_buf,100))==-1)      {          if(errno==EAGAIN)              printf("The FIFO has not been read yet.Please try later\n");      }      else           /*输出写入的内容*/          printf("write %s to the FIFO\n",w_buf);  }  /*fifo_write.c*/
#include
#include
#include
#include
#include
#include
#include
/*FIFO管道路径*/
#define FIFO_SERVER "/tmp/myfifo"
main(int argc,char** argv)
{
        int fd = 0;
        char w_buf[100];
        int nwrite;
        /*打开FIFO管道*/
        fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
        if(fd==-1)
                if(errno==ENXIO)
                        printf("open error; no reading process\n");
        /*判断有没有参数输入*/
        if(argc==1)
                printf("Please send something\n");
        /*复制参数输入*/
        strcpy(w_buf,argv[1]);
        /*写到FIFO去*/
        if((nwrite=write(fd,w_buf,100))==-1)
        {
                if(errno==EAGAIN)
                        printf("The FIFO has not been read yet.Please try later\n");
        }
        else
                /*输出写入的内容*/
                printf("write %s to the FIFO\n",w_buf);
}

服务程序(读管道)
/*fifo_read.c*/  #include   #include   #include   #include   #include   #include   #include     /*定义FIFO路径*/  #define FIFO "/tmp/myfifo"    main(int argc,char** argv)  {      char buf_r[100];      int  fd;      int  nread;      /*创建FIFO管道*/      if((mkfifo(FIFO,O_CREAT|O_EXCL)        printf("cannot create fifoserver\n");      printf("Preparing for reading bytes...\n");            memset(buf_r,0,sizeof(buf_r));      /*打开FIFO管道,不阻塞方式*/      fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);      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);  }  /*fifo_read.c*/
#include
#include
#include
#include
#include
#include
#include
/*定义FIFO路径*/
#define FIFO "/tmp/myfifo"
main(int argc,char** argv)
{
        char buf_r[100];
        int  fd;
        int  nread;
        /*创建FIFO管道*/
        if((mkfifo(FIFO,O_CREAT|O_EXCL)
接下来进行编译,编译好后,在Linux中运行两个终端,分别运行以上两个程序,可以看到,运行fifo_read时,程序一直在每隔一秒读,然后我们在另一个终端输入:
$ ./fifo_write helloworld
可以看出fifo_read显示出“helloworld”,说明接受成功
FIFO的一些注意问题:
(1)管道数据的FIFO处理方式
首先放入管道的数据,在端口首先被读出
(2)管道数据的不可再现性
已读取的数据在管道里消失,不能再读
(3)管道长度的有限性
(4)SIGPIPE信号 如果一个进程试图写入到一个没有读取到进程的管道中哦你,系统内核产生SIGPIPE信号
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/102839/showart_2041236.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP