Linux进程间通信方式

每个进程的用户空间都是独立的,不能相互访问。
所有进程的内核空间(32位系统3G-4G)都是共享的

应用场景

  • 作为缓冲区,处理速度不同的进程之间的数据传输
  • 资源共享:多个进程之间共享同样的资源,一个进程对共享数据的修改,别的进程应该立刻看到
  • 数据传输: 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
    Linux进程间通信方式

一、管道

缺点:缓存区在内核中大小受限,只能承载无格式字节流;单向通信方式,低效,不适合频繁交换数据

生命周期随着进程创建而建立,随着进程终止而消失
遵循先进先出原则,不支持 lseek 之类的文件定位操作
需要双方通信时,需要建立起两个管道
读端不读或者读的慢,写端要等待读端;
读端关闭,写端收到SIGPIPE信号直接终止;
写端不写或者写的慢,读端要等待写端;
写端关闭,读端读完pipe内部的数据然后再读,会读到0为止,表明读到文件结尾;

1.1 匿名管道 pipe

特殊文件只存在于内存,没有存在于文件系统中
只能用于有亲缘关系的进程间
shell 命令中的竖线就是匿名管道
pipe() 和 fork() 搭配

匿名管道PIPE

1.2 有名管道 fifo

mkfifo myfifo #在文件系统中创建一个类型为 p 的设备文件

int mkfifo(const char *pathname, mode_t mode); //默认在当前的路径下创建
mkfifo("myfifo", 0666);
open("myfifo", O_RDONLY);
open(MY_FIFO, O_WRONLY);

二、消息队列

是消息的链表,存放在内核中并由消息队列标识符标识,具有足够特权的任何进程都可以往一个队列放置/读出一个消息,不需要等待消息的到达。
- 生命周期是随内核的,需要显示删除。
- 消息结构相关联的类型字段(msg_type)提供了两个特性:
(1)标识消息,使得多个进程在单个队列上复用消息。
(2)用作优先级字段,允许接收者以不同于先进先出的某个顺序读出各个消息。
优点
灵活,消息体可以自由定义,支持多种数据类型和优先级。
可靠,消息持久化且不会因发送者崩溃而丢失。
高效,支持大量数据的传输和并行处理
缺点:通信不及时; 需要访问权限;用户态与内核态之间的数据拷贝开销;有大小限制,不适合比较大数据的传输
在内核中一条消息最大长度MSGMAX 和一个队列的最大长度MSGMNB(以字节为单位)

  • 2.1 System V 消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);
int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg); //发送消息
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg); //读取消息
//cmd参数:IPC_STAT获取信息、IPC_SET设置属性、IPC_RMID删除
int msgctl(int msqid, int cmd, struct msqid_ds *buf); 
  • 2.2 POSIX 消息队列
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>mqd_t mq_open(const char *name, int oflag, ...); //打开一个已存在的消息队列,或创建一个新的消息队列
//发送消息
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);//接收消息
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout);//设置/获取消息队列的属性
int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat);
int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat);int mq_close(mqd_t mqdes); //关闭
int mq_unlink(const char *name); //删除一个命名的消息队列。

三、共享内存最快的IPC

映射一段能被其它进程访问的内存,这段共享内存由一个进程创建,多个进程均能访问
缺点:存在进程间共享资源竞争,常与信号量配合使用
生命周期是随内核的,进程要主动删除其创建的共享内存:ipcrm -m {shmid}
共享内存块的大小都必须是系统页面大小的整数倍。系统页面大小指的是系统中单个内存页面包含的字节数。在 Linux 系统中,内存页面大小是4KB,不过您仍然应该通过调用 getpagesize 获取这个值(通过man 2 getpagesize查看 )

在这里插入图片描述
在这里插入图片描述

  • 3.1 System V 共享内存
#include <sys/ipc.h>
#include <sys/shm.h>     // shmget
#include <sys/types.h>   // key_t
// key_t ftok(const char *pathname, int proj_id);  //获取key值
// int shmget(key_t key, size_t size, int shmflg); //得到共享内存标识符,不存在时创建并返回
// void* shmat(int shmid, const void *shmaddr, int shmflg); //共享内存绑定到当前进程的地址空间中
// int shmdt(const void *shmaddr); //取消共享内存与进程地址空间之间的关联
// int shmctl(int shmid, int cmd, struct shmid_ds *buf); //cmd表示具体控制动作:IPC_STAT,IPC_SET改变状态,IPC_RMID	删除key_t key = ftok(PATH_NAME, PROJ_ID);//获取key值
shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL); //操作系统给用户返回的id// ipcs命令查看有关进程间通信设施的信息
// -q:列出消息队列相关信息。
// -m:列出共享内存相关信息。
// -s:列出信号量相关信息
  • 3.2 POSIX 共享内存
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>int shm_open(const char *name, int oflag, mode_t mode);  //创建或打开一个POSIX共享内存对象
int ftruncate(int fd, off_t length); //设置大小
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); //映射到进程的地址空间
int munmap(void *addr, size_t length); //解除映射
int shm_unlink(const char *name); //删除共享内存对象

四、信号量

一个整型的计数器表示资源的数量,是为了保证进程间的同步与互斥而设计的
缺点信号量是通过标识符而不是文件描述符来引用,同时等待一个文件IO和文件描述符的输入之类的操作就会变得比较困难(不能使用I/O模型来同时检测)
两原子操作:
P 操作: 把信号量 -1。相减后信号量 >= 0,表明还有资源可使用,进程可正常继续执行,否则进程需阻塞等待
V 操作: 把信号量 +1。相减后信号量 > 0,表明当前没有阻塞中的进程;否则表明当前有阻塞中的进程,将该进程唤醒运行
信号量pv操作

  • 4.1 System V 信号量(复杂且功能丰富)

System V信号量不仅限于二元状态可以取任何非负整数值, 资源计数
核心在于信号量集(semaphore set)允许在单个原子操作中管理多个信号量,这是一种强大的同步机制,可以用来解决复杂的协调任务。
银行家算法是一种预防死锁的方法,它确保分配资源不会导致系统进入不安全状态。在这个算法中,System V 信号量集用于同时管理多种资源类型
生产者和消费者进程共享一个固定大小的缓冲区,信号量集在这里用于同时控制对缓冲区的访问(互斥信号量)和跟踪缓冲区中项目的数量(计数信号量)
数据库管理系统中,多个事务可能同时操作多个数据项。这里,信号量集用于确保事务的原子性和一致性。每个数据项可以有一个关联的信号量,用于控制对该项的访问
多线程服务器应用中,信号量集可以用来管理线程池中的线程数量,确保服务器不会因为过多的并发请求而过载

#include <sys/types>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/stat.h>// 每个信号量集都有一个关联的semid_dss结构体
struct semid_ds{struct ipcperm sem_perm;  //ownship and permissionstime_t        sem_otime;  //time of last semop()time_t        sem_ctime;  //time of last changesunsigned lone sem_nsems;  //Number of semaphores;
};
union semun {int                val;  // Value for SETVALstruct semid_ds   *buf;  // Buffer for IPC_STAT, IPC_SETunsigned short  *array;  // Array for GETALL, SETALLstruct seminfo  *__buf;  // Buffer for IPC_INFO
};
int semget(key_t key,int nsems,int semflg); //创建一个新信号量集,或者获取一个既有集合的标识符
int semctl(int semid,int sennum, int cmd,.../*union semnu arg*/);//设置或获取信号量集的属性
struct sembuf{unsinged short sem_num;    //semaphore numbershort sem_op;   //operation to be performedshort sem_flag;  //operation flags(IPC_NOWAIT and SEM_UNDO)
};
int semop(int semid,struct sembuf *sops,unsigned int nsops);//对一个或多个信号量执行原子操作
  • 4.2 POSIX 二元信号量

更轻量级, 适用于不复杂操作的对性能敏感的基本同步任务
有名信号量: 操作系统内核维护的具有全局唯一名字的信号量
无名信号量: 是一种不具有全局唯一名字的信号量,通常只能在相关的进程或线程之间进行共享
二进制信号量: 只有0和1两种取值的信号量

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); //创建或打开有名信号量
int sem_init(sem_t *sem, int pshared, unsigned int value); //初始化无名信号量int sem_getvalue(sem_t *sem, int *sval); //获取当前信号量的值
int sem_post(sem_t *sem); //V操作:信号量 +1
int sem_wait(sem_t *sem); //等待信号量减小。如果信号量的值大于0,则将其减小1并立即返回,否则会阻塞当前线程直到信号量变为大于0为止
int sem_trywait(sem_t *sem); //尝试等待信号量减小的非阻塞版本。如果信号量的值大于0,则将其减小1并立即返回,否则会立即返回,并且不会阻塞当前线程
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); //函数允许设置一个超时时间,如果在指定的时间内未能获得信号量,函数将返回一个特定的错误码int sem_close(sem_t *sem);   //关闭有名信号量
int sem_destroy(sem_t *sem); //销毁无名信号量
int sem_unlink(const char *name); //从系统中删除有名信号量

五、信号

缺点:传递信息少
用于通知接收进程某个事件已经发生,唯一的异步通信机制。
信号事件来源主要: 硬件来源(如键盘 Cltr+C )和 软件来源(如 kill 命令)
可以在任何时候发送信号给某一进程,一旦有信号产生,进程就对信号处理(执行默认操作,定义一个信号处理函数,忽略信号)

# Ctrl+C 产生 SIGINT 信号,表示终止该进程;
# SIGTERM  终止该进程;通过 Core Dump 将当前进程的运行状态保存在文件里面,方便事后分析问题在哪里
# Ctrl+Z 产生 SIGTSTP 信号,表示停止该进程,但还未结束;
kill -l1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

六、套接字

3个属性:域、类型、协议。唯一的跨网络主机的通信机制

// domain: AF_INET 用于 IPV4、
//         AF_INET6 用于 IPV6
//         AF_LOCAL/AF_UNIX 二者等价,用于本机
// type: SOCK_STREAM 字节流,对应 TCP
//       SOCK_DGRAM 数据报,对应 UDP
//       SOCK_RAW   原始套接字
int socket(int domain, int type, int protocal);

TCP 服务端负责监听的 socket 叫作监听 socket ==> listen_fd
调用 accept 时,连接成功,会返回一个已完成连接的 socket,叫作已完成连接 socket ==> sock_fd,用来后续传输数据。
是「两个」 不同 socket
在这里插入图片描述
UDP 是没有连接的,所以不需要三次握手。不存在客户端和服务端的概念
每次通信时,调用 sendto 和 recvfrom,都要传入目标主机的 IP 地址和端口
socket
本地 socket 的实现效率大大高于 IPv4 和 IPv6 的字节流、数据报 socket 实现
不像 TCP 和 UDP 要绑定 IP 地址和端口,而是绑定一个本地文件

关于 System V 、POSIX 区别

参考:https://www.cnblogs.com/tongh/p/18002994

Linux内核v2.6.6glibc2.3.4之后的版本支持POSIX消息队列 (查看glibc版本:ldd --version
POSIX:可移植操作系统接口,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称,其正式称呼为IEEE 1003,而国际标准名称为ISO/IEC 9945
标准线上地址:注册后可以在线阅读或者下载。
IEEE和Open Group 的POSIX认证
相关页面
20世纪80年代中期,Unix厂商试图通过加入新的、往往不兼容的特性来使它们的程序与众不同。局面非常混乱,麻烦也就随之而来了。为了提高兼容性和应用程序的可移植性,阻止这种趋势, IEEE(电气和电子工程师协会)开始努力标准化Unix的开发,后来由 Richard Stallman命名为“Posix”。
这套标准涵盖了很多方面,比如Unix系统调用的C语言接口、shell程序和工具、线程及网络编程
有了这个规范,就可以调用通用的API

操作系统发展历史

操作系统发展历史

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据Scala教程从入门到精通第五篇:Scala环境搭建

一&#xff1a;安装步骤 1&#xff1a;scala安装 1&#xff1a;首先确保 JDK1.8 安装成功: 2&#xff1a;下载对应的 Scala 安装文件 scala-2.12.11.zip 3&#xff1a;解压 scala-2.12.11.zip 4&#xff1a;配置 Scala 的环境变量 在Windows上安装Scala_windows安装scala…

RK3568 学习笔记 : u-boot 下通过设置 env ethact 设置当前工作的以太网设备

前言 正点原子 &#xff1a;RK3568 开发板 atompi-ca1 默认有两个网口&#xff0c;通过 u-boot mii 命令&#xff0c;可以查看 网口信息 > mii device MII devices: ethernetfe010000 ethernetfe2a0000 Current device: ethernetfe010000u-boot 下的以太网&#xff0c;不同…

昂科烧录器支持O2Micro凹凸科技的电池组管理IC OZ7708

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中O2Micro凹凸科技的电池组管理IC OZ7708已经被昂科的通用烧录平台AP8000所支持。 OZ7708是一款高度集成、低成本的电池组管理IC&#xff0c;适用于5~8s Li-Ion/Polymer电池组&a…

C++从入门到入土(二)——初步认识类与对象

目录 前言 类与对象的引入 类的定义 类的访问限定符及封装 访问限定符&#xff1a; 封装&#xff1a; 类的作用域 类的实例化 类的大小 this指针 this指针的特性 前言 各位佬们&#xff0c;在开始本篇文章的内容之前&#xff0c;我想先向大家道个歉&#xff0c;由于…

Unity数据持久化之XML

目录 数据持久化XML概述XML文件格式XML基本语法XML属性 C#读取存储XMLXML文件存放位置C#读取XML文件C#存储XML文件 实践小项目必备知识点XML序列化&#xff08;不支持字典&#xff09;XML反序列化IXmlSerializable接口让Dictionary支持序列化反序列化 数据持久化XML概述 什么是…

Unity数据持久化之Json

目录 Json概述Json文件格式Json配置规则Excel转Json C#读取存储Json文件JsonUtlityJsonUtlity序列化JsonUtility反序列化 LitJsonLitJson序列化LitJson反序列化JsonUtility和LitJson对比 Json概述 Json是什么? 全称:JavaScript对象简谱(JavaScript Object Notation) Json是国…

修改表空间的状态

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 表空间有4种状态:联机、脱机、只读和读写。修改其中某一种状态的语句如下所示 设置表空间 tspace 为联机状态。 SQL>ALTER TABLESPACE space ONLINE: 设置表空间 tspa…

【触摸案例-手势解锁案例-按钮高亮 Objective-C语言】

一、我们来说这个self.btns,这个问题啊,为什么不用_btns, 1.我们说,在懒加载里边儿,经常是写下划线啊,_btns,为什么不写,首先啊,这个layoutSubviews:我们第一次,肯定会去执行这个layoutSubviews: 然后呢,去懒加载这个数组, 然后呢,接下来啊,走这一句话, 第一次…

C语言数据在内存中的存储

C语言数据在内存中的存储 个人主页&#xff1a;大白的编程日记 个人专栏&#xff1a;C语言学习之路 文章目录 C语言数据在内存中的存储前言一.整数在内存中的存储1.1整数的表示形式1.2整数在内存中的存放 二.大小端字节序和字节序判断2.1大小端的概念2.2为什么有大小端 三.练习…

利用智能私信软件,快速拓展潜在客户群体

在数字化营销的浪潮中&#xff0c;企业如何快速而有效地触及并吸引潜在客户&#xff0c;已成为一个不可忽视的挑战。随着人工智能技术的不断进步&#xff0c;智能私信软件作为一种新型工具&#xff0c;正逐渐改变着企业的市场拓展方式。本文将探讨如何通过这类软件&#xff0c;…

加州大学欧文分校英语中级语法专项课程04:Intermediate Grammar Project学习笔记(完结)

Intermediate Grammar Project Course Certificate Specialization Certificate Specialization Intro Course Intro 本文是学习 Coursera: Intermediate Grammar Project 这门课的学习笔记。 文章目录 Intermediate Grammar ProjectWeek 01: IntroductionCapstone Introducti…

机器学习——2.损失函数loss

基本概念 损失函数也叫代价函数。损失函数就是计算预测结果和实际结果差距的函数&#xff0c;机器学习的过程就是试图将损失函数的值降到最小。 图左&#xff1a;&#xff5c;t_p - t_c&#xff5c; 图右&#xff1a;&#xff08;t_p - t_c&#xff09;**2 代码实…

docker安装Debian:11 freeswitch1.10.5

文章目录 一、生成一个镜像二、切换一个镜像源为阿里源三、安装一些相关依赖和freeswitch3.1第一步&#xff1a;安装freeswitch-mod和下载所需的依赖项3.2 设置密钥3.3 安装freeswitch所需的依赖项3.4 报错3.4.1 报错13.4.2 报错23.4.3 报错3 四、运行4.1 通话三十秒自动挂断 一…

linux学习:线程池

目录 原理 初始线程池 运行中的线程池 相关结构体 api 线程池初始化 投送任务 增加活跃线程 删除活跃线程 销毁线程池 例子 thread_pool.h thread_pool.c test.c 测试程序 原理 一个进程中的线程就好比是一家公司里的员工&#xff0c;员工的数目应该根据公司的…

【qt】容器的用法

容器目录 一.QVertor1.应用场景2.增加数据3.删除数据4.修改数据5.查询数据6.是否包含7.数据个数8.交换数据9.移动数据10.嵌套使用 二.QList1.应用场景2.QStringList 三.QLinkedList1.应用场景2.特殊点3.用迭代器来变量 四.QStack1.应用场景2.基本用法 五.QQueue1.应用场景2.基本…

LeetCode例题讲解:快乐数

编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1&#xff0c…

[uniapp 地图组件] 小坑:translateMarker的回调函数,会调用2次

大概率是因为旋转和移动是两个动画&#xff0c;动画结束后都会分别调用此函数 即使你配置了 【不旋转】它还是会调用两次&#xff0c; 所以此处应该是官方的bug

JavaWeb之Servlet(上)

前言 1. 什么是Servlet (1) Servlet介绍 (2) Servlet运行于支持Java的应用服务器中。 (3) Servlet工作模式&#xff1a; 2. Servlet API 3. 第一个Servlet (1) 创建一个类实现Servlet接口,重写方法。或继承HttpServlet亦可 (2) 在web.xml文档中配置映射关系 标签的执行…

新能源汽车充电站智慧充电电能服务综合解决方案

安科瑞薛瑶瑶18701709087/17343930412 ★解决方案 ✔目的地充电-EMS微电网平台 基于EMS解决方案从设备运维的角度解决本地充电的能量管理及运维问题&#xff0c;与充电管理平台打通数据&#xff0c;为企业微电网提供源、网、荷、储、充一体化解决方案。 ✔运营场站--电能服务…

Burp插件之BurpSuitFake

在最近的测试中发现一个问题 某些高校在在登陆教务平台登陆的时候没有设置验证码 而且重点是 他写的很清楚 密码是身份证后六位 以下是我的一些思路和过程中解决的办法 part1信息搜集 学生的学号是很有规律的 例如我的学号 就是入学年份专业代码班级学号 每个大学学号规则不…