进程通信之管道
2018-03-28 16:14
127 查看
管道
管道是UNIX系统IPC的最古老形式,并且所有UNIX系统都提供此种通信机制,我们把一个进程连接到另一个进程的数据流称为管道,在管道中一个进程写,一个进程读。管道的本质也就是操作系统内核提供的一段内存。
管道在创建时获得固定字节数的大小,当一个进程往里面写时,如果有空间,写请求立即执行,否则该进程被阻塞。类似的,如果一个进程试图读取多于当前管道的字节数时,也会阻塞。
管道有两类:匿名管道和命名管道
匿名管道
匿名管道的操作必须是有两个亲缘关系的进程
管道是调用pipe函数创建的:
int pipe(int fd[2])
fd是一个文件描述符数组,fd[0]表示读端,fd[1]表示写端
成功返回0,失败返回小于0的错误代码
下面一段匿名管道创建的代码:
#include<stdio.h> #include<string.h> #include<unistd.h> void Test1() { int fd[2]; int ret = pipe(fd); if(ret < 0) { perror("pipe"); return; } //通过fork创建子进程,父进程从管道一端写,子进程从管道读 int pid = fork(); const char* str = "hello\n"; if(pid > 0) { //father write close(fd[0]);//父进程只写,所以关闭读端的文件描述符 write(fd[1],str,strlen(str)); close(fd[1]); printf("father:%d\n",getpid()); } else if(pid == 0) { //child read close(fd[1]);//子进程只读,所以关闭写端的文件描述符 char buf[1024] = {0}; read(fd[0],buf,sizeof(buf)-1);//-1操作是为了给'\0'预留位置 close(fd[0]); printf("child:%d ,%s\n",getpid(),buf); } else perror("fork"); sleep(1); }
用frok共享管道原理:
注意:当数据被读走后,数据就会被管道释放,以便继续接收更多的数据。
管道结构
在底层实现总,管道的实现是两个进程的f_inode指向同一个临时的inode节点,这个节点指向一个物理页面
因此,对管道的操作也就是对文件的操作,通过不同的文件描述符来标识不同的文件
命名管道
命名管道不需要进程之间有任何关系便能完成通信。
创建一个命名管道:
mkfifo filename
也可以通过函数创建
int mkfifo(const char*filename,mode_t mode);
代码实现:
client.c
#include<stdlib.h> #include<string.h> #include<fcntl.h> #include<stdio.h> #include<unistd.h> int main() { int ret = open("./mypipe",O_WRONLY); if(ret < 0) { perror("open"); exit(1); } char buf[1024] = {0}; while(1) { printf(">:"); fflush(stdout); ssize_t read_size = read(0,buf,sizeof(buf)-1); if(read_size > 0) { buf[read_size] = '\0'; write(ret,buf,strlen(buf)); } else { perror("read"); continue; } } return 0; }
server.c
#include<stdlib.h> #include<string.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<stdio.h> int main() { int ret = open("./mypipe",O_RDONLY); if(ret < 0) { perror("open"); exit(1); } char buf[1024] = {0}; while(1) { ssize_t read_size = read(ret,buf,sizeof(buf)-1); if(read_size < 0) { perror("read"); continue; } else if(read_size == 0) { printf("一个客户端退出\n"); break; } else { buf[read_size] = '\0'; printf("[client]:"); fflush(stdout); write(1,buf,strlen(buf)); } } close(ret); return 0; }
mkfifo创建一个命名管道:
用命名管道实现服务器/客户端之间的通信,满足:客户端从标准输入读取信息,通过命名管道发送给服务器端,服务器端将其输出到屏幕上。
管道的特点
单向通信
面向字节流
aaf4
缓冲区大小有限制
生命周期根随进程
管道有容量限制
管道内部具有同步机制(同时只能由一个进程读写)
相关文章推荐
- 进程的通信:共享存储、消息传递和管道通信
- Linux进程通信 标准流管道
- 管道用于进程通信的实现
- 操作系统--线程和进程/线程管道通信实验
- Linux操作系统分析(10) - 进程通信之管道与信号量
- Linux pipe函数 进程之间的管道通信
- Linux进程通信:命名管道FIFO小结
- 进程间的通信方式:管道
- Linux进程通信总结(二) --管道
- Linux(八):进程通信IPC(二)之命名管道
- C++ 进程通信 管道
- Linux进程间的通信——管道
- 匿名管道实现父子进程之间的通信....
- Linux进程通信:命名管道FIFO小结
- 利用匿名管道技术实现本地进程通信
- 第六章 进程通信之管道
- 关于进程通信的实例-管道
- Linux进程通信——管道
- 进程通信(管道 单向通信)
- C++和C#进程之间通过命名管道通信(附源码)—下