Linux管道的一些细节
来源:互联网 发布:知天下吧 ztx8.net 编辑:程序博客网 时间:2024/05/22 11:12
读管道:
1、进程从管道中读取数据时,进程被挂起直到数据被写进管道。(如果管道被两个进程共享,进程A关闭了读端,进程B读写都开启,B使用读端时,会一直等待B进程的写端的动作,而不会理会A的动作。)
2、当所有的写者关闭了管道的写数据端时,试图从管道中读取数据的调用返回0,意味着文件结束。
3、管道是一个队列。一个进程从管道中读取数据后,数据已经不存在了。如果两个进程都试图对同一个管道进行度操作,在一个读取一些之后,另一个进程读到的将是后面的内容。他们读到的数据必然是不完整的,除非两个进程用某种方式来协调它们对管道的访问。
写管道:
1、管道容纳的数据量是有限的,比磁盘文件差很多。如果进程想写入1000个字节,而管道只能容纳500个,那么写入调用只能等待,直到管道中再有500个字节。
2、当所有读者都关闭读数据端,则写操作失败。首先内核发送SIGPIPE消息给进程。若进程被终止,则无任何事情发生,否则write调用返回-1,并且将errno置为EPIPE。
3、POSIX标准规定内核不会拆分小于512字节的块。而Linux则保证管道中可以存在4096字节的连续缓存。如果两个进程向管道写数据,并且每一个进程都限制其消息不大于512字节,那么这些消息都不会被内核拆分。
这个示例程序,简单地展示了管道的使用:
/* * @FileName: pipedemo.c * @Author: wzj * @Brief: * * @History: * * * * @Date: 2011年10月04日星期二18:55:23 * */ #include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>int main(){int len, i, apipe[2];char buf[BUFSIZ];int tmfd;//tmfd = open("/etc/passwd", O_RDONLY);//dup2(tmfd, 2); // redirect output...//close(tmfd);//close(0); // can't get the input...//close(1); // can't output...close(2);/*get a pipe*/if(pipe(apipe) == -1){perror("could not make pipe");exit(1);}printf("Got a pipe ! It is file descriptors: \{ %d %d} BUFSIZE:%d\n", apipe[0], apipe[1], BUFSIZ);/*read from stdin, write into pipe, read from pipe, print*/while(fgets(buf, BUFSIZ, stdin)){len = strlen(buf);if(write(apipe[1], buf, len) != len){perror("writing to pipe");break;}for(i=0; i<len ; i++){buf[i] = 'X';}len = read(apipe[0], buf, BUFSIZ);if(len == -1){perror("reading from pipe");break;}if(write(1, buf, len) != len){perror("writing to stdout");break;}}return 0;}
下面这个程序演示了,如果所有读者都关闭的时候,写者进行写操作就会错误。子进程尝试写,失败后内核发出SIGPIPE信号。当处理了SIGPIPE时,write返回-1,未处理,子进程直接退出,父进程可以查看到他的状态。
/* * @FileName: pipe.c * @Author: wzj * @Brief: * * @History: * * * * @Date: 2011年10月04日星期二19:44:40 * */ #include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<signal.h>#define CHILD_EXT(x)((x)>>8)//child exit value#define CHILD_SIG(x)((x)& 0x7f)//child signal #define CHILD_SEGV(x)((x)& 0x80)//segment fault #define oops(m,x) {perror(m); exit(x);}void showpipe(int signum){fprintf(stderr,"pipe got the error!!!!!\n");}int main(int ac, char** av){int thepipe[2],newfd,pid;int result;//signal(SIGPIPE, showpipe); // catch the SIGPIPEif(pipe(thepipe) == -1)oops("Can't get a pipe", 1);if((pid = fork()) == -1){oops("Cannot fork", 1);}close(thepipe[0]);if(pid > 0) // parent{close(thepipe[1]);wait(&result);printf("%d,%d,%d\n", CHILD_EXT(result), CHILD_SIG(result), CHILD_SEGV(result));} if(pid == 0) //child{if(write(thepipe[1], "asdf", 4) == -1){fprintf(stderr,"write pipe failed\n");}fprintf(stderr,"after pipe\n");}return 0;}
- Linux管道的一些细节
- linux的一些细节!
- Linux下管道使用的一些限制
- linux inotify的一些细节知识
- linux c mysql的一些细节
- grub启动linux的一些细节
- Linux定义信号的一些细节处理
- linux磁盘分区一些细节
- document_getElementById的一些细节
- JS的一些细节
- 一些简单的细节
- dll的一些细节
- C++的一些细节
- Servlet的一些细节
- Servlet的一些细节
- Servlet的一些细节
- Servlet的一些细节
- 一些小小的细节
- hoiem的boost代码使用
- Custom SDI —— 向视图添加控件
- PHP源代码分析- tick(s)
- 关于Mono的好网站
- 链表的各种操作
- Linux管道的一些细节
- 复制360doc网页中的内容
- linux综合
- java常见面试题收集(质量不保证)
- 分享我的原创软件—MyRSS
- 哈希表实现的统计关键字频度
- Jdom将文件读和写xml
- 第六天(分支语句和逻辑操作符)
- ARM中断