管道没有名字,所以只能在具有血缘关系的进程间使用,而在无名管道发展出来的有名管道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 文件来读取后才正常返回。
下面练习,分别写两个程序,一个是服务器程序,不断从管道读取客户发送的信息;另一个是客户程序,在命令行输入信息并从管道发送:
客户程序(写管道)
- #include???
- #include???
- #include???
- #include???
- #include???
- #include???
- #include???
- ??
- #define?FIFO_SERVER?"/tmp/myfifo"??
- ??
- main(int?argc,char**?argv)??
- {??
- ????int?fd?=?0;??
- ????char?w_buf[100];??
- ????int?nwrite;??
- ????
- ????fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);??
- ????if(fd==-1)??
- ????????if(errno==ENXIO)??
- ????????????printf("open?error;?no?reading?processn");??
- ????
- ????if(argc==1)??
- ????????printf("Please?send?somethingn");??
- ????
- ????strcpy(w_buf,argv[1]);??
- ????
- ????if((nwrite=write(fd,w_buf,100))==-1)??
- ????{??
- ????????if(errno==EAGAIN)??
- ????????????printf("The?FIFO?has?not?been?read?yet.Please?try?latern");??
- ????}??
- ????else???
- ????????
- ????????printf("write?%s?to?the?FIFOn",w_buf);??
- }??
服务程序(读管道)
- #include???
- #include???
- #include???
- #include???
- #include???
- #include???
- #include???
- ??
- #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?fifoservern");??
- ????printf("Preparing?for?reading?bytes...n");??
- ??????
- ????memset(buf_r,sizeof(buf_r));??
- ????
- ????fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);??
- ????if(fd==-1)??
- ????{??
- ????????perror("open");??
- ????????exit(1);??????
- ????}??
- ????while(1)??
- ????{??
- ????????memset(buf_r,sizeof(buf_r));??
- ????????
- ????????if((nread=read(fd,buf_r,100))==-1){??
- ????????????if(errno==EAGAIN)??
- ????????????????printf("no?data?yetn");??
- ????????}??
- ????????printf("read?%s?from?FIFOn",buf_r);??
- ????????sleep(1);??
- ????}?????
- ????pause();??
- ????unlink(FIFO);??
- }??
接下来进行编译,编译好后,在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 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|