Linux进程的锁与进程间通信

Linux作为多任务系统,能够同时运行几个进程,通常进程间相互独立,避免彼此干扰,但有的时候,进程间需要进行通信。

举例来说:

  • 一个进程生成的数据传输到另一个进程(类似生产者进程和消费者进程)
  • 多个进程共享一份数据
  • 不同进程需要彼此等待时
  • 需要协调资源的使用

进程间共享带来的问题:

如果几个进程共享一个资源,就很容易产生干扰,因此内核不仅提供了数据共享的机制,同时也提供了协调数据访问的机制。为了防止干扰,需要通过锁进行保护。

控制机制

进程间通信(interprocess communication, IPC)和数据同步机制。

竞态条件

几个资源在访问资源时彼此干扰的情况通常称之为“竞态条件”。主要问题是,因为竞态条件无法通过系统的试错法检测。某些情况下,需要做一些工作来保护代码避免竞态条件。

临界区

进程的执行在不应该的地方中断,从而导致进程工作的不正确。只要没有其他的进程进入临界区,那么在临界区中的执行是可以中断的。这种情况下的禁止条件称为互斥。也就是说在给定时刻,只有一个进程可以进入临界区代码。

内核锁机制

内核为了保护数据操作,提供了各种锁的选项。

  • 原子操作:最简单的锁操作,保证其操作简单,比如之间操作计数器加1之类的(不能中断的操作)。
  • 自旋锁:最常用的锁选项。用于保护短期保护某段代码,以防止其他处理的访问。在内核等待自旋锁释放时,会重复的检测是否能够获取到锁,而不会进入忙等状态。
  • 信号量:使用最经典的方法实现的,在等待信号量释放时,内核进入睡眠状态,直到被唤醒,然后内核尝试重新获取信号量。互斥量是信号量的一种特例,保护的临界区只能有一个用户进入。
  • 读者/写者锁:此类锁会区分两种不同类型的访问。可以进行并发的读操作,但是同时只有一个能进行写操作。

SystemV进程间通信

Linux使用SystemV(SysV)引入的机制,来支持用户进程的进程间通信和同步。

SystemV机制

SystemV Unix的3种进程间通信(IPC)机制(信号量、消息队列、共享内存)反映了3种相去甚远的概念。共同点在于,它们都使用了全系统范围的资源,可以由几个进程见同时共享。在访问IPC对象时,系统采用了基于文件访问权限的一个权限系统。每个IPC对象都有一个用户ID和一个租ID。读写权限在初始化时分配。

共享内存

共享内存是进程间通信的最后一个概念,从用户和内核的角度来看。
与信号量和消息队列相比,共享内存没有本质的区别。

  • 应用程序请求的IPC对象,可以通过magic number和当前命名空间的内核内部ID访问。
  • 对内存的访问,可能受到权限系统的限制。
  • 可以使用系统调用分配和IPC对象关联的内存,具备适当授权的所有进程,都可以访问该内存。

其他IPC机制

除了SystemV UNIX采用的IPC机制之外,进程之间还有其他传统的方法可用于交换信息和数据。

信号

与SysV机制相比,信号是一种比较原始的通信机制。kill命令根据pid向进程发送信号。信号通过-s sig指定,是一个正整数,最大长度取决于处理器类型。另一种是kill -9,等价于在死刑批准上签字(导致某些进程死亡)。

Last modification:July 31, 2022
If you think my article is useful to you, please feel free to appreciate