Linux复习 / 进程概念相关Q&A

前言

博主目前在复习Linux相关内容,这篇Q&A是其中的一部分,若你也在复习相关内容或者正在学习相关内容,可以通过这些问题检测自己的知识掌握程度。

Q&A


进程概念

Q:什么是进程?为什么要有进程?

A:进程是系统分配资源的基本单位。由于操作系统需要对系统资源进行管理,管理分为两步:先描述,再组织。由于进程承担了资源分配的基本单位,所以操作系统用数据结构来描述进程(进程控制块在Linux中被叫做task_struct,windows中被叫做PCB)。由于体系结构决定,程序运行之前要先加载到内存,那么进程就等于内存中的数据和代码+操作系统描述的数据结构。有了进程的概念,操作系统才能进行更好的资源管理,提高系统性能。

Q:如何查看系统当前运行的进程信息?

A:使用ps axj指令可以查看当前系统运行的进程。

  • a表示显示所有进程
  • x表示显示没有控制终端的进程
  • j表示显示进程的作业信息

fork

Q:为什么fork后的代码被执行了两次?

A:父子进程共享代码,两者都会执行fork之后的代码,因此这些代码被执行了两次。但是前提是:没有有if else语句分割父子进程的代码块。

Q:为什么fork有两个返回值?

A:fork的作用是创建子进程,在执行fork函数的return语句前,fork的功能已经完成,即子进程已经创建且运行起来了。由于父子进程共享代码,子进程和父进程一样处于fork函数中,两者执行同样的代码,fork的return语句当然被执行了两次。

Q:为什么fork对子进程返回0,父进程返回非0?

A:父进程和子进程的关系是一对多的关系,即一个父进程可以有多个子进程,但子进程的父进程只有一个。

  • 给父进程返回非0(子进程的pid)是为了告知父进程子进程是否创建成功
    • 若创建成功,fork给父进程返回子进程的pid,父进程可以对pid进行保存,保存的原因是:父进程可以有多个子进程,需要子进程的pid以管理子进程
    • 若创建失败,fork给父进程返回-1
  • 给子进程返回0是因为子进程只有一个父进程,0只是创建成功的象征

进程状态

Q:进程有哪些状态?它们的含义是什么?

A:

  • 创建态:进程的资源正在分配,PCB正在初始化
  • 就绪态:进程位于运行队列,但没有被cpu调度,准备被调度,此时进程状态为就绪态。除了cpu资源,进程已经获得需要的其他资源,随时都可以被调度
  • 运行态:当进程位于运行队列中,且正在被cpu执行,此时进程状态为运行态
  • 终止态:进程执行完成或者被信号终止,正在从操作系统中消失,不占用任何资源
  • 阻塞态:位于某设备等待队列的进程处于阻塞态。当某些资源没有就绪,可能是cpu资源,也可能是外设资源,此时处于运行态的进程会被移动到对应设备的等待队列中,状态切换为阻塞态
  • 挂起态:内存不足时,运行队列无法添加新的进程,此时操作系统会进行辗转腾挪,将不常用的进程移动到磁盘的swap分区,位于swap分区的进程处于挂起态。当内存资源足够时,这些进程会被换回来。所以当计算机内存资源不足时,往往伴随着高频的磁盘访问
Q:Linux具体的状态有哪些?对应操作系统的抽象状态的关系是怎样的?

A:

  • 运行(R):进程位于运行队列,表示进程随时可以被执行或者正在运行,对应操作系统的就绪态和运行态。要注意的是:只要Linux的进程位于运行队列,那么该进程就处于R状态,而R状态可以拆分为操作系统的就绪态和运行态
  • 可中断睡眠(S):进程等待非IO设备资源就绪而陷入阻塞,对应操作系统的阻塞状态,该状态可以被信号唤醒
  • 不可中断睡眠(D):进程等待IO设备的资源就绪而陷入阻塞,对应操作系统的阻塞状态,该状态不可被信号唤醒,只有请求资源就绪时才会被唤醒
  • 僵尸(Z):进程运行完成,等待父进程回收其资源以告知进程运行情况而维护的一种状态。是Linux独有的一种状态,不对应任何抽象状态。
  • 暂停(T):进程被SIGSTOP信号或者调试器暂停而处于的一种状态,可以被SIGCONT或者调试器恢复运行。没有严格的对应操作系统的抽象状态
  • 终止(X):进程在退出过程中的一种状态,存在时间短暂,很难被捕捉到。对应操作系统的终止态。
Q:S和D状态的区别?为什么有了S状态还要有D状态?

A:

  • S和D都是Linux的睡眠态,对应操作系统的阻塞态
  • 当进程等待非IO资源时,会进入S状态
  • 当进程等待IO资源时,会进入D状态
  • 它们的区别是:S是可中断状态,可以被信号打断(终止)。而D是不可中断状态,不能被信号打断,只有对应的资源就绪,进程才会被唤醒
  • 其中的原因是:为了防止某些设备陷入不可控状态
  • 举个例子:如果进程因为等待磁盘的写入而阻塞,假设磁盘的写入失败,此时操作系统要告知进程这一情况,如果进程被杀死,异常情况无法告知,磁盘设备就陷入了不可控状态,操作系统不知道磁盘的资源使用情况,可能导致数据的丢失与设备的损坏
Q:僵尸进程占用了哪些资源?

A:仍然占用进程表中的一个位置,保留了进程ID、退出状态、资源使用情况,但放弃了几乎所有的内存空间,没有任何的可执行代码,不可被调度。过多的僵尸进程不会导致内存泄漏,只会导致PID资源不足,无法创建新进程。

Q:如何释放僵尸进程的资源?

A:最简单的方法是:杀死其父进程,使其成为孤儿进程,让init进程释放其资源。或者是修改父进程的程序代码,利用wait_pid回收子进程。


进程地址空间

Q:进程地址空间的划分?每块空间存储了什么?

A:从低地址到高地址分别是:

  • 代码区:存储程序的正文代码,可读
  • 已初始化数据区:存储已初始化全局变量与静态变量,可读可写
  • 未初始化数据区:存储未初始化全局变量与静态变量,可读可写
  • 堆区:存储动态内存分配的变量,可读可写
  • 共享区:存储动态库、共享文件等,可读可写
  • 栈区:存储在函数栈帧中创建的局部变量、函数返回地址、函数参数,可读可写
  • 命令行参数与环境变量区:存储命令行参数与环境变量信息
  • 系统代码区:存储操作系统,驱动程序等,需要更高的权限访问,可读
Q:如何理解只读数据区?

A:一般情况下,硬件都是可读可写的,表现出只读的原因是:程序和硬件之间还有一层软件层,这层软件层就是虚拟地址空间和页表。程序访问的地址都是虚拟地址,只有通过页表的转换才能得到真实地址。当程序访问非法地址(只读数据区)进行写入操作时,会被软件层拦截,表现出来就是写入操作失败。但是只读属性只是虚拟出来,由软件层实现,并不是真正的只读。

Q:进程的创建过程?

A:进程在被运行之前,只是磁盘上的一份数据。由于体系结构决定,操作系统将磁盘上的数据加载到内存中,并创建task_struct保存进程的相关信息。其中,task_struct包含了页表、mm_struct等结构,这是进程的虚拟地址空间,通过页表虚拟地址可以转换为真实地址。每次创建进程,虚拟地址是不变的(每块区域存储什么样的数据不变),但是其映射的真实地址大概率发生变化。可以这样类比:真实地址是学生的座位,而虚拟地址是学生的座号,座位可能发生变化,而座号不变,通过座号与座位的映射关系,可以找到学生。

Q:fork是怎样返回两个值的?

A:之前关于这类问题的回答都是基于函数的角度,引入了进程地址空间的概念后,可以从进程地址空间的角度回答此问题。

fork之后,父子进程共享页表,两者共享同一块物理内存,此时的父子进程,无论是虚拟地址还是物理地址都是相同的,因为页表相同。当某一进程发起写操作(谁先写入)就会触发写时拷贝,比如

pid_t id = fork();

在fork没有返回之前,父子进程的id变量指向了同一块物理内存。当父进程的fork先返回时,由于父进程对共享数据发起了写操作,所以父进程会拷贝id变量所在的,修改页表,生成新页以存储fork的返回值。当然,父进程id变量的虚拟地址和子进程相同,只是因为页表不同,父进程id变量映射的物理地址与子进程id变量映射的物理地址不同。

总结一下:父子进程谁先向共享数据发起写操作,谁就要进行写时拷贝。写时拷贝不是拷贝所有页面,而是拷贝写入数据所在的页面,修改部分页表。所以写时拷贝后,父子进程的部分空间独立,部分空间仍共享。

最后:fork以写时拷贝的方式返回两个值。

Q:子进程继承父进程fork之后的代码还是父进程的所有代码?

A:虽然子进程只执行fork之后的代码,但子进程会继承父进程的所有代码。父进程的代码存储在进程地址空间的代码区,子进程与父进程共享代码区,继承了父进程的所有代码。由于程序计数器pc也被继承,所以子进程只能从fork之后开始执行代码。若想让子进程执行fork之前的代码,可以将某些代码封装成函数,fork之后再调用该函数。

Q:虚拟地址空间的意义?

A:

  1. 保证了系统安全,内存安全。虚拟地址空间可以有效防止非法访问,若没有虚拟地址空间,所有进程的数据都在物理内存上,它们可能互相影响,篡改其他进程数据,修改函数返回值,降低系统安全性
  2. 简化内存管理,减轻编译器工作。每个进程以统一的方式看待内存,且区域的边界明确。若数据的存储杂乱无章,编译器的工作将难以进行
  3. 使进程与物理地址解耦。程序编译完成就生成了虚拟地址空间,操作系统只需要生成页表,将其与物理空间进行映射,不用关心物理内存的分配,实现动态加载与动态链接
  4. 高效使用内存。虚拟地址空间使进程可以拥有比物理内存更大的空间。当物理空间不足时,系统会将不常用的进程置换到swap分区,以运行其他进程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值