加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

进程通信---FIFO

发布时间:2020-12-13 22:02:31 所属栏目:Linux 来源:网络整理
导读:管道没有名字,所以只能在具有血缘关系的进程间使用,而在无名管道发展出来的有名管道FIFO,则有路径名与之相关联,以一种特殊设备文件形式存在于文件系统中,从而允许无亲缘关系的进程访问FIFO,下面看FIFO的详细操作 1.FIFO的建立 FIFO是存在于文件系统的

管道没有名字,所以只能在具有血缘关系的进程间使用,而在无名管道发展出来的有名管道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 文件来读取后才正常返回。

下面练习,分别写两个程序,一个是服务器程序,不断从管道读取客户发送的信息;另一个是客户程序,在命令行输入信息并从管道发送:

客户程序(写管道)

  1. /*fifo_write.c*/??
  2. #include???
  3. #include???
  4. #include???
  5. #include???
  6. #include???
  7. #include???
  8. #include???
  9. ??
  10. /*FIFO管道路径*/??
  11. #define?FIFO_SERVER?"/tmp/myfifo"??
  12. ??
  13. main(int?argc,char**?argv)??
  14. {??
  15. ????int?fd?=?0;??
  16. ????char?w_buf[100];??
  17. ????int?nwrite;??
  18. ????/*打开FIFO管道*/??
  19. ????fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);??
  20. ????if(fd==-1)??
  21. ????????if(errno==ENXIO)??
  22. ????????????printf("open?error;?no?reading?processn");??
  23. ????/*判断有没有参数输入*/??
  24. ????if(argc==1)??
  25. ????????printf("Please?send?somethingn");??
  26. ????/*复制参数输入*/??
  27. ????strcpy(w_buf,argv[1]);??
  28. ????/*写到FIFO去*/??
  29. ????if((nwrite=write(fd,w_buf,100))==-1)??
  30. ????{??
  31. ????????if(errno==EAGAIN)??
  32. ????????????printf("The?FIFO?has?not?been?read?yet.Please?try?latern");??
  33. ????}??
  34. ????else???
  35. ????????/*输出写入的内容*/??
  36. ????????printf("write?%s?to?the?FIFOn",w_buf);??
  37. }??

服务程序(读管道)

  1. /*fifo_read.c*/??
  2. #include???
  3. #include???
  4. #include???
  5. #include???
  6. #include???
  7. #include???
  8. #include???
  9. ??
  10. /*定义FIFO路径*/??
  11. #define?FIFO?"/tmp/myfifo"??
  12. ??
  13. main(int?argc,char**?argv)??
  14. {??
  15. ????char?buf_r[100];??
  16. ????int??fd;??
  17. ????int??nread;??
  18. ????/*创建FIFO管道*/??
  19. ????if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))??
  20. ????????printf("cannot?create?fifoservern");??
  21. ????printf("Preparing?for?reading?bytes...n");??
  22. ??????
  23. ????memset(buf_r,sizeof(buf_r));??
  24. ????/*打开FIFO管道,不阻塞方式*/??
  25. ????fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);??
  26. ????if(fd==-1)??
  27. ????{??
  28. ????????perror("open");??
  29. ????????exit(1);??????
  30. ????}??
  31. ????while(1)??
  32. ????{??
  33. ????????memset(buf_r,sizeof(buf_r));??
  34. ????????/*读管道,因为定义了非阻塞方式,故在此不会阻塞进程*/??
  35. ????????if((nread=read(fd,buf_r,100))==-1){??
  36. ????????????if(errno==EAGAIN)??
  37. ????????????????printf("no?data?yetn");??
  38. ????????}??
  39. ????????printf("read?%s?from?FIFOn",buf_r);??
  40. ????????sleep(1);??
  41. ????}?????
  42. ????pause();??
  43. ????unlink(FIFO);??
  44. }??

接下来进行编译,编译好后,在Linux中运行两个终端,分别运行以上两个程序,可以看到,运行fifo_read时,程序一直在每隔一秒读,然后我们在另一个终端输入:

$ ./fifo_write helloworld

可以看出fifo_read显示出“helloworld”,说明接受成功

FIFO的一些注意问题:

(1)管道数据的FIFO处理方式

首先放入管道的数据,在端口首先被读出

(2)管道数据的不可再现性

已读取的数据在管道里消失,不能再读

(3)管道长度的有限性

(4)SIGPIPE信号 如果一个进程试图写入到一个没有读取到进程的管道中哦你,系统内核产生SIGPIPE信号

?

转自:http://blog.chinaunix.net/uid-22278460-id-1777637.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读