首页 > 运维 > linux运维 > 正文

进程通信(一)无名管道和有名管道

絕刀狂花
发布: 2025-07-15 08:20:13
原创
819人浏览过

进程通信是指不同进程之间进行信息交换的过程。

《王道考研复习指导》提到,管道通信是一种特殊的消息传递方式。所谓的“管道”,是指用于连接一个读进程和一个写进程以实现它们之间通信的共享文件,也称为pipe文件。发送进程(即写进程)通过字符流形式将大量数据写入管道(共享文件),而接收进程(即读进程)则从管道中读取数据。为了确保通信的顺畅,管道机制需要提供三种协调能力:互斥、同步和确认对方存在。接下来以Linux中的管道为例进行说明。在Linux系统中,管道是一种常用的通信机制。尽管管道本质上也是一种文件,但它与普通文件不同,管道能够克服使用文件通信的两个问题,具体表现为:1)管道大小受限。实际上,管道是一个固定大小的缓冲区。在Linux中,该缓冲区大小为4KB,这使得它不会像文件那样无限制增长。使用单一固定缓冲区可能会导致问题,如在写入管道时可能会填满缓冲区,发生这种情况时,write()调用将默认阻塞,等待某些数据被读取以释放空间。2)读进程可能比写进程运行得快。当所有当前数据已被读取时,管道变为空。在这种情况下,read()调用将默认设置为阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。注意:从管道读取数据是一次性操作,数据一旦被读取就会被丢弃,释放空间以便写入更多数据。管道只能进行半双工通信,即在某一时刻只能单向传输。若要实现父子进程之间的双向互动,需要使用两个管道。

在Linux操作系统下,可以使用ulimit -p命令查看默认管道的大小。

1.无名管道(匿名管道)

函数原型:int pipe(int pipefd[2])

参数:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端。即管道的两端,注意fd是传出参数。当程序调用pipe函数时,操作系统会创建内核缓冲区,fd作为传出参数以便操作内核缓冲区。

返回值:如果匿名缓冲区创建成功,返回值为0;否则,返回-1,并设置errno全局变量为相应的错误。

适用范围:有血缘关系的进程间通信,如父子进程、兄弟进程。

下面举例说明如何使用无名管道在父子进程间进行通信:

进程通信(一)无名管道和有名管道前文已提到,由于管道是半双工通信,即在某一时刻只能单向传输。

代码语言:C

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
<p>int main(){
int fd[2];  //创建文件描述符数组,fd[0]对应管道读端,fd[1]对应管道写端
int res = pipe(fd); //fd作为传出参数,以便对内核缓冲区进行操作
assert(-1 != res);</p><pre class="brush:php;toolbar:false;"><code>pid_t pid = fork(); //创建子进程
if(-1 == pid){
    perror("fork()");
    exit(0);
}

//子进程
if(pid == 0){
    close(fd[0]); //关闭读端
    write(fd[1],"hello",5); //向内核缓冲区写入字符串hello
}else{
    close(fd[1]); //关闭写端
    char buf[128] = {0};
    read(fd[0],buf,sizeof(buf)); //将内核缓冲区的内容写入buf中
    printf("%s \n",buf); //将写入buf中的内容输出到屏幕上
}
登录后复制

}

代码语言:C

gcc pipe.c -o pipe
./pipe
hello
登录后复制

进程通信(一)无名管道和有名管道可以看出,使用匿名管道完成了父子进程的通信,子进程作为写进程输入信息hello,父进程作为读进程读取信息并输出到屏幕上。

有道小P
有道小P

有道小P,新一代AI全科学习助手,在学习中遇到任何问题都可以问我。

有道小P 64
查看详情 有道小P

2.有名管道

由于无名管道的限制,仅限于有血缘关系的进程间通信,因此当需要在无血缘关系的进程之间通信时,pipe就不能使用了。这时需要使用有名管道(fifo)。其特点包括:(1)在磁盘上存在一个文件,使用ls -l命令可以查看管道文件的类型为p。(2)这是一个伪文件,其大小永远为0。(3)在内核中有一个对应的缓冲区。(4)半双工的通信方式。

进程通信(一)无名管道和有名管道使用场景:(1)无血缘关系的进程间通信。

创建方式:(1)使用命令mkfifo 管道名

进程通信(一)无名管道和有名管道(2)调用函数mkfifo,函数原型为:int mkfifo(const char *pathname, mode_t mode);参数:路径和权限。

下面举例说明如何使用mkfifo实现两个无血缘关系进程之间的通信。简单描述:在A进程中向内核缓冲区输入字符串,输入end表示结束进程。在B进程中将内核缓冲区的内容保存到命令行参数argv[1]指定的文件中。A进程:fifoa.c

代码语言:C

#include<stdio.h></p><h1>include<stdlib.h></h1><h1>include<unistd.h></h1><h1>include<string.h></h1><h1>include<assert.h></h1><h1>include<fcntl.h></h1><p>int main(){
int fd = open("FIFO",O_WRONLY); //默认是阻塞的
if(fd == -1){
int n = mkfifo("FIFO",0664); //创建管道文件FIFO
if(-1 == n){
perror("mkfifo");
exit(0);
}
fd = open("FIFO",O_WRONLY);
}
assert(-1 != fd);
printf("open success!\n");
while(1){
printf("please input:");
char buf[128] = {0};
fgets(buf,128,stdin);
if(strncmp(buf,"end",3) == 0) //输入end用以结束进程
{
break;
}
write(fd,buf,strlen(buf) - 1); //strlen(buf)-1减去回车符占用的一个字节长度,否则输出到屏幕上的值为乱码
}
close(fd);
}
登录后复制

B进程:fifob.c

代码语言:C

#include<stdio.h></p><h1>include<stdlib.h></h1><h1>include<unistd.h></h1><h1>include<string.h></h1><h1>include<assert.h></h1><h1>include<fcntl.h></h1><p>int main(int argc,char *argv[]){
int fd = open("FIFO",O_RDONLY); //默认是阻塞的
if(fd == -1){
perror("open");
exit(0);
}
assert(-1 != fd);
int file_fd = open(argv[1],O_WRONLY|O_CREAT,0664);
if(file_fd == -1){
perror("open");
exit(0);
}
char buf[128] = {0};
while(read(fd,buf,128) > 0){
write(file_fd,buf,strlen(buf));
memset(buf,0,128);
}
close(fd);
close(file_fd);
}
登录后复制

代码语言:C

gcc fifoa.c -o fifoa
gcc fifob.c -o fifob
./fifoa
./fifob a.txt
登录后复制

A、B进程必须同时执行,否则被执行的进程会出现阻塞。这体现了管道机制中的一条要求,必须确认对方的存在,否则就会阻塞,等待对方的到来。

进程通信(一)无名管道和有名管道进程通信(一)无名管道和有名管道 在A进程中输入字符串:

进程通信(一)无名管道和有名管道 查看由B进程保存的a.txt文件:

进程通信(一)无名管道和有名管道 正是我们在A进程中输入的字符串。

以上就是进程通信(一)无名管道和有名管道的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号