进程
进程是计算机科学中最重要和最成功的概念之一。
操作系统内核
操作系统内核是应用程序和硬件之间的媒介,它提供三个基本的抽象:
- 文件是对 I/O 设备的抽象
- 虚拟存储器是对主存和磁盘的抽象
- 进程是对处理器、主存和 I/O 设备的抽象
进程和线程的区别
- 进程有独立的地址空间,线程没有独立的地址空间
- 进程的上下文切换时间开销远远大于线程上下文切换时间
- 进程的并发性较低,线程的并发性较高
- 进程有一个程序运行的入口,顺序执行序列和程序的出口,但线程不能独立执行,必须依存于应用程序,由应用程序提供多个线程执行控制
- 进程的鲁棒性更好,相互之间不会影响,一个进程的崩溃不会影响另一个进程,但一个线程的崩溃会导致其它线程的崩溃
进程之间的通信方式
管道
int pipe(int fd[2])
: 创建一个匿名管道,fd[0]
表示管道的读取端,fd[1]
表示管道的写入端。
然后使用 fork
创建子进程,为防止读写混乱,父进程往往关闭读取端,子进程关闭写入端,不管是匿名管道,还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据的时候自然也是从内核中获取,同时通信数据都遵循先入先出的原则。
共享内存
共享内存机制,就是拿出一块虚拟地址空间,映射到相同的物理地址中,从而实现进程之间的通信。
构造
- 创建共享内存:使用
shmget()
创建一个新的共享内存区域或获取一个已经存在的共享内存区域的标识符 - 连接共享内存:使用
shmat()
将共享内存区域映射到进程的虚拟地址空间中,从而使进程可以访问共享内存中的数据 - 访问共享内存:可以通过指针访问共享内存中的数据,从而实现数据共享
- 解除连接:通过调用系统函数
shmdt()
将共享内存从进程的虚拟地址空间中分离
销毁
- 解除所有进程与共享内存的连接,调用
shmdt()
将共享内存从它们的虚拟地址空间中分离 - 删除共享内存:调用
shmctl()
,传入ICP_RMID
参数,以删除共享内存对象
信号量
为了防止多进程之间竞争共享资源,造成数据混乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问。
信号初始化为 1 时,即为互斥信号量,初始化为 0 时,即为同步信号量。
信号
信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。
- 执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 SIGTERM 信号,就是终止进程的意思。
- 捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。
- 忽略信号。当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP,它们用于在任何时候中断或结束某一进程。
Socket
不同主机、同主机下不同进程都可以使用 socket.