进程间通信方式----管道通信
来源:互联网 发布:淘宝回收相机定金1000 编辑:程序博客网 时间:2024/05/21 12:45
管道通信
介绍
一、管道的定义
管道(Pipe)及有名管道(Named Pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
二、管道的通信方式
管道的通信方式分为无名管道和有名管道,无名管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制。
三、管道的特点
管道是Linux支持的最初Unix IPC 形式之一,具有以下特点:
1、管道是半双工的,数据只能向一个方向流动;需要双方通信,需要建立两个管道。
2、只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。
3、单独构成一种独立的文件系统。
4、数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。
操作
一、建立无名管道
返回值:成功返回0,否则-1;
例子:#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
int main()
{
pid_t pid;
int filedes[2];
char buffer[80];
pipe(filedes);
pid = fork();
if(-1 == pid)
{
perror("fork");
exit(1);
}
else if(pid > 0)
{
/*父进程*/
char s[]="hello!\n";
write(filedes[1],s,sizeof(s));
}
else
{
/*子进程*/
read(filedes[0],buffer,80);
printf("%s",buffer);
}
return 0;
}
二、读写无名管道
示例:#include <unistd.h>
#include<stdio.h>#include<sys/types.h>#include<string.h>#include<errno.h>#include<stdlib.h>int main(){int pipe_fd[2];pid_t pid;char r_buf[100];char w_buf[4];char *p_wbuf;int r_num;int cmd;memset(r_buf,0,sizeof(r_buf));memset(w_buf,0,sizeof(w_buf));p_wbuf = w_buf;if(pipe(pipe_fd)<0){printf("pipe create error!\n");return -1;}if((pid = fork())==0){printf("\n");close(pipe_fd[1]);sleep(3); //确保父进程关闭写端r_num = read(pipe_fd[0],r_buf,100);printf("read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf));close(pipe_fd[0]);exit(0);}else if(pid>0){close(pipe_fd[0]); //readstrcpy(w_buf,"6666");if(write(pipe_fd[1],w_buf,4)!=-1){printf("parent write over!\n");}close(pipe_fd[1]);printf("parent close fd[1] over!\n");sleep(10);
read num is 4 the data read from the pipe is 6666
#include<sys/types.h>#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){int pipe_fd[2];pid_t pid;char r_buf[4];char* w_buf;int writenum;int cmd;memset(r_buf,0,sizeof(r_buf));if(pipe(pipe_fd)<0){printf("pipe create error!\n");return -1;}if((pid = fork())==0){close(pipe_fd[0]);close(pipe_fd[1]);sleep(10);exit(0);}else if(pid>0){sleep(1);close(pipe_fd[0]);w_buf="111";if((writenum = write(pipe_fd[1],w_buf,4))==-1)printf("write to pipe error!\n");elseprintf("the bytes write to pipe is %d \n",writenum);close(pipe_fd[1]);}return 0;}执行: broken pipe原因:该管道及其所有 fork() 产物的读端已经被关闭。
对管道的写规则的验证2:Linux不保证写管道的原子性验证
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<errno.h>
#include<string.h>
int main(int argc,char **argv)
{
int pipe_fd[2];
pid_t pid;
char r_buf[4096];
char w_buf[4096*2];
int writenum;
int rnum;
memset(r_buf,0,sizeof(r_buf));
if(pipe(pipe_fd)<0)
{
printf("pipe create error!\n");
return -1;
}
if((pid = fork())==0)
{
close(pipe_fd[1]);
while(1)
{
sleep(1);
rnum = read(pipe_fd[0],r_buf,1000);
printf("child:readnum is %d \n",rnum);
}
close(pipe_fd[0]);
exit(0);
}
else if(pid > 0)
{
close(pipe_fd[0]);
memset(r_buf,0,sizeof(r_buf));
if((writenum=write(pipe_fd[1],w_buf,1024))==-1)
printf("write to pipe error!\n");
else
printf("the bytes write to pipe is %d \n",writenum);
writenum=write(pipe_fd[1],w_buf,4096);
close(pipe_fd[1]);
}
return 0;
}了解即可,运行后会陷入死循环(或在 while(1)处添加限制条件)
三、无名管道应用实例
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipe_fd[2];
pid_t pid;
char r_buf[4];
char* w_buf[256];
int childexit=0;
int i;
int cmd;
memset(r_buf,0,sizeof(r_buf));
if(pipe(pipe_fd)<0)
{
printf("create pipe error!\n");
return -1;
}
if((pid = fork())==0)
{
printf("\n");
close(pipe_fd[1]);
sleep(2);
while(!childexit)
{
read(pipe_fd[0],r_buf,4);
cmd = atoi(r_buf);
if(cmd == 0)
{
printf("child:receive command from parent over\nnow childprocess exit\n");
childexit=1;
}
else if(handle_cmd(cmd)!=0)
return ;
sleep(1);
}
close(pipe_fd[0]);
exit(0);
}
else if(pid > 0)
{
close(pipe_fd[0]);
w_buf[0]="003";
w_buf[1]="005";
w_buf[2]="777";
w_buf[3]="000";
for(i=0;i<4;i++)
write(pipe_fd[1],w_buf[i],4);
close(pipe_fd[1]);
}
return 0;
}
int handle_cmd(int cmd)
{
if((cmd<0)||(cmd)>256)
{
printf("child:invalid command\n");
return -1;
}
printf("child:th cmd from parent is %d\n",cmd);
return 0;
}
执行:child:th cmd from parent is 3
child:th cmd from parent is 5
child:invalid command
创建有名管道
#include <sys/stat.h>
定义函数:int mkfifo(const char *pathname, mode_t mode);
#include <sys/stat.h>
#include<stdio.h>
#include <fcntl.h>
#define FIFO "/home/self/2"
int main()
{
char buffer[80];
int fd;
unlink(FIFO);
mkfifo(FIFO,0666);
if(fork()>0)
{
char s[]="hello!\n";
fd = open(FIFO,O_WRONLY);
write(fd,s,sizeof(s));
close(fd);
}
else
{
fd = open(FIFO,O_RDONLY);
read(fd,buffer,80);;
printf("%s",buffer);
close(fd);
}
return 0;
}
读写有名管道
2、向 FIFO 中写入数据
3、对 FIFO 读写规则的验证
- 进程间通信方式----管道通信
- 进程间通信方式介绍-管道
- 进程间通信方式(1)---管道
- 进程间通信方式之管道
- 进程间通信方式之有名管道
- 进程间通信--管道的实现方式
- 进程间的通信方式:管道
- 管道(传统进程间通信方式)
- 进程间通信的方式(一):管道
- 进程间通信方式(一)管道
- 进程间通信-管道通信
- 进程间通信--管道通信
- 进程间的通信方式之管道通信
- 通信方式--管道(父子进程通信)
- 进程间管道通信
- 进程间通信: 管道
- 进程间通信--管道
- 进程间通信----管道
- bootstrap 布局图片列表
- Android的CheckBox控件设置自定义图片
- 建设数据中心机房主要看这几点,否则被定为劣质机房!!!
- DUBBO常用xml配置总结与分类
- 3分钟学会sessionStorage用法
- 进程间通信方式----管道通信
- 第十四讲 适配器模式、内部类、递归算法、数据结构之链表、包装类、Eclipse开发环境设置
- 多线程三种实现方式/IO流模拟用户注册及登录
- 引用类型(一) Object类型
- Linux下Patch命令用来打补丁和卸载补丁
- python 从哪开始执行 之 main 函数
- C# 编译成一个exe文件
- Leetcode题解
- Mycat系列—生产实践案例-Mycat 读写分离案例