当前位置:网站首页>【进程间通信】:管道通信/有名/无名
【进程间通信】:管道通信/有名/无名
2022-08-02 14:14:00 【白U】
进程间通信的方式:
- 管道 (半双工(只能收或者发,不能同时) ,全双工(同步进行,同发同收)
- 信号量
- 共享内存
- 消息队列
- 套接字
- 管道: 有名管道和无名管道
有名管道:可以在任意进程间通信
无名管道:仅在父子进程间通信 - 定义:
从一个进程链接数据流到另外一个进程
说人话:一个进程的输出通过某种介质作为另一个进程的输入
这个介质就是管道。这也是需要管道的原因。
命令的写法:cmd1 | cmd2
比如shell 让标准输入和标准输出两个命令通果管道显示在终端屏幕上:
cmd1 标准输入的命令(键盘)
cmd1 标准输出传给 cmd2 ,作为cmd2的标准输入
cmd2 标准输出到屏幕
如下图:
- 管道通信:如果需要程序实现,需要两个函数(popen()和pclose())来实现两个进程之间的数据传递。
command :要运行的程序名和相应的参数
open_mode:r / w 权限
r : 被输出的程序可以被输出程序使用,输出程序利用popen返回的FILE*文件流指针,使用fread来读取被输出程序的输出。
w: 输出程序通过fwrite 向被输出程序发送数据。而被输出程序从标准输入读取数据。【它不知道这口饭刚从别人嘴里吐出来。放在盘子里。】
【接盘侠,可以理解为从婚介所得到一个其他人吐出来的二手货】
#include<stdio.h>
FILE *popen(const char* command,const char* open_mode);
int pclose(FILE *stream_to_close);
popen() :允许一个程序将另外一个程序做为新进程启动。
也就是一个程序的输出命令作为了另一个程序的输入
pclose() : 只在popen启动的进程结束后返回。返回值是所关闭的文件流所在的进程的退出码。如果父进程提前获取了该进程的退出码,那么该进程极其资源被回收。其返回值为-1或error。
也就是pclose必须在父进程获取该进程退出码之前执行。
例如:ps -ef 输出 | 输入grep “main”
出现一下问题:
1. 管道必须读写进程同时 open,否则会阻塞
2. 如果管道没有数据,那么read ,阻塞
3. 管道的写端关闭,读read返回值为0
4. 管道的读端关闭,写会产生异常(发送SIGPIPE)
(女朋友挂断电话,你还一个劲说话有啥用?)
#include<signal.h>
void fun(int sig)
{
printf("sig =%d",sig);
}
int main()
{
signal(SIGPIPE,fun);

- 创建有名管道
mkfifo FIFO (fifo 可以随便起)
touch a.c b.c
特殊之处:打开文件管道文件,会在内存中开辟一片空间,会将写入的数据写入内存中。不论有名管道还是无名管道
- a.c文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fdw = open("fifo", O_WRONLY);
if (fdw == -1)
{
exit(-1);
}
char buff[128] = {
0 };
fgets(buff, 128, stdin);
write(fdw, buff, strlen(buff) - 1);
close(fdw);
exit(0);
}
- b.c文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fdr = open("fifo", O_RDONLY);
if (fdr == -1)
{
exit(1);
}
printf("fdr =%d\n", fdr);
char buff[128] = { 0 };
int num = read(fdr, buff, 127);
printf("buff =%s\n", buff);
close(fdr);
exit(0);
}

- 改进:(连续发送数据,和接收数据)
管道中没有数据会阻塞住(只要不关闭管道)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fdw = open("fifo", O_WRONLY);
if (fdw == -1)
{
exit(-1);
}
while(1){
char buff[128] = {
0 };
fgets(buff, 128, stdin);
if(strncmp(buff,"end",3)==0 )
{
break;
}
write(fdw, buff, strlen(buff) - 1);
}
close(fdw);
exit(0);
}
- b.c文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fdr = open("fifo", O_RDONLY);
if (fdr == -1)
{
exit(1);
}
printf("fdr =%d\n", fdr);
while(1){
char buff[128] = { 0 };
int num = read(fdr, buff, 127);
if(num == 0) //读到的数据为0
{
break;
}
printf("buff =%s\n", buff);
}
close(fdr);
exit(0);
}

无名管道创建
man pipe
通过pipe打开管道文件,直接将管道的文件描述符返回
会用fork()产生一个子进程,(因此父进程负责写,子进程负责读)
必须父子进程均关闭,该文件才关闭ca。(教室最后一个人走了,才算真的关闭)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd[2];
if (pipe(fd) == -1) //fd[0] 读,fd[1]写
{
exit(1);
}
printf("fd[0] = %d,fd[1] = %d\n", fd[0], fd[1]);
pid_t pid =fork();
if(pid == -1)
{
exit(0);
}
if(pid == 0)
{
close(fd[1]);
char buff[128] ={
0};
read(fd[0],buff,127);
printf("child read :%s\n",buff);
close(fd[0]);
}
else
{
close(fd[0]);
write(fd[1],"abc",3);
close(fd[1]);
}
exit(0);
}

- 面试会问:

dup(3,1)将3的文件描述符复制到1的位置ls>a.test文件重定向 (追加和覆盖)
因为标准输入输出已经被a.txt 覆盖,因此就没有标准输出和标准输入了。因此hello打印再a.txt中
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd = open("a.txt", O_WRONLY | O_CREAT, 0600)
{
if (fd == -1)
{
printf("open a.txt filed\n");
exit(1);
}
dup2(fd, 1);
dup2(fd, 2);
}
printf("hello\n"); //因为标准输入输出已经被a.txt 覆盖,因此就没有标准输出和标准输入了。因此hello打印再a.txt中
exit(0);
}

管道的实现:
边栏推荐
猜你喜欢

二叉排序树与 set、map

剑指offer:合并两个排序的链表

Exotic curiosity-a solution looking - bit operations

JCMsuite应用:四分之一波片

STM32LL library - USART interrupt to receive variable length information

Unity-Post Processing

C语言函数调用过程-汇编分析

change the available bandwidth of tcp flow dynamically in mininet

剑指offer:在O(1)时间删除链表结点

Test case exercises
随机推荐
固态硬盘到底要不要分区
求解斐波那契数列的若干方法
5款最好用的免费3D建模软件(附下载链接)
LeetCode 2344. 使数组可以被整除的最少删除次数 最大公约数
net start mysql 服务名无效。
Doubled and sparse tables
Unity中事件的3种实现方法
2. Log out, log in state examination, verification code
开源一个golang写的游戏服务器框架
Debug on pure method is called
第三十三章:图的基本概念与性质
shader入门精要3
【线程】线程创建 | 理解线程并发 (1)
你的站点可能还没有准备好用于Site KitSite Kit 无法访问 WordPress REST API。请确保其已在您的站点上启用。
Unity Line-Renderer
mininet multihomed topology
为什么Volatile能保证双重检查锁的线程安全
5. Transaction management
富文本编辑
剑指offer:在O(1)时间删除链表结点