管道概念
管道是Linux支持的 IPC形式之一,具有以下特点:
- 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
- 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
- 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
- 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
匿名管道是通过pipe()函数创建的:
1 2 3 | #include <unistd.h> int fd[2]; int pipe( fd); |
该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
管道的读写规则
管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。
从管道中读取数据:
- 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
- 当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。
向管道中写入数据:
- 向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
- 只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> int main() { int fd[2]; char rbuf[10]; //~ 读缓冲 char wbuf[5120];//~ 写缓冲 size_t rsize; pid_t pid; if(pipe(fd) == -1) printf("pipe create failure\n"); if((pid = fork()) < 0) printf("process create failure\n"); if(pid == 0) //~ 子进程写 { //close(fd[0]); //!~ 若此处将读端关闭,则管道就没有打开的读端,也无法写入。 while(rsize = fread(wbuf, 1, sizeof(wbuf), stdin)) { rsize = write(fd[1], wbuf, rsize); printf("write: %d\n", rsize); } close(fd[1]); } else if(pid > 0) //~ 父进程读 { //~ sleep(1); close(fd[1]); close(fd[0]);//~读端写端均关闭,此时父进程不做任何事。 sleep(9); while(1) { sleep(1); //~ rsize = read(fd[0], rbuf, sizeof(rbuf)); //~ fprintf(stderr, "%d ", rsize); //~ fwrite(rbuf,1 , rsize, stderr); //~ fprintf(stderr, "\n"); } } return 0; } |
疑问
上述程序运行时,当输入字符串大于写缓冲时,为何没有阻塞?对于一下输入:
There’s a whole lot of laughing gas in the atmosphere these days. But it’s no laughing matter. Nitrous oxide, or N2O, wafts up from manure and the chemical fertilizer sprayed on fields. Industry contributes as well
…….
There’s a whole lot of laughing gas in the atmosphere these days. But it’s no laughing matter. Nitrous oxide, or N2O, wafts up from manure and the chemical fertilizer sprayed on fields. Industry contributes as well
产生的输出:
write: 4096 write: 4096 write: 4096 write: 4096 write: 4096 write: 4096
这是为什么呢?:-(
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Be the first to comment on this entry.