1. 什么是进程?比较进程与程序
进程 :是正在运行的程序的实例,是操作系统进行资源分配和调度的基本单位,包含代码、数据、PCB(进程控制块)等。
进程 vs 程序:
程序是静态的(存储在磁盘的指令集合),进程是动态的(有生命周期:创建、运行、结束);
程序不占用系统资源,进程占用 CPU、内存等资源;
一个程序可对应多个进程(如打开多个 "记事本" 程序)。
2. 为什么要引入进程这一概念?进程存在的标志是什么?
引入原因:
程序是静态的,无法描述 "并发执行" 的动态行为(如多个程序同时运行时的资源竞争、状态变化),
进程能刻画程序的动态执行过程,实现资源分配与调度。
存在标志 :进程控制块(PCB)(操作系统通过 PCB 识别和管理进程)。
3. 什么是进程控制块?举例说明操作系统是如何利用进程控制块中的信息来管理进程的?
进程控制块(PCB):是操作系统管理进程的核心数据结构,存储进程的状态、PID、程序计数器、寄存器、资源占用等信息。
管理举例:
调度进程时,通过 PCB 中的 "优先级" 决定下一个运行的进程;
进程阻塞时,通过 PCB 中的 "状态" 将其移入阻塞队列;
进程切换时,通过 PCB 保存 / 恢复寄存器、程序计数器等上下文信息。
4. 什么是操作系统内核?操作系统内核主要完成什么功能?
操作系统内核:是操作系统的核心部分,运行在特权态,直接控制硬件并提供基础服务。
核心功能:
进程管理(调度、同步互斥)、
内存管理(分配 / 回收)、
设备管理(驱动、I/O 控制)、
中断处理。
5. 操作系统在什么时候创建进程?操作系统如何创建一个进程?
创建时机 :用户执行程序(如双击 exe)、系统启动服务(如开机启动进程)、进程主动创建子进程(如fork())。
创建过程:
- 分配唯一 PID;
- 创建 PCB 并初始化(状态设为 "就绪");
- 分配内存(加载程序代码、数据);
- 将进程加入就绪队列。
6. 什么是进程的阻塞、唤醒、挂起?
阻塞:进程因等待资源(如 I/O 完成、锁)而暂停执行,状态转为 "阻塞态",移出运行队列。
唤醒:进程等待的资源就绪后,由操作系统将其状态转为 "就绪态",加入就绪队列。
挂起:进程被暂时调出内存(如内存不足),状态转为 "挂起态",数据暂存磁盘;后续可被唤醒并调回内存。
7. 举例说明时钟对于计算机系统的重要性
时钟是系统的 "时间基准",例如:
**进程调度:**按时间片切换进程,依赖时钟中断;
**定时任务:**如 "30 分钟后自动关机",依赖时钟计时;
**时间戳:**文件修改时间、日志时间等,由时钟提供。
8. 时钟中断信号是如何产生的?时钟中断处理程序的功能是什么?
产生方式:硬件时钟(如晶体振荡器)按固定频率(如 100Hz)产生脉冲,触发时钟中断。
处理程序功能:
更新系统时间;
递减进程时间片,时间片用完则触发进程调度;
处理定时任务(如超时检测)。
9. 什么是进程的就绪态、阻塞态、执行态?在什么情况下发生三种状态的转换?
就绪态:进程已准备好,等待 CPU 调度;
阻塞态:进程等待资源,无法执行;
执行态:进程正在 CPU 上运行。
状态转换:
- 就绪→执行:进程被调度器选中;
- 执行→就绪:时间片用完,或高优先级进程进入就绪队列;
- 执行→阻塞:进程请求 I/O、等待锁等资源;
- 阻塞→就绪:进程等待的资源就绪(如 I/O 完成)。
10. 说明进程的阻塞和唤醒的过程
阻塞过程:
进程请求资源,自身状态改为 "阻塞";
操作系统将其 PCB 移入阻塞队列;
调度其他就绪进程执行。
唤醒过程:
资源就绪(如 I/O 完成),操作系统找到对应的阻塞进程;
将其状态改为 "就绪",PCB 移入就绪队列;
等待调度器选中执行。
11. 什么是用户空间?什么是系统空间?什么是系统态?什么是用户态?
用户空间:用户进程运行的内存区域,权限低,不能直接访问硬件。
系统空间:内核运行的内存区域,权限高,可直接访问硬件。
系统态(内核态):CPU 的特权模式,运行内核代码,可执行所有指令。
用户态:CPU 的非特权模式,运行用户程序,只能执行受限指令。
12. 举例说明系统调用的执行过程。系统调用和普通函数有什么区别?
系统调用执行过程(以open()为例):
1.用户程序调用open(),触发软中断(陷入内核);
2.CPU 切换到系统态,保存用户态上下文;
3.内核执行open()对应的系统调用处理函数;
4.处理完成后,恢复用户态上下文,返回用户程序。
系统调用 vs 普通函数:
普通函数:在用户态执行,不切换特权级;
系统调用:会切换到系统态,由内核执行,可访问硬件资源。
13. 什么是线程?为什么引入线程?
线程:是进程内的执行单元,共享进程的资源(内存、文件句柄等),是 CPU 调度的基本单位。
引入原因:
进程切换开销大(需切换地址空间),
线程切换开销小(共享资源),更适合并发场景(如多任务的程序)。
14. 什么是用户级线程?什么是内核级线程?试对两者进行比较
用户级线程:由用户库(如 pthread)管理,内核无感知;
内核级线程:由操作系统内核管理,内核直接调度。
比较:
| 维度 | 用户级线程 | 内核级线程 |
|---|---|---|
| 调度单位 | 进程(内核看不到线程) | 线程 |
| 切换开销 | 小(用户态切换) | 大(内核态切换) |
| 并发性 | 同一进程内线程不能并行(单 CPU) | 可并行(多 CPU) |
| 依赖内核 | 不依赖 | 依赖 |
15. 线程与进程有什么区别和联系?
联系:线程是进程的一部分,共享进程的资源(内存、文件等);一个进程至少有一个线程。
区别:
资源分配:进程是资源分配单位,线程不独立分配资源;
调度:线程是 CPU 调度单位,进程是资源隔离单位;
开销:线程切换开销远小于进程。
16. 分别说明用户级线程与内核级线程的阻塞和唤醒过程
用户级线程(阻塞):线程阻塞时,整个进程会被内核阻塞(因为内核看不到线程),需用户库调度进程内其他线程。
用户级线程(唤醒):由用户库将阻塞线程标记为就绪,等待库调度执行。
内核级线程(阻塞):线程阻塞时,内核将其状态改为阻塞,调度其他线程(同进程或其他进程)执行。
内核级线程(唤醒):内核将阻塞线程改为就绪,加入就绪队列,等待 CPU 调度。
17. 说明操作系统的引导过程
操作系统引导(开机启动)过程:
加电自检(POST):检查硬件(CPU、内存、磁盘)是否正常;
加载 BIOS:运行 BIOS 程序,找到启动设备(如硬盘);
加载引导程序(MBR):从启动设备读取 MBR(主引导记录),执行引导程序;
加载内核:引导程序加载操作系统内核到内存;
初始化系统:内核初始化硬件、启动服务,进入用户界面。
18. 用 C 语言实现一个多线程程序(以 Linux 下 pthread 为例)
c
运行
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// 线程函数:打印线程ID和计数
void *thread_func(void *arg) {
int thread_num = *(int*)arg;
for (int i = 0; i < 3; i++) {
printf("线程 %d:计数 %d\n", thread_num, i);
sleep(1); // 休眠1秒
}
pthread_exit(NULL); // 退出线程
}
int main() {
pthread_t tid1, tid2;
int num1 = 1, num2 = 2;
// 创建线程1
if (pthread_create(&tid1, NULL, thread_func, &num1) != 0) {
perror("创建线程1失败");
return 1;
}
// 创建线程2
if (pthread_create(&tid2, NULL, thread_func, &num2) != 0) {
perror("创建线程2失败");
return 1;
}
// 等待线程结束
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("所有线程执行完成\n");
return 0;
}
编译运行(需链接 pthread 库):gcc thread_demo.c -o thread_demo -pthread