进程、系统调用

「多问,为什么?」能够帮助你深入理解各种你想要知道的东西?什么,你不信,那我们一起试试吧。

1. 进程

1.1 为什么需要进程

不是进程需要我们,而是我们需要进程。想象一下,现在提供一个操作系统,而你想要通过操作系统控制各种资源,包括处理器、内存、磁盘等,你会怎么做?

  • 将各个资源排队,每次都取一类资源处理,最后整和到一起使用,这得是一种多么低效的手段……
  • 提前打包好各种可能使用的资源,每次使用申请一个已经包装好各个资源的壳子出来,这就聪明很多了嘛

结论:操作系统作为硬件的使用层,提供使用硬件资源的能力,进程作为操作系统使用层,提供使用操作系统抽象出的资源层的能力。

1.2 进程的一生

1.2.1 什么是进程

进程,是指计算机中已运行的程序。进程本身不是基本的运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。

概念性的东西,笔者一向会有点抓不住重点,所以画个重点:

  • 进程是处于执行时期的程序。

  • 内核调度的对象是线程,不是进程。

  • 概念摘自维基百科,详细参考可直接戳

1.2.2 进程 — 生

在创建一个进程的时候,我们到底创建了什么?

答:其实就是一个数据结构—task_struct,这个数据结构记录进程运行需要的各种资源,像打开的文件描述符、挂起的信号量、内核内部数据、处理器状态等(ps 反正就是这个进程创建需要的各种资源……

进程创建后如何表示?

答: 为了能够找到上面创建的 task_struct,内核用双向循环链表存储 task_struct,并通过一个唯一的 PID 来标识每个进程。 (ps ?思考下:操作系统中的进程数量可以无限增加吗?

进程如何创建?

进程创建被分解到两个单独的函数中去执行:

  • fork() 拷贝当前进程创建一个子进程
  • exec() 负责读入可执行文件并将其砸入到地址空间开始运行

注意:写实拷贝,是一种推迟甚至免除拷贝数据的技术。父子进程会共享同一份拷贝,只要在需要写入的时候,数据才会被复制。写实拷贝的出现是因为直接把所有资源复制给新的创建进程效率太低,因为拷贝数据有可能根本不共享或者新进程打算执行一个新的映像,那么所有拷贝都会失效

1.2.3 进程 — 死

为什么死,还需要单独说呢?死了不就一了百了,什么都不用管了嘛……,身体发肤受之父母,总得通知下你父母吧。

谈谈进程花式死法吧?

  • 自杀 —— 显示或者隐示的调用 exit() 系统调用
  • 他杀 —— 信号量(ps 你执行了kill 什么,害死了活泼可爱的进程……)

但是无论哪种死法,你总得需要释放下创建的时候你申请的各种资源

清理完资源你就真的宣告死亡了嘛?

答:世界这么复杂,你想死也由不得你不是,所以进程死亡的时候清理资源和删除上面创建的 task_struct 是分开进行的,所以删除 task_struct 是在下面布置执行完再进行的。

  • 假如父亲健在,通知父亲儿子死亡的消息
  • 假如父亲先挂掉了,找到公共养父进程 (init) 通知儿子死亡的消息

疑问:笔者其实没想通为什么清理工作和删除 task_struct 要分开进程……

2. 系统调用

操作系统提供进程与操作系统进行交互的一组接口,这组接口被称为系统调用,提供以下能力:

  • 进程受限的访问硬件设备
  • 创建新进程
  • 与已有进程进行通信
  • 申请操作系统其它资源的能力

2.1 为什么需要系统调用

人跟人之间是没有信任的,你怎么确定进程能够按照你的想法使用操作系统,所以

  • 系统调用提供了一种硬件的抽象接口,使得进程不需要关系磁盘类型和介质等底层的信息。
  • 作为操作系统和进程的中间层,操作系统可以基于权限、用户类型和其他的一些规则对访问进行限制。

注意此处均以 linux 的操作系统为例,该系统提供系统调用接口有几百个,跟接口设计名言「提供机制而不是策略」,系统调用抽象出完成某种确定目的的函数,至于这些函数怎么用不是操作系统关系的。

2.2 系统调用怎么做

每个系统调用都被赋予一个系统调用号,通过系统调用号可以关联到系统调用。系统调用表记录了所有已注册过的系统调用列表。

进程在创建的时候会申请 4G 大小的虚拟内存,具体布局见下图。

在这里插入图片描述

内核驻留在受保护的地址空间。基于安全性的考虑不允许用户进程直接访问,所以系统调用执行的时候是通过软中断实现的,通过引发一个异常来促使系统切到内核态去执行处理程序,此时异常处理程序实际上就是系统调用的处理程序。

注:进程只有通过系统调用 和 异常处理程序 才能够访问内核。

进程上下文: 当一个进程执行系统调用或者触发某个异常,它就陷入内核空间。内核「代表进程执行」处于进程上下文。

中断上下文: 不是进程级别的,为内核所有,具体概念理解改日来补充吧,主要是笔者也木有理解的很清楚

3. 总结

笔者其实想把进程调度也加入到这篇文章的,但是想了下进程调度比较复杂,其实可以单独列出来分享一下(ps 还有就是一直被保安大叔外放的歌曲打断思路,我太难了……

4. 参考资料

  • 《Linux 内核设计与实现》3、5 两章

猜你喜欢

转载自blog.csdn.net/phantom_111/article/details/101172448
今日推荐