二十、Linux系统编程-管道(一)管道、匿名管道、管道读写规则
2015-04-11 15:45
726 查看
一、管道
概念:管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”,管道本质上是内核中一块固定大小的缓冲区。
管道限制:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
二、匿名管道pipe
函数声明:
返回值:成功返回0,失败返回-1
创建管道示意图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201504/271062a46099d422498a8584fadf1ffa)
管道示例1-父子进程通信:
三、管道读写规则
如果往读端写数据或者从写端读数据都会失败。
(1)、当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
(2)、管道满的时候
O_NONBLOCK disable:write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
(3)、如果所有管道写端对应的文件描述符被关闭,则read返回0
(4)、如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE
(5)、当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
(6)、当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
示例:
概念:管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”,管道本质上是内核中一块固定大小的缓冲区。
管道限制:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
二、匿名管道pipe
函数声明:
#include <unistd.h> int pipe(int pipefd[2]);函数参数:pipefd[0]是管道读端,pipefd[1]管道写端
返回值:成功返回0,失败返回-1
创建管道示意图:
管道示例1-父子进程通信:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <signal.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) int main() { signal(SIGCHLD,SIG_IGN); int pfd[2]; int fd; char buff[1024]; if (pipe(pfd) == -1) ERR_EXIT("pipe error"); if ((fd = fork()) < 0) ERR_EXIT("fork error"); if (fd == 0) { close(pfd[0]); write(pfd[1],"hello",5); close(pfd[1]); exit(EXIT_SUCCESS); } close(pfd[1]); read(pfd[0],buff,5); printf("%s\n",buff); return 0; }管道示例2-数据重定向:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <signal.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) int main() { signal(SIGCHLD,SIG_IGN); int pfd[2]; int fd; char buff[1024]; if (pipe(pfd) == -1) ERR_EXIT("pipe error"); if ((fd = fork()) < 0) ERR_EXIT("fork error"); if (fd == 0) { dup2(pfd[1],STDOUT_FILENO); close(pfd[0]); close(pfd[1]); execlp("ls","ls",NULL); exit(EXIT_FAILURE); } dup2(pfd[0],STDIN_FILENO); close(pfd[0]); close(pfd[1]); execlp("wc","wc","-w",NULL); printf("%s\n",buff); return 0; }
三、管道读写规则
如果往读端写数据或者从写端读数据都会失败。
(1)、当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
(2)、管道满的时候
O_NONBLOCK disable:write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
(3)、如果所有管道写端对应的文件描述符被关闭,则read返回0
(4)、如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE
(5)、当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
(6)、当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
示例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <fcntl.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) #define TEST_SIZE 68*1024 int main(void) { char a[TEST_SIZE]; char b[TEST_SIZE]; memset(a, 'A', sizeof(a)); memset(b, 'B', sizeof(b)); int pipefd[2]; int ret = pipe(pipefd); if (ret == -1) ERR_EXIT("pipe error"); pid_t pid; pid = fork(); if (pid == 0) { close(pipefd[0]); ret = write(pipefd[1], a, sizeof(a)); printf("apid=%d write %d bytes to pipe\n", getpid(), ret); exit(0); } pid = fork(); if (pid == 0) { close(pipefd[0]); ret = write(pipefd[1], b, sizeof(b)); printf("bpid=%d write %d bytes to pipe\n", getpid(), ret); exit(0); } close(pipefd[1]); sleep(1); int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); char buf[1024*4] = {0}; int n = 1; while (1) { ret = read(pipefd[0], buf, sizeof(buf)); if (ret == 0) break; printf("n=%02d pid=%d read %d bytes from pipe buf[4095]=%c\n", n++, getpid(), ret, buf[4095]); write(fd, buf, ret); } return 0; }
相关文章推荐
- 二十一、Linux系统编程-管道(二)命名管道(FIFO)、匿名管道与命名管道区别、命名管道的打开规则
- linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF
- linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF
- linux系统编程之管道(二):管道读写规则
- 进程返回linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF
- linux系统编程之管道(二):管道读写规则
- linux系统编程之管道(一):匿名管道(pipe)
- linux系统编程之管道(一):匿名管道(pipe)
- Linux系统编程:pipe匿名管道的使用,实现linux命令下管道命令
- linux系统编程之管道(一):匿名管道(pipe)
- linux系统编程之管道(一):匿名管道和pipe函数
- linux系统编程之管道(三):命令管道(FIFO)
- Linux系统编程——进程间通信:命名管道(FIFO)
- Linux命名管道FIFO的读写规则
- 【Linux系统编程】进程间通信--有名管道
- Linux系统编程——进程间通信:管道(pipe)
- UNIX环境高级编程——管道读写规则和pipe Capacity、PIPE_BUF
- linux 系统编程-学习笔记10--进程间通信--管道/FIFO/消息队列/
- 四、Linux系统编程-文件和IO(二)文件的读写
- Linux进程间通信(IPC)编程实践(一) 基本概念和匿名管道