Linux进程间通信1

news2025/1/11 5:50:20

文章目录

  • 前言
  • 管道
  • 命名管道 / FIFO
  • 消息队列


前言

进程之间可能会存在特定的协同工作的场景,而协同就必须要进行进程间通信,协同工作可能有以下场景

数据传输:一个进程需要将它的数据发送给另一个进程
资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它发生了某种事件。
·进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的
所有陷入和异常,并能够及时知道它的状态改变

那如何实现进程间通信呢?
由于一个进程是不能访问到另一个进程的资源的,即进程之前是具有独立性的。

那么进程之间要通信,就不能使用属于进程的资源,而应该使用一份公共的资源。

所以进程间通信的本质是:由OS参与,提供一份所以进程都能访问的公共资源。

而公共资源是什么,例如:文件、队列、内存块。


管道

管道,又称为“匿名管道”,是UNIX系统IPC(进程间通信)最古老的形式。
特点:
1.它是半双工的(即同一时间数据只能在一个方向上流动),具有固定的读端和写端。
2.它只能用于具有亲缘关系的进程之间的通信(父子进程或者兄弟进程)。
3.它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不 是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

在这里插入图片描述
管道,管道这个名字就好比如这个东西就是一个水管,水管有两个头,决定了一边进,那么也就决定了另外一边出,就比如一个父进程从管道的一端写入,子进程从另外一端读出。这就是一个简单的运用了。父子都是从同一个端口写,都是从同一个端口读,所以运用过程中,我们规划好了谁写谁读后,就需要关闭另外一个,就比如决定了父进程写,就要关闭父进程的读端口。
制造管道函数原型:
在这里插入图片描述
参数:参数为一个数组大小可以储存2个int的指针
返回值:创建成功返回0,失败返回-1
使用须知:pipefd[0]是为读打开的,pipefd[1]是为写打开的。



使用函数小demo:

#include <unistd.h>  
#include <stdio.h>
#include <string.h>

int main()
{
   int fd[2];
   int pid;
   char buf[128];//存放数据

   if(pipe(fd) == -1)//假如创建失败
   {
      printf("creat pipe error\n");
   }

   pid = fork();//创建子进程
   
   if(pid > 0)//父进程
   {
      close(fd[0]);//关闭读端
      write(fd[1],"hello from father\n",strlen("hello from father\n"));
   }
   else//子进程
   {
      close(fd[1]);//关闭写端
      read(fd[0],buf,128);
      printf("read from father: %s\n",buf);
   }

   return 0;
}

运行结果:
在这里插入图片描述
管道读写的特性:
由于fork后我们不知道是子进程先执行还是父进程先执行,如果是子进程先运行,执行到read的时候,由于管道没有数据,所以子进程会阻塞,直到管道中有数据了才会读取。

命名管道 / FIFO

FIFO,也称为命名管道,FIFO文件。
特点:
1.FIFO可以在无关的进程之间交换数据,与无名管道不同。
2.FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。


一旦创建了一个FIFO,就可以用一般的文件I/O函数操作它。它和无名管道十分类似,只不过它是文件,往文件里写就像往管道里写一样。
函数原型:

#include <sys/stat.h>
 
int mkfifo(const char *pathname, mode_t mode);

参数:
用mkfifo函数就能创建一个FIFO文件(有名管道),mode参数与open函数中的mode相同。mode记录待创建文件的访问权限,0600表示可读可写的文件。

当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:
·若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO,只写 open 要阻塞到某个其他进程为读而打开它。
·若指定了O_NONBLOCK,则只读 open 立即返回,而只写 open 将出错返回 -1 如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。
一般都不设置O_NONBLOCK,因为都希望写入数据后再读,不然意义不大。

返回值:创建成功返回0,失败返回-1


运用函数小demo:
read.c:

#include <unistd.h>  
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>


int main()
{
   char buf[128] = {0}; 
   if((mkfifo("./pipe",0600) == -1) && errno != EEXIST)//创建失败或者已经存在
   {
      printf("mkfifo failed\n");
      perror("why");//打印失败原因
   }
   
   int fd = open("./pipe",O_RDONLY);//以只读方式打开FIFO,这里如果管道没有信息会阻塞到有信息

   read(fd,buf,20);//读取
   printf("read buf: %s\n",buf);

   close(fd);//关闭FIFO


   return 0;
}

write:

#include <unistd.h>  
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>


int main()
{
   char *str = "hello\n";
   int fd = open("./pipe",O_WRONLY);//以只写方式打开FIFO

   write(fd,str,strlen(str));//写入数据

   close(fd);//关闭FIFO


   return 0;
}

运行结果:
这里先运行read.c看是否他会阻塞到有数据写入
在这里插入图片描述
看到程序一直卡在一个地方,然后在运行write.c
在这里插入图片描述
现象已经表明,read函数会一直阻塞到有数据写入。

消息队列

消息队列,是消息的链表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点:
1.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
2.消息队列独立于发送和接受进程。进程终止时,消息队列及其内容并不会被删除。
3.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。


函数原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
 
int msgget(key_t key, int msgflq);

参数:
Key:大于0的32位整数,就是每个消息的“名字”,也可以理解为“密码”。
msgglq: msgflq为参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定消息队列的存取权限,一般传入IPC_CREAT,表示:如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列,返回此消息队列的标识符(后续代码示例传入IPC_CREAT|0777,表示创建可读可写可执行的消息队列)

返回值:成功返回消息队列的标识符,出错-1,原因储存在error中


其次要介绍信息接收以及发送函数:
首先要认识一个结构体的组成:

#include <stdio.h>
 
struct msgbuf{
    long mtype;//信息的“名字”,必须大于0
    char mtext[自定义大小];//信息包含的数据
};

接收函数:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
 
ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

发送函数:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
 
int msgsnd(int msgid, const void *msgp, ssize_t msgsz, int msgflq);

参数:(两个函数的参数差不多都是一样的)


区别就是发送函数少了一个msgtyp


msgid:消息队列的标识符
*msgp:传入msgbuf结构体类型的地址
msgsz:收取消息用sizeof计算缓存区的大小
msgtyp:消息的“名字”,发送消息时定义
msgflq:通常为0,即阻塞的方式


运用函数小demo:
send:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
 
struct msgbuf{
	long mtype;
	char mtext[128];
};
 
int main()
{
	struct msgbuf sendbuf={888,"message from quen\n"};//消息的“名字”为888
 
	int msgid=msgget(0x1234,IPC_CREAT|0777);//获取消息的标识符,消息队列的“名字”为0x1234
 
	msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),8880);//计算要发送的数据的大小,所以传入数组名即可
	return 0;
}

read:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
 
struct msgbuf{
	long mtype;
	char mtext[128];
};
 
int main()
{
	struct msgbuf readbuf;//存储接受到的消息
 
	int msgid=msgget(0x1234,IPC_CREAT|0777);//获取消息队列的标识符,队列“名字”同样为0x1234
 
	msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),0);//计算接受到的数据用sizeof
	printf("read from que: %s\n",readbuf.mtext);
 
	return 0;
}

运行结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1969164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【TDH社区版大事件】图分析、全文检索、小文件治理、数据开发工具通通都有!

星环科技大数据基础平台TDH社区版&#xff0c;在保留了商业版核心技术优势的基础上最大程度地降低了用户使用大数据技术的门槛与成本&#xff0c;具有更轻量、更简单、更易用等特性。 此次TDH社区开发版、社区版、社区订阅版均发布了新版本&#xff0c;带来新的产品组件和新的…

我是如何给阿里大神Tree工具类做CodeReview并优化的

首发公众号&#xff1a;赵侠客 引言 前段时间我写了一篇关于树操作的工具类《解密阿里大神写的天书般的Tree工具类&#xff0c;轻松搞定树结构&#xff01;》&#xff0c;当时主要把精力集中在分析代码的实现层面&#xff0c;没有从设计层面、性能层考虑&#xff0c;然后就被很…

Linux网络之多路转接——老派的select

目录 一、高级IO 1.1 概念 1.2 五种IO模型 1.3 小结 二、多路转接的老派 2.1 select 的作用 2.2 select 的接口 三、select 的编写 3.1 类的预先准备 3.2 类的整体框架 3.3 类的执行 Loop 四、Loop 中的回调函数 4.1 HandlerEvent 4.2 AcceptClient 4.3 Service…

二、4 函数的递归与迭代

1、n 的阶乘 2、斐波那契数列 &#xff08;1&#xff09;递归 用递归解决这个问题&#xff0c;由于需要多次重复计算&#xff0c;当 n 较大时&#xff0c;计算效率就非常慢 &#xff08;2&#xff09;迭代&#xff08;速度更快&#xff09;

C# 下⽀持表达式树的框架类型详解与示例

文章目录 什么是表达式树&#xff1f;表达式树的主要用途包括&#xff1a;表达式树节点类型示例&#xff1a;创建一个简单的加法表达式树示例&#xff1a;使用表达式树进行数据绑定示例&#xff1a;动态生成代码总结 在C#中&#xff0c;表达式树&#xff08;Expression Tree&am…

首届「中国可观测日」圆满落幕

首届中国可观测日&#xff08;Observability Day&#xff09;在上海圆满落幕&#xff0c;为监控观测领域带来了一场技术盛宴。作为技术交流的重要平台&#xff0c;此次活动不仅促进了观测云与亚马逊云科技之间的深化合作&#xff0c;更标志着双方共同推动行业发展的重要里程碑。…

红蓝绿三巨头集体拉胯,NVIDIA新显卡被核显秒了

最近蓝厂 intel 的瓜想必大家都已经吃上了吧&#xff1f;13-14 代中高端 CPU 大面积故障崩溃事件。 后续是 intel 官方回应&#xff0c;系微代码错误&#xff0c;请求电压较高导致的。 intel 目前给出的方案是&#xff0c;出现了问题的 CPU&#xff0c;intel 给予免费换新售后…

微信小程序之单选框

微信小程序中的单选框&#xff08;Radio&#xff09;是一个常用的输入组件&#xff0c;用于在多个选项中进行选择。常见的应用场景有性别选择、选项过滤、问卷调查等。本文将介绍小程序中单选框的特点和作用及相应示例。 一、单选框的特点和作用 特点&#xff1a; 单一选择&a…

php yii2 foreach中使用事务,事务中使用了 continue

问题描述&#xff1a;使用yii2&#xff0c;在foreach中使用事务&#xff0c;每个循环一个事务&#xff0c;在事务进行判断,然后直接continue,导致后面的循环数据没有保存成功 如下图&#xff1a; 修改后&#xff1a;如下图

【人工智能学习之商品检测实战】

【人工智能学习之商品检测实战】 1 开发过程2 网络训练效果2.1 分割网络2.2 特征网络 3 跟踪与后处理4 特征库优化5 项目源码解析5.1 yolo训练train_yolo.pygood_net.pydataset.pygood_cls_data.pysave_feature.pyanalyse_good.pyshop_window.pytest.py 6 结语 1 开发过程 拍摄…

Spring boot 整合influxdb2

一.服务安装 docker search influxdb docker pull influxdb docker run -dit --name influxdb --restart always -p 8086:8086 -v /dp/docker/file/influxdb:/var/lib/influxdb influxdb 访问8086 初始化 账号组织和新建bucket 创建密钥 这些豆记录下来 二.项目配置 引入依赖…

什么是物流锁控,RFID物流智能锁对于物流锁控有什么意义

在当今竞争激烈的全球商业环境中&#xff0c;物流行业作为经济发展的重要支撑&#xff0c;其高效、安全的运作至关重要。物流锁控作为保障物流运输过程中货物安全、准确和及时交付的关键环节&#xff0c;正面临着日益复杂的挑战。 一、物流锁控的定义与范畴 物流锁控&#xf…

JavaScript学习笔记(十一):JS Browser BOM

1、JavaScript Window - 浏览器对象模型 浏览器对象模型&#xff08;Browser Object Model (BOM)&#xff09;允许 JavaScript 与浏览器对话。 1.1 浏览器对象模型&#xff08;Browser Object Model (BOM)&#xff09; 不存在浏览器对象模型&#xff08;BOM&#xff09;的官方…

【周易哲学】生辰八字入门讲解(一)

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文讲解【周易哲学】生辰八字入门讲解&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff01; 目录 生辰八字阴阳五行天干地支天干天干天干五合天干…

怎么恢复电脑删除的数据?4种有效的数据恢复方法

在数字时代&#xff0c;数据已成为我们生活与工作的核心要素&#xff0c;它不仅存储着我们工作中的各种重要资料&#xff0c;也记录着个人生活的点点滴滴。无论是精心准备的工作文档或者珍藏的重点照片&#xff0c;在不经意间被误删、因设备故障、中病毒等原因导致丢失&#xf…

AI砸掉了这些人的饭碗

在一般打工人眼里&#xff0c;金融圈往往被认为是高端脑力工作者的聚集地&#xff0c;他们工资高&#xff0c;学历高&#xff0c;能力强&#xff0c;轻易无法被替代。 可最近&#xff0c;偏偏一个“非人类”的物种&#xff0c;要来抢他们的饭碗。相关报道称&#xff0c;华尔街…

因为不懂Redis集群,我被diss了

点赞再看&#xff0c;Java进阶一大半 Redis官方在官网里写着霸气的宣传语&#xff1a;从构建者那里获取世界上最快的内存数据库Get the world’s fastest in-memory database from the ones who built it。南哥相信国内没用Redis的科技公司也屈指可数。 现在Redis已经走向了商业…