Linux进程间通信IPC

简介: Linux进程间通信IPC

简介


进程之间具有独立性,无法直接通信,因为每个进程都有一个自己独立的虚拟地址空间。


因此让进程间能够通信,本质上就是给进程间提供一块公共的区域,让需要通信的进程都能够访问这块区域,从而就能实现通信。


根据通信应用场景不同,提供的方式也有多种,如:数据传输、数据共享、协调控制


进程间常见的4种通信方式:


       数据传输:管道、消息队列


       数据共享:共享内存


       进程控制:信号量


· 四种进程间通信方式★


一、管道


1.相关特性


使用场景:数据传输


★特性:半双工通信(可以选择方向的单向通信)


       若管道中没有数据,read默认会阻塞等待,直到读取到数据后返回;


       若管道中数据写满,write默认会阻塞,直到数据被读出有空闲空间。


       管道的读写是一种字节流传输服务,数据会在缓冲区堆积,并且遵循先进先出规则。


       若管道所有写端被关闭,read读取完缓冲区数据后,继续读取read将不再阻塞,而是返回0


(所有管道read返回0,表示的是继续读取没有意义)。


       若管道所有读端被关闭,write继续写入数据,则会触发异常,退出程序。


★本质:内核中的一块缓冲区(内核空间的一块内存)


分类:


       匿名管道:内核中的缓冲区没有标识符


       命名管道:内核中的缓冲区具有标识符


2.匿名管道


       因为没有标识符,所以只能用于具有亲缘关系的进程间通信。


       只有通过子进程复制父进程的方式获取操作句柄。


(父进程创建管道后,在创建子进程时,子进程会复制父进程pcb中的大部分信息,其中也包括父进程的管道操作句柄,这样父子进程中的管道操作句柄访问的就是同一个内核缓冲区,从而实现进程间通信)


image.png


3.命名管道


       命名管道的标识符是一个可见于文件系统的特殊管道文件,多个进程通过打开同一个管道文件,访问内核中的同一块缓冲区。


image.png


注意:管道文件只是为了让多个进程找到内核中的同一块缓冲区。


4.管道操作★


4.1匿名管道


int pipe(int pipefd[2]);


功能:创建一个匿名管道


       pipefd[0]:用于从管道中读取数据;


       pipefd[1]:用于向管道中写入数据。


返回值:


       成功:返回0;


       失败:返回-1。


4.2命名管道


int mkfifo(const char* pathname, mode_t mode);


功能:创建一个命名管道的标识符(命名管道文件)


       pathname:带有路径文件名称


       mode:文件权限


返回值:


       成功,返回0;


       失败,返回-1;


       EEXIST,文件已存在。


注意:mkfifo只是创建了一个管道的标识符,后续对于命名管道的操作类似于对普通文件操作。


打开特性:


       如果管道文件被只读打开,就会阻塞,直到管道文件被以写方式也打开;


       如果管道文件被只写打开,也会阻塞,直到管道文件被以读方式也打开。


5.管道总结★


       管道的本质就是内核中的一块缓冲区,分为匿名管道和命名管道。其中匿名管道只能用于具有亲缘关系的进程间通信。


特性:


1)半双工通信;


2) 提供字节流传输服务:


       先进先出;


        基于连接:所有读端关闭write异常,所有写端关闭read返回0不阻塞


3)生命周期跟随进程


4)自带同步与互斥:


       互斥:资源在同一时间只有一个进程可以访问


                管道的写入操作大小不超过PIPE_BUF(默认4096字节)大小时保证原子操作


               (原子操作:要么一次性完成,无法被打断;要么不做。)


       同步:通过某些条件限制,让进程对资源访问更加合理


               若管道中没有数据,则read阻塞;


               若管道中数据已满,则write阻塞。


二、共享内存


1.相关特性


使用场景:实现进程间的数据共享


★特性:最快的进程间通信方式


原理:


       申请一块物理内存,需要进行数据共享的进程将同一块物理内存映射到自己的虚拟地址空间,然后通过虚拟地址直接访问。相较于其他通信方式,没有了两次用户空间与内核空间之间的数据拷贝操作,因此速度最快。


2.操作流程


       1)创建/打开共享内存


       2)将共享内存映射到虚拟地址空间


       3)共享内存操作


       4)解除映射关系


       5)删除共享内存


3.操作接口


3.1创建或打开操作


int shmget (key_t key, size_t size, int shmflag);
        key:标识符,多个进程通过标识符打开同一个共享内存;
        size:共享内存大小;
        shmflag:打开方式&权限;
                打开方式:IPC_CREAT,......;
                权限:0777,......;


返回值:


       成功,返回操作句柄(非负整数);


       失败,返回-1。


3.2建立映射关系操作


void *shmat(int shmid, void *addr, int shmflag);
        shmid:shmget返回的操作句柄;
        addr:指定映射首地址(通常置NULL);
        shmflag:要进行的操作
                SHM_RDONLY:只读;
                默认给0:可读可写;


返回值:


       成功,返回映射的首地址;


       失败,返回(void*)-1。


3.3解除映射关系操作


int shmdt(void *shm_start);
        shm_start:shmat映射的首地址。


3.4删除共享内存操作


int shmct(int shmid, int cmd,  struct shmid_ds *buf);
        shmid:shmget返回的句柄;
        cmd:要对共享内存的操作
                删除:IPC_RMID
                ......;
        buf:用于设置或获取共享内存信息,不使用则设置为NULL。


返回值:对于删除操作


       成功:返回0;


       失败:返回-1。


★注意:


共享内存的删除,实际上并不会立即删除共享内存,而是将共享内存标记为被删除状态,拒绝后续的新建映射,等到映射连接数为0时,自动释放共享内存段。


4.共享内存总结


4.1本质原理


       共享内存的本质就是开辟了一块物理内存,将其映射到多个进程的虚拟地址空间中,进程通过映射后的虚拟地址直接访问同一块物理内存,实现数据共享。


4.2特性


       最快的进程间通信方式(相较于其他方式,少了用户空间与内核空间之间的两步数据拷贝操作)。


       生命周期随内核。


4.3注意事项


多个进程对共享内存进行操作,存在操作安全隐患。


三、消息队列


使用场景:用于实现进程间的数据传输


本质:内核中的一个优先级队列


原理:多个进程通过访问同一个内核中的消息队列,向队列中添加节点、获取节点,实现数据传输


特性:


       消息队列自带同步与互斥;


       生命周期随内核。


四、信号量


使用场景:用于实现进程间的同步与互斥


本质:内核中的一个计数器和pcb等待队列


原理:针对资源进行计数,实现同步与互斥


操作:PV操作


       P操作:在获取或者访问资源前进行P操作


               对计数器进行判断,若小于等于0,则阻塞进程并且计数器-1;


               若计数器大于0,则计数器-1,操作正确返回。


       V操作:在产生资源之后进行V操作


               计数器加1,并唤醒一个等待中的进程。


同步实现:


       对资源进行计数,在资源获取之前进行P操作,在产生资源后进行V操作。


互斥实现:


       将资源计数器初始化为1,表示资源只有一个。


       在访问数据前进行P操作,访问数据完毕之后进行V操作,从而实现同一个资源同一时间内,只有一个进程能够进行访问。


五、进程间通信资源的命令操作


1. ipcs 查看进程间通信资源


语法:ipcs [选项]


-m:共享内存


-s:信号量


-q:消息队列


2. ipcrm 删除进程间通信资源


语法:ipcrm [选项] 资源id


1.png

 


相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
549 67
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
351 20
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
534 16
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
427 0
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
474 0
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
343 0
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
436 0
|
存储 Linux 调度
【Linux】进程概念和进程状态
本文详细介绍了Linux系统中进程的核心概念与管理机制。从进程的定义出发,阐述了其作为操作系统资源管理的基本单位的重要性,并深入解析了task_struct结构体的内容及其在进程管理中的作用。同时,文章讲解了进程的基本操作(如获取PID、查看进程信息等)、父进程与子进程的关系(重点分析fork函数)、以及进程的三种主要状态(运行、阻塞、挂起)。此外,还探讨了Linux特有的进程状态表示和孤儿进程的处理方式。通过学习这些内容,读者可以更好地理解Linux进程的运行原理并优化系统性能。
663 4
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
1843 5
|
Linux 应用服务中间件 nginx
Linux 进程管理基础
Linux 进程是操作系统中运行程序的实例,彼此隔离以确保安全性和稳定性。常用命令查看和管理进程:`ps` 显示当前终端会话相关进程;`ps aux` 和 `ps -ef` 显示所有进程信息;`ps -u username` 查看特定用户进程;`ps -e | grep <进程名>` 查找特定进程;`ps -p <PID>` 查看指定 PID 的进程详情。终止进程可用 `kill <PID>` 或 `pkill <进程名>`,强制终止加 `-9` 选项。
339 3