Unix网络编程--进程间通信--管道通信
2013-08-28 13:06
337 查看
所有式样的Unix都提供管道,它由 pipe 函数创建,提供一个单路(单向)数据流。
原型如下:
该函数返回两个文件描述符:fd[0] fd[1]。前者打开用于读,后者打开来写。(都是站在进程的角度上来看读和写)
管道的典型用途是以下述方式为两个不同的进程(一个是父进程,一个是子进程)提供进程间的通信手段。首先,由一个进程创建管道后调用 fork 派生出一个自身的副本,过程如下所示:
注意:其实上面这张图说明的道理没有问题,但是图的画法确实是存在问题的。因为管道是单向传输数据流的,所以,当有两个不同的进程进行通信时,需要的是两个管道协同合作,而不是上图的画法。我们可以考虑一种情况,当父进程或者是子进程往管道里写入数据,因为管道里只要有数据就可以读出,所以,如果这时如果父进程或者是子进程读管道中的数据,那么读出的可能就是刚刚写入的数据,这样,就没能完成通信的任务。
所以,如果要实现通信,正确的步骤是:
(1)创建管道1( fd1[0] 和 fd1[1] )和管道( fd2[0] 和 fd2[1] )
(2)fork;
(3)父进程关闭管道1的读出端
(4)父进程关闭管道2的写入端
(5)子进程关闭管道1的写入端
(6)子进程关闭管道2的读出端
完成了以上步骤就好像下面这张图这样:
例子:
现在描述一个客户端-服务器的例子。main 函数创建两个管道并用 fork 生成一个子进程。客户然后作为父进程运行,服务器则作为子进程运行。第一个管道用于从客户向服务器发送路径名,第二个管道用于从服务器向客户发送该文件的内容(或者是一个出错消息),这样设置完毕后就得到下图所示的情形:
下面请看实现的实例程序:
mainpipe.c
我在主目录下放置文件 test.txt,文件内容如下所示:
编译运行程序得到如下输出:
由此可见,利用管道实现了进程间通信。
原型如下:
#include <unistd.h> int pipe(int fd[2]);
该函数返回两个文件描述符:fd[0] fd[1]。前者打开用于读,后者打开来写。(都是站在进程的角度上来看读和写)
管道的典型用途是以下述方式为两个不同的进程(一个是父进程,一个是子进程)提供进程间的通信手段。首先,由一个进程创建管道后调用 fork 派生出一个自身的副本,过程如下所示:
注意:其实上面这张图说明的道理没有问题,但是图的画法确实是存在问题的。因为管道是单向传输数据流的,所以,当有两个不同的进程进行通信时,需要的是两个管道协同合作,而不是上图的画法。我们可以考虑一种情况,当父进程或者是子进程往管道里写入数据,因为管道里只要有数据就可以读出,所以,如果这时如果父进程或者是子进程读管道中的数据,那么读出的可能就是刚刚写入的数据,这样,就没能完成通信的任务。
所以,如果要实现通信,正确的步骤是:
(1)创建管道1( fd1[0] 和 fd1[1] )和管道( fd2[0] 和 fd2[1] )
(2)fork;
(3)父进程关闭管道1的读出端
(4)父进程关闭管道2的写入端
(5)子进程关闭管道1的写入端
(6)子进程关闭管道2的读出端
完成了以上步骤就好像下面这张图这样:
例子:
现在描述一个客户端-服务器的例子。main 函数创建两个管道并用 fork 生成一个子进程。客户然后作为父进程运行,服务器则作为子进程运行。第一个管道用于从客户向服务器发送路径名,第二个管道用于从服务器向客户发送该文件的内容(或者是一个出错消息),这样设置完毕后就得到下图所示的情形:
下面请看实现的实例程序:
mainpipe.c
#include <sys/types.h> /* basic system data types */ #include <sys/time.h> /* timeval{} for select() */ #include <time.h> /* timespec{} for pselect() */ #include <errno.h> #include <fcntl.h> /* for nonblocking */ #include <limits.h> /* PIPE_BUF */ #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> /* for S_xxx file mode constants */ #include <unistd.h> #include <sys/wait.h> #define MAXLINE 1024 void client(int, int); void server(int, int); int main(int argc, char **argv) { int pipe1[2], pipe2[2]; pid_t childpid; pipe(pipe1); pipe(pipe2); if ((childpid = fork()) == 0) { close(pipe1[1]); close(pipe2[0]); server(pipe1[0], pipe2[1]); exit(0); } close(pipe1[0]); close(pipe2[1]); client(pipe2[0], pipe1[1]); waitpid(childpid, NULL, 0); exit(0); } void client(int readfd, int writefd) { size_t len; ssize_t n; char buff[MAXLINE]; fgets(buff, MAXLINE, stdin); len = strlen(buff); if (buff[len - 1] == '\n') len--; write(writefd, buff, len); while ((n = read(readfd, buff, MAXLINE)) > 0) write(STDOUT_FILENO, buff, n); } void server(int readfd, int writefd) { int fd; ssize_t n; char buff[MAXLINE+1]; if ( (n = read(readfd, buff, MAXLINE)) == 0) { printf("end-of-file while reading pathname"); exit(-1); } buff = '\0'; if ( (fd = open(buff, O_RDONLY)) < 0) { snprintf(buff + n, sizeof(buff) - n, ": can't open, %s\n", strerror(errno)); n = strlen(buff); write(writefd, buff, n); } else { while( (n = read(fd, buff, MAXLINE)) > 0) write(writefd, buff, n); close(fd); } }
我在主目录下放置文件 test.txt,文件内容如下所示:
Hello! This is DLUTBruceZhang! I love three things! The sun, for the day; The moon, for the night; The you, forever.
编译运行程序得到如下输出:
由此可见,利用管道实现了进程间通信。
相关文章推荐
- Linux进程间通信(九)---综合实验之有名管道通信实验
- linux进程间通信-管道通信
- 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
- Linux进程间通信(九)---综合实验之有名管道通信实验
- 进程间通信---在父进程跟子进程之间利用管道进行通信。一个简单的例子
- Linux--进程间通信(一)-管道(pipe)通信
- 【Linux】进程间通信IPC之管道通信
- Linux进程间通信(二)---管道通信之无名管道及其基础实验
- 进程间通信之匿名管道通信
- 学习进程间通信 (一)匿名管道通信
- 进程间通信之管道通信(一)
- Linux--进程间通信(二)-命名管道(pipe)通信
- uc笔记09---进程通信,管道,进程间通信,共享内存,消息队列,信号量,IPC 命令
- 进程间通信:匿名管道通信
- 进程间通信-管道通信
- Linux进程间通信(三)---管道通信之有名管道及其基础实验
- 管道通常用在两个线程间通信或进程间通信
- 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
- 进程间通信方式----管道通信
- Linux进程间通信(三)---管道通信之有名管道及其基础实验