文章目录
- 概念 组成 特征
- 状态与转换
- 进程控制
- 1. 进程的状态
- 2. 进程控制块(PCB)
- 3. 进程的创建与终止
- 进程的创建
- 进程的终止
- 4. 进程调度
- 5. 进程间通信(IPC)
- 6. 上下文切换
- 进程通信
- 1. **管道(Pipes)**
- 2. **信号(Signals)**
- 3. **消息队列(Message Queues)**
- 4. **共享内存(Shared Memory)**
- 5. **信号量(Semaphores)**
- 6. **套接字(Sockets)**
- 7. **内存映射文件(Memory-Mapped Files)**
- 典型场景
- 线程
- 单对单
- 多对单
- 多对多
- 线程的转换
- 杂七杂八知识点
概念 组成 特征
分配唯一的PID(process ID),进程所属用户,分配资源,运行情况,以上信息被保存在数据结构PCB
进程实体(进程映像)由PCB,程序段,数据段组成
状态与转换
看书完全看不懂,还不如看视频清楚
进程控制
进程控制要用原语,要一气呵成。
进程控制(Process Control)是操作系统管理和调度进程的重要组成部分。它涉及到进程的创建、执行、暂停、终止以及在不同进程之间的切换。进程是程序的一次执行实例,它包含程序代码、数据段、堆栈段以及相关资源。在操作系统中,进程控制的主要内容包括以下几个方面:
1. 进程的状态
进程可以处于不同的状态,操作系统会根据这些状态来管理进程。常见的进程状态有以下几种:
- 就绪状态(Ready):进程已准备好执行,等待CPU分配资源。
- 运行状态(Running):进程正在CPU上执行。
- 阻塞状态/等待状态(Blocked/Waiting):进程因等待某种资源(如I/O操作)而暂时停止执行。
- 终止状态(Terminated):进程已完成任务或因异常情况被终止。
2. 进程控制块(PCB)
每个进程在操作系统中都有一个与之相关的结构体,称为进程控制块(Process Control Block,PCB)。PCB中包含进程的关键信息:
- 进程ID(PID):唯一标识进程的ID。
- 程序计数器(PC):保存进程下一条将要执行的指令地址。
- CPU寄存器:用于保存进程执行过程中CPU的寄存器内容。
- 进程状态:记录进程当前的状态(就绪、运行、等待等)。
- 记忆信息:进程的地址空间、内存使用情况等。
- I/O状态:与该进程相关的I/O设备信息。
操作系统通过PCB来跟踪进程的执行情况,并进行上下文切换。
3. 进程的创建与终止
进程的创建和终止是进程控制的两个基本操作。
进程的创建
创建进程时,操作系统会为新进程分配必要的资源,如内存空间、文件描述符等。通常,进程创建的方式是通过系统调用来实现的。在Linux系统中,使用fork()
系统调用创建新进程。fork()
会将当前进程复制为一个子进程,子进程和父进程执行相同的代码,但它们各自拥有不同的进程ID。
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程
printf("This is the child process.\n");
} else {
// 父进程
printf("This is the parent process.\n");
}
return 0;
}
进程的终止
进程执行完任务或因异常情况退出时,系统会释放与该进程相关的所有资源。进程终止的常见方式有两种:
- 正常终止:进程执行完任务,调用
exit()
函数。 - 异常终止:进程由于某些错误(如非法操作、段错误)被系统强制终止。
4. 进程调度
进程调度是操作系统管理CPU资源的重要机制。调度程序负责决定哪一个进程应该进入运行状态,并控制进程在CPU上的执行顺序。常见的调度算法有:
- 先来先服务(FCFS):按照进程到达的顺序调度执行。
- 最短作业优先(SJF):选择预计执行时间最短的进程。
- 轮转法(Round Robin):每个进程分配固定时间片,轮流执行。
- 优先级调度(Priority Scheduling):根据进程的优先级调度,优先级高的进程先执行。
5. 进程间通信(IPC)
进程间通信(Inter-Process Communication, IPC)用于在不同进程之间传递数据。由于进程具有独立的内存空间,它们无法直接共享数据,因此需要通过IPC机制进行通信。常见的IPC机制包括:
- 管道(Pipe):用于在父子进程之间传递数据。
- 消息队列(Message Queue):允许进程之间发送和接收消息。
- 共享内存(Shared Memory):多个进程可以直接访问共享的内存区域。
- 信号量(Semaphore):用于同步多个进程的执行,避免竞争条件。
- 套接字(Socket):用于网络通信进程之间的数据交换。
6. 上下文切换
当操作系统从一个进程切换到另一个进程时,需要保存当前进程的状态并恢复新进程的状态,这个过程称为上下文切换(Context Switch)。上下文切换的开销较大,因为需要保存和恢复寄存器、程序计数器等信息。
进程通信
进程间通信(Inter-Process Communication,简称 IPC)是指不同的进程之间通过某种机制来交换数据或信息。由于操作系统中不同的进程有独立的地址空间,它们无法直接共享内存中的数据,所以需要使用特定的通信方式来进行数据交换。
IPC 的应用场景非常广泛,例如在多任务环境中,不同的进程可能需要协作完成复杂任务,或者当一个进程产生数据时,另一个进程需要接收并处理这些数据。常见的 IPC 机制有以下几种:
1. 管道(Pipes)
管道是一种最古老和简单的 IPC 方式,允许一个进程将输出重定向到另一个进程的输入。管道有以下两种类型:只能半双工通信
-
匿名管道(Unnamed Pipe):只能用于父子进程之间的通信,具有单向性。数据在管道中只能从一端写入,从另一端读取。
-
命名管道(Named Pipe,也叫 FIFO):可以用于任意进程间的通信,双向通信,但必须要通过文件系统来建立命名管道。
优点:简单易用,特别适用于父子进程通信。
缺点:数据只能一次性传递,无法保留状态,而且只能在同一台主机上使用。
2. 信号(Signals)
信号是一种简单的异步通信方式,通常用于通知进程发生了某些事件。例如,一个进程可以向另一个进程发送一个信号,告诉它发生了特定的情况(如结束进程、暂停执行等)。
优点:操作简单,可以异步通知。
缺点:信号本身只传递很少的信息(通常就是信号的类型),不适合复杂数据传递。
3. 消息队列(Message Queues)
消息队列允许进程以消息的形式传递数据。消息队列可以看作一个链表,进程可以将消息放入队列,另一个进程从队列中读取消息。
直接通信方式,间接通信方式。
需要两个原语:发送原语和接收原语
优点:消息队列可以跨多个进程使用,且支持消息的优先级。
缺点:需要显式地管理消息队列,消息大小有一定的限制。
4. 共享内存(Shared Memory)
共享内存是最快的 IPC 方式之一,它允许多个进程共享一段内存。进程可以通过读取和写入这段共享内存来通信。但因为多个进程可以同时访问这段内存,因此需要同步机制(如信号量)来避免竞争条件和数据不一致的问题。
要保证共享访问是互斥的
优点:效率非常高,适合大量数据交换。
缺点:需要管理内存同步,编程复杂。
5. 信号量(Semaphores)
信号量主要用于解决共享资源访问的同步问题,它本身并不传递数据,而是用于协调多个进程对共享资源的访问,确保某个时刻只有一个进程可以访问资源。
优点:用于进程同步,避免竞争条件。
缺点:只能传递同步信息,不传递实际数据。
6. 套接字(Sockets)
套接字不仅可以用于进程间通信,还可以用于网络通信。套接字允许两个进程通过网络或本地的通信机制进行数据传输。通过 TCP/IP 或者 UNIX 套接字,进程可以实现双向通信。
优点:可以用于不同主机之间的通信,不局限于本地进程。
缺点:通信成本较高,编程相对复杂。
7. 内存映射文件(Memory-Mapped Files)
进程可以通过将文件映射到内存地址空间,来实现文件内容的共享。不同进程可以通过映射同一个文件的方式,达到共享数据的目的。
优点:适合用于共享大量数据的进程间通信。
缺点:需要处理文件系统的管理,使用复杂。
典型场景
- 多进程服务器:使用套接字实现进程之间的数据传递和客户端请求的处理。
- 多进程的图像处理任务:使用共享内存或消息队列,在不同进程间传递大块数据(如图像)。
- 父子进程的同步和通信:使用信号量、管道来同步资源访问或传递控制信号。
选择适合的 IPC 方式,取决于具体场景中需要传递的数据量、速度、复杂性等因素。
线程
单对单
一对一模型:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
多对单
多对多
线程的转换
杂七杂八知识点
程序封闭性指进程的结果只取决于本身,不受外界影响。
C语言编写的程序在使用内存时一般分为三个段,它们一般是正文段(即代码和赋值数据段)、数据堆段和数据栈段:二进制代码和常量存放在正文段,动态分配的存储区在数据堆段,临时使用的变量在数据栈段。由此,我们可以确定全局赋值变量、常量在正文段赋值数据段,未赋值的局部变量和实参传递在栈段,动态内存分配在堆段,进程的优先级只能在 PCB内。
只要就绪队列不空,无论多少进程就绪数目,CPU效率不变。
不同进程有不同的代码段和数据段,全局变量只针对同一个进程
进程创建原语完成的工作是:向系统申请一个空闲PCB,为被创建进程分配必要的资源,然后将其PCB初始化,并将此PCB插入就绪队列,最后返回一个进程标志号。