进程通信(IPC)------Linux

目录

一.进程间通信方式

二.管道

2.1无名管道

2.2有名管道

三.信号

3.1信号概念

3.2查看信号(在Linux终端kill -l命令)

3.3常用信号

3.4发送信号命令

3.5信号处理方式

查看IPC进程间通信

四.消息队列

4.1消息队列原理

4.2消息队列优缺点

4.2.1消息队列优点:

4.2.2消息队列缺点:

五.共享内存

5.1共享内存原理

5.2共享内存优缺点:

5.2.1共享内存优点:

5.2.2共享内存缺点:

六.信号量

七.Socket

7.1基于TCP协议通信的Socket通信方式

7.2基于UDP协议通信的Socket通信方式

总结


一.进程间通信方式

每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。为此Linux 内核提供了不少进程间通信的机制。

进程间通信(Inter-Process Communication, IPC)是指不同进程之间传递数据和消息的技术

二.管道

管道,就是内核里面的一串缓存。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限

2.1无名管道

无名管道是内核空间实现的机制,只能用于亲缘进程间通信,无名管道的大小是64K。

无名管道特点:

  1. 只能用于亲缘间进程的通信。
  2. 无名管道半双工的通信方式:单工 A->B; 半双工同一时刻 A->B B->A; 全双工同一时刻 A<->B。
  3. 无名管道大小是64K。
  4. 无名管道不能够使用lessk函数(调用会出错 返回-1)。
  5. 读写的特点:如果读端存在写管道:有多少读多少,直到写满(64K)为止,写阻塞。直到管道中腾出新的4K空间,写操作解除阻塞。如果读端不存在写管道,管道破裂(SIGPIPE)。如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待。如果写端不存在读管道:有多少读多少,没有数据的时候立即返回(非阻塞)。

2.2有名管道

可以用于非亲缘进程间通信,也可以用于亲缘进程间通信。

有名管道会创建一个管道文件,只需要打开这个文件,进行读写操作即可。管道文件本质是在内存上的,在文件系统中显示的只是一个标识。

有名管道的大小也是64K,也不能使用lseek函数。

创建管道:创建管道文件,可以使用mkfifo函数,也可以使用mkfifo命令直接在终端创建。

有名管道的特点:

  1. 可以用于任意进程间的通信,不仅限亲缘进程。
  2. 有名管道数据是半双工的通信方式。
  3. 有名管道的大小是64K。
  4. 有名管道不能使用lessk函数(调用会失败 返回-1)。
  5. 读写的特点:如果读端存在写管道:有多少写多少,直到写满(64K)为止,写阻塞。如果读端不存在写管道:1.读端没有打开,写端在open位置阻塞。2.读端打开后关闭,管道破裂(SIGPIPE)。如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待。如果写端不存在读管道:1.写端没有打开,读端在open位置阻塞。2.写端打开后关闭,有多少读多少,没有数据的时候立即返回。

三.信号

3.1信号概念

信号是中断的一种软件模拟,中断是基于硬件实现的,信号是基于linux内核实现的

用户可以给进程发信号,系统可以给进程发信号,进程也可以给进程发信号。

进程对信号的处理方式有三种:忽略、默认、捕捉

3.2查看信号(在Linux终端kill -l命令)

3.3常用信号

SIGCHLD 当子进程退出的时候,会给父进程发送该信号,默认的行为是忽略。

上述信号中只有 SIGKILL 和 SIGSTOP 不能被忽略和捕捉

3.4发送信号命令

kill -信号的编号 PID

3.5信号处理方式

信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。

  1. 执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 SIGTERM 信号,就是终止进 程的意思。
  2. 捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。
  3. 忽略信号:当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP ,它们用于在任何时候中断或结束某一进程。

查看IPC进程间通信

四.消息队列

4.1消息队列原理

消息队列是保存在内核中的消息链表。

消息队列也是基于内核实现的,A进程将消息写入消息队列

消息队列中的消息有类型和正文。

B进程可以根据消息的类型从消息队列中将对应类型的消息取走。

消息队列的大小,默认是 16K,

如果消息队列满了,A进程还想向消息队列中写入消息,此时A进程将会阻塞。

4.2消息队列优缺点

4.2.1消息队列优点

  1. 异步通信:消息队列允许发送方进程和接收方进程异步地发送和接收消息。发送方在发送消息后不需要等待接收方接收消息,这可以提高系统的并发性和效率。
  2. 可靠性:消息队列存储在内核中,在系统崩溃或进程崩溃后消息不会丢失(除非系统重启),提供了较高的可靠性。
  3. 有序性:消息队列保证消息的顺序性,即消息以发送的顺序到达接收方,这对于某些应用场景非常重要。
  4. 灵活性:消息队列支持不同类型的消息,进程可以根据消息类型选择性地接收消息,提供了较高的灵活性。
  5. 隔离性:消息队列的通信是通过内核进行管理的,进程间直接的耦合较低,有助于提高系统的模块化和隔离性。

4.2.2消息队列缺点

  1. 内存消耗:消息队列存储在内核内存中,大量使用消息队列会占用内核内存资源,可能导致系统内存压力增加。
  2. 复杂性:使用消息队列进行进程间通信需要处理消息的发送、接收、排序和错误处理等,编程复杂性较高。
  3. 性能开销:消息队列的操作涉及系统调用(如msgsndmsgrcv),每次系统调用都需要从用户态切换到内核态,会有一定的性能开销。
  4. 容量限制:消息队列有容量限制(例如,消息队列的最大长度和每个消息的最大长度),如果消息过多或者消息过大,可能会导致消息发送失败或阻塞。
  5. 消息丢失:在极端情况下,如果消息队列满了且没有处理好,会导致消息发送失败,可能会丢失消息。
  6. 消息队列不适合比较大的数据传输,在内核中每个消息体都有一个最大长度限制,同时所有队列所包含的全部消息体的总长度也有上限。在Linux内核中,会有两个宏定义 MSGMAX 和 MSGMNB,它们以字节为单位,分别定义了一条消息的最大长度和一个队列的最大长度。

五.共享内存

5.1共享内存原理

在内核中创建共享内存,让进程A和进程B都能够访问到,通过这段内存进行数据的传递。

共享内存是所有进程间通信方式中效率最高的(不需要来回进行数据的拷贝)。

共享内存的机制就是拿出一块虚拟地址空间来,映射到相同的物理内存中。

5.2共享内存优缺点:

5.2.1共享内存优点

  1. 高效性:共享内存是所有进程直接访问同一块物理内存,不需要通过内核进行数据拷贝,速度非常快,是最快的IPC方式之一。
  2. 低延迟:由于不需要频繁的系统调用和上下文切换,共享内存具有非常低的延迟,适用于实时性要求高的应用。
  3. 大数据传输:共享内存非常适合传输大数据量,因为数据不需要经过多次拷贝,可以直接在共享内存区域进行读写。
  4. 灵活性:进程可以灵活地访问和操作共享内存中的数据,适用于需要频繁读写操作的场景。

5.2.2共享内存缺点

  1. 同步问题:共享内存本身不提供同步机制,需要应用程序自己实现进程间的同步,例如使用信号量(semaphore)或互斥锁(mutex)来避免竞态条件和数据不一致问题。
  2. 编程复杂性:实现共享内存通信涉及共享内存的创建、映射、同步和销毁等操作,编程复杂度较高。此外,还需要处理好进程之间的内存访问冲突和数据一致性问题。
  3. 安全性:共享内存区域对所有映射的进程都是可见的,存在潜在的安全隐患。如果一个进程错误地修改了共享内存中的数据,可能会影响其他进程的正常运行。
  4. 内存管理:共享内存区域的管理需要小心,尤其是在进程退出时需要正确地释放共享内存,否则可能会造成内存泄漏或资源浪费。
  5. 系统资源限制:共享内存的大小受到系统配置的限制,不同系统对共享内存的大小有不同的限制,可能需要调整系统参数来适应需求。

六.信号量

信号量是一个整型的计数器,主要用于进程间的互斥和同步,而不是用于缓存进程间通信的数据。

信号量也可形象化的称作信号灯集,在一个信号灯集中可以有多个信号灯,这些信号灯之间工作相互互不干扰。一般情况下使用二值信号灯。

信号量表示资源的数量,控制信号量的方式由两种原子操作:

  1. P操作:这个操作会把信号量减1,相减后如果信号量<0,则表明资源已经被占用,进程需要阻塞等待;相减后如果信号量>=0,则表明还有资源可以使用,进程正常继续执行。
  2. V操作:这个操作会把信号量加1,相加后如果信号量>=0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量>0,则表明当前没有阻塞中的进程。

P操作是用在共享资源之前,V操作是用在离开共享资源之后,这两个操作是必须成对出现的。
两个进程互斥访问共享内存使用信号量(初始化信号量为 1):

两个进程同步访问共享内存使用信号量(初始化信号量为 0):

七.Socket

Socket通信可用于跨网络与不同主机上的进程通信。

7.1基于TCP协议通信的Socket通信方式

7.2基于UDP协议通信的Socket通信方式

总结

无名管道通信的数据是无格式的流并且大小受限,通信的方式是单向的,数据 只能在一个方向上流动,如果要双向通信,需要创建两个管道,而且无名管道是只能用于存在父子关系的 进程间通信,无名管道的生命周期随着进程创建而建立,随着进程终止而消失

有名管道突破了无名管道只能在亲缘关系进程间的通信限制。

不管是有名管道还是无名管道进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获 取,同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。

消息队列克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的消息链 表,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体, 当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。

共享内存可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销,它直接分配一个共享空间,每个进程都可以直接访问,就像访问进程自己的空间一样快捷方便,不需要陷入内核态或者系统调用,大大提高了通信的速度,享有最快的进程间通信方式之名。但是便捷高效的共享内存通信,带来新的问题,多进程竞争同个共享资源会造成数据的错乱

信号量不仅可以实现访问的互斥性,还可以实现进程间的同步信号量其实是一个计数器,表示的 是资源个数,其值可以通过两个原子操作来控制,分别是 P 操作和 V 操作

信号是进程间通信机制中唯一的异步通信机制,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP ,这是为了方便我们能在任何时候结束或停止某个进程。

要与不同主机的进程间通信,那么就需要 Socket 通信了。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议 的通信方式,一个是本地进程间通信方式。

  • 42
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴耕雨读912

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值