一.进程和线程的区别
1.本质区别和所属关系是什么?
进程是资源调度以及分配的基本单位。
线程是CPU调度的基本单位。
一个线程属于一个进程,一个进程可以拥有多个线程。
2.地址空间和内存
进程拥有独立的虚拟地址空间。
线程没有独立的地址空间;线程有栈,程序计数器(PC),本地存储(LS) 等少量独立空间。
系统会为每个进程分配不同的内存空间
系统不会为线程分配内存,线程所使用的资源来自所属的进程资源。
3.并发性和健壮性
进程的并发性较低。
线程的并发性较高。
对于单个CPU,系统会把CPU运行时间划分为多个时间段,再将时间段分配给各个线程执行。
在切换效率上,进程切换效率低,线程切换效率高,都会涉及到上下文的切换。
一个进程崩溃不会影响其他进程。
一个线程崩溃可能会导致整个进程崩溃 。
进程隔离性更强一些。
二.操作系统中进程和线程的切换过程
1.进程由哪几个部分构成?
task_struct
进程的地址空间 = 代码段___数据段___栈区____堆区
2.上下文由哪几个部分组成?
用户级上下文
系统级上下文 = __进程标识符信息__进程现场信息__进程控制信息__系统内核栈
寄存器上下文(硬件上下文) = __CPU各寄存器的内容___进程的现场信息
3.何时发生切换?
主动 = 系统调用,产生软中断。
被动 = 时间中断
靠中断来完成切换
4.现场信息存储在哪里?
程序计数器(PC),寄存器,堆栈,进程/线程控制块(PCB)
5.进程/线程切换过程
保存当前进程的硬件上下文,修改当前进程的PCB,状态由运行态变为就绪态或者阻塞态,加入相关队列,调度另外一个进程,修改被调度进程的PCB,状态变为运行态,把当前进程的存储管理数据改为被调度进程的存储管理信息(页表,cache,TLB)__(这一小段线程没有__线程不具备虚拟地址空间__共享进程的虚拟地址空间),恢复被调度进程的硬件上下文,让PC指向新的进程代码。
三.系统调用的整个流程
1.系统调用是什么?干嘛的?
系统调用是内核给用户程序提供的编程接口,内核具有最高的权限,可以直接访问所有资源,用户只能访问受限制的资源,不能直接访问内存,网络,磁盘等硬件资源。
大致的流程 = 应用程序--->函数库---->系统调用--->内核
靠中断使程序从用户态切换到内核态或者从内核态切换到用户态
2.系统调用是否引起进程或者线程切换?
不会必然切换:很多系统调用(如
getpid()
、gettimeofday()
等)只是简单地获取信息,执行很快,不会导致进程或线程切换。可能导致切换:如果系统调用涉及阻塞操作(如
read()
、write()
、accept()
、sleep()
等),当前进程或线程因为等待I/O或资源而被阻塞,操作系统会把它挂起,调度其他进程或线程运行,这时就会发生切换。主动让出CPU:有些系统调用(如
sched_yield()
、sleep()
)会主动让出CPU,也会导致切换。
3.系统调用引起中断上下文切换
系统调用一定会引起用户态到内核态的中断上下文切换,但是否会引起进程或线程的切换,要看系统调用是否导致阻塞或主动让出CPU。
4.系统调用的流程
用户态发起系统调用
应用程序通过调用库函数(如C语言的read()
、write()
等)发起系统调用请求。陷入内核态
库函数内部会使用特定的指令(如x86上的syscall
或int 0x80
)触发软中断或陷入,CPU从用户态切换到内核态。保存现场
CPU会保存当前用户态的寄存器等现场信息,确保系统调用返回后能恢复原来的执行状态。内核处理系统调用
操作系统根据系统调用号找到对应的内核服务例程,执行相应的内核代码,完成所需的操作(如文件读写、进程管理等)。返回用户态
系统调用执行完毕后,内核将结果返回给用户程序,并通过特定的指令(如sysret
)切换回用户态,恢复之前保存的现场。用户程序继续执行
用户程序获得系统调用的返回值,继续后续的执行。
四.后台进程有什么特点?
1.前台进程是什么?有什么用?
运行在前台的进程,终端是该进程的控制终端,终端关闭(SIGHUP),进程退出。
可接受终端输入,并可以在终端输出。
2.后台进程是什么?有什么用?
运行在后台的进程,若在终端运行,终端关闭,进程可能退出。
不可以接受终端输入,可以在终端输出。
3.前后台程序切换
Ctrl + Z:可以将当前前台运行的程序挂起,转为后台暂停状态。
fg:用于将后台的程序切换回前台继续运行。
bg:让已经挂起的后台程序在后台继续运行。
&:在命令末尾加上&,可以让程序直接在后台运行。
nohup:用于忽略SIGHUP信号,通常配合&一起使用,保证程序在终端关闭后依然运行。
Ctrl + D:用于断开当前终端的session,相当于退出登录。
4.守护进程
后台进程的延申,脱离终端的后台进程。
5.如何成为守护进程?
fork子进程令父进程退出,让子进程被init进程接管,成为孤儿进程。
setsid()建立新的进程会话,使守护进程成为会话首进程,从而脱离与终端的关联。
打开/dev/null,把0,1,2重新定向到/dev/null。
五.进程间通信有哪几种方式
1.管道
单根管道是半双工的,通常用于父子进程之间,通过pipe文件速度慢,容量有限。
2.FIFO (有名/命名管道)
FIFO(First In First Out)有名管道是一种用于进程间通信(IPC)的机制。与匿名管道不同,有名管道有一个路径名,存在于文件系统中,通常通过
mkfifo
命令或mkfifo()
系统调用创建。
3.消息队列
消息的连接表存储在内核当中,独立于进程,容量有限。
消息队列的流程主要包括通过
msgget
创建队列,使用msgsnd
发送消息,msgrcv
接收消息,最后用msgctl
管理或删除队列。
4.共享内存
多个进程共享的一块存储区,最快的一种IPC方式,需要和信号量配合使用。
共享内存的接口使用流程主要包括通过
shmget
创建共享内存,shmat
挂载到进程地址空间,进程间读写数据,最后用shmdt
分离和shmctl
删除共享内存。
5.信号
信号是一种软中断,处理方式是忽略/捕获/默认动作。
6.信号量
信号量是一个计数器,主要用于进程/线程之间的同步和互斥。
7.socket套接字
不局限于是否在同一个机器上。
六.操作系统中进程调度策略
1.什么是进程调度?
调度对象
线程和进程相对于操作系统而言都是任务(task_struct)。
线程又称为共享用户虚拟地址空间的进程。
包含多个线程的进程称之为线程组。
只有一个线程的进程称为进程。
没有用户虚拟地址空间的进程称之为内核线程。
用于绝对由谁(哪个或者哪几个)获得处理器的执行权
进程状态
就绪 -->|进程调度| 运行
运行 -->|时间片用完| 就绪运行 -->|io请求| 阻塞
阻塞 -->|io就绪| 就绪
调度时机
主动调度(系统调用等待某个资源)。
周期调度(系统进程不主动让出,内核依靠周期时钟来抢占调度)。
唤醒抢占,创建新进程抢占,内核抢占。
2.进程调度有哪些算法?
先来先服务(FCFS)
从就绪队列中存在时间最长的进程执行调度。
短作业优先(SJF)
从就绪队列中选择估计运行时间最短的任务执行调度
高响应比优先
FCFS和SJF的综合;综合考虑等待时间和估计运行时间来选择执行调度。
时间片轮转调度
适用分时系统,为任务分配时间片,执行完时间片后放入就绪队列。
优先级调度
从就绪队列中选择优先级最高的若干任务执行调度。
优先级用来描述运行的紧迫程度。
多级反馈队列
时间片和优先级的综合。
动态调整任务的优先级和时间片的大小,从而兼顾多方面的系统目标。