【Linux】进程间通信——管道
创始人
2024-01-26 17:16:46
0

目录

一、概念

二、管道函数

1.popen函数

2.pclose函数

3.文件函数

三、管道的操作

1.管道的分类

无名管道

有名管道

管道的特点

四、管道的实现


操作系统对进程之间相互保护

两个进程之间相互通信

前言:

进程间通信的方法/IPC机制都有哪些:

  1. 管道
  2. 套接字
  3. 信号量
  4. 共享内存
  5. 消息队列

一、概念

什么是管道?

当从一个进程连接数据流到另一个进程时,使用“管道”。通常把一个进程的输出通过管道连接到另一个进程的输入

        shell命令的连接是通过管道字符来完成,如下所示:

cmd1|cmd2

        shell负责安排两个命令的标准输入和标准输出。cmd1的标准输入来自终端键盘,cmd1的标准输出传递给cmd2,作为它的标准输入。cmd2的标准输出来接到终端屏幕。管道是在内存上分配空间,cmd1把数据写到内存中,cmd2从内存中读取数据,效率高。

        shell做的工作实际就是对标准输入和标准输出流进行重新连接,使数据流从键盘输入通过两个命令最终输出到屏幕上。

图示为用管道将多个进程连接起来     

二、管道函数

1.popen函数

头文件:

#include

函数原型:

FILE *popen(const char * command,const char * open_mode);
  • 作用:
    • 允许一个程序将另一个程序作为新程序来启动,并可以传递数据给它或者通过它接收数据。        
  • 参数:
    • 第一个参数command字符串是要运行的程序名和相应参数。open_mode必须是“r”或者是“w”。
    • 第二个参数open_mode必须是“r”或者是“w”。如果open_mode是“r”,被调用的程序输出就可以被调用程序使用,调用程序利用popen函数返回的FILE*文件流指针,就可以通过常用的stdio库函数(如fread)来读取被调用程序的输出。如果open_mode是“w”,调用程序就可以用fwrite调用向被调用程序发送数据,而被调用程序可以在自己的标准输入流上读取数据,然后做出相应的操作。
  • 返回值:
    • 失败返回空指针

2.pclose函数

头文件:#include

函数原型:

FILE *pclose(FILE *stream_to_close);
  • 作用:
    • 关闭与之关联的文件流。        
  • 返回值:
    • 通常是它所关闭的文件流所在进程的退出码。

3.文件函数

#include

write:

把缓冲区Buf的前nbytes个字节写入与文件描述符fildes关联的文件中。返回实际写入的字节数。

size_t write(int fildes,const void *buf,size_t nbytes)

read:

从文件描述符filedes相关联的文件里读入nbytes个字节的数据,并且把他们放到数据区buf中。返回实际读入的字节数。

size_t read(int dildes,void* buf,size_t nbytes);

open:

创建一个新的文件描述符

#include
#include
#includeint open(const char * path,int oflags);
int open(const char *path,int oflags,mode_t mode);

三、管道的操作

管道也是个文件,用文件操作的命令对管道进程操作。管道存放在内存中,读取速度很快。

1.管道的分类

  1. 有名管道:在任意两个进程间通信
  2. 无名管道:在父子进程间通信

无名管道

  • 只能进行父子间通信
  • 使用pipe创建无名管道
  • pipe:
    • 头文件:
    • #includeint pipe(int file_descriptor[2]);
    • 成功返回0,失败返回-1
    • file_descriptor[0]:管道读端的描述符
    • file_descriptor[1]:管道写端的描述符
    • 两个返回的文件描述符以一种特殊的方式连接起来。写到file_deacriptor[1]的所有数据都有可以从file_descriptor[0]读回来。数据基于先进先出的原则(通常写为FIFO)进行处理,这意味着如果把字节1,2,3写到file_deacriptor[1],从file_deacriptor[0]读取到的数据也会是1,2,3,这也栈的处理方式不同,栈采用后进先出,写作LIFO。

  • 函数在两个程序之间传递数据不需要启动一个shell来解释所请求的命令,他同时还提供了对亵读写数据的更多控制。
  • pipe函数的参数是一个由两个整数类型的文件描述符组成数组的指针。该函数在数组中天上两个新的文件描述符后返回0,如果失败则返回-1并设置error来表示失败的原因。
  • 代码演示:父进程写入数据,子进程读取:
  • #include
    #include
    #include
    #include
    #includeint main()
    {int fd[2];//写端描述符assert(pipe(fd)!=-1);pid_t pid=fork();//open->fork,父子共享文件描述法assert(pid!=-1);if(pid==0)//子进程{close(fd[1]);char buff[128]={0};read(fd[0],buff,127);printf(fd[0]);}else{close(fd[0]);write(fd[1],"hello",5);close(fd[1]);}exit(0);
    }
    
  • 代码牵扯到一个知识点:先open打开文件再fork出子进程,此时,父子进程共享文件偏移量/文件描述符。注意:这里使用的文件描述符而不是文件流,所以我们必须用底层的read和write调用来访问数据,而不是用文件流库函数fread和fwrite。
  • fork,可以把fds[0][1]带给子进程,传递描述符

    子进程可以共享,管道就通过fork把管道描述符带给fork

有名管道

  • 有名管道实现任意进程间通信
  • 有名管道的创建:
    • 创建命令:mkfifo
    • 打开管道:open();
    • 读数据:read();
    • 写入数据:write();
    • 关闭管道:close()
  • 代码实现有名管道间通信:

a.c:读取fifi的管道文件,写入5个字符的"hello"数据进去。

#include
#include
#include
#include
#include
#includeint main()
{int fd=open("fifi",O_WRONLY);assert(fd!=-1);printf("fd=%d\n",fd);write(fd,"hello",5);close(fd);
}

b.c

#include
#include
#include
#include
#include
#includeint main()
{int fd=open("./fifi",O_RDONLY);assert(fd!=-1);printf("fd=%d\n",fd);char buff[128]={0};read(fd,buff,127);//不读\0printf("read %s\n",buff);close(fd);
}

管道的特点

  1. 管道必须读,写进程同时open会阻塞
  2. 如果管道中没有数据,那么read就会堵塞
  3. 管道的写端关闭,读read返回值为0,终止程序
  4. 管道的读端关闭,写端写入时产生信号,终止程序
  5. 管道打开的时候只有只读只写两种方式,不能是读写方式,因为读写方式是未定义的
  6. 管道是半双工的:
    1. 全双工、单工、半双工、
    2. 全双工:任意时刻都是双向的
    3. 半双工:某一时刻只能是一个方向
    4. 单:发送方和接收方只有一个方向
  7. 管道文件大小永远为0

四、管道的实现

open打开管道后,会开辟如下所示大小的空间:

头指针:当前待写入的数据位置

尾指针:当前待读取数据的位置,图示为即将读取h

abcdefg为已经读取的数据,用户使用过的空间可以被重新利用,当前空间满了可以写入在缓冲区指针位置。--相当于循环队列

IPC机制有:IPC进程间通信。

相关内容

热门资讯

让更多人走进赛场、体验“十五运...   第十五届全国运动会8月1日将迎来开幕式倒计时100天。7月25日,国务院新闻办举行新闻发布会,介...
​现金流量套期与公允价值套期会... 现金流量套期与公允价值套期会计处理有何区别公允价值套期和现金流量套期的区别主要体现在套期对象、目的和...
保民生、促消费,财政政策有力度... 数据来源:国家发展改革委、财政部  7月25日,财政部召开2025年上半年财政收支情况新闻发布会。 ...
扎根国防一线30年 导弹筑巢...   火箭军某旅工程安装技师崔道虎,矢志建功国防工程30年,先后在8个工种、12个岗位历练,参与30余...
中新健康丨五个关键词,读懂“十...   中新网北京7月24日电(记者 张尼)基本医疗保险参保率稳定在95%左右,医保码、移动支付和电子处...
重访抗战地标丨南泥湾·自己动手...   “困难并不是不可征服的怪物,大家动手征服它,它就低头了。大家自力更生,吃的、穿的、用的都有了。目...
列车一次性座椅套卖爆,真有必要...   有的已累计售卖10万余件,有的周销量飙升超7倍  列车一次性座椅套卖爆,真有必要还是卫生焦虑? ...
微信最新公告:情节严重者永久封...   7月23日,微信视频创作安全中心官方账号发布 《关于开展微信视频号直播“团播低俗内容治理专项”的...
签约3万平方米!第九届进博会招...   7月25日,距离第八届进博会还有100多天,2026年第九届中国国际进口博览会招展就在上海正式启...
“敏捷精神2025”多国联合军...   新华社巴库7月25日电(记者 钟忠)第比利斯消息:代号为“敏捷精神2025”的多国联合军事演习2...