我是如何学习写一个操作系统(五):故事的高潮之进程和线程1

  • 2019 年 10 月 3 日
  • 笔记

前言

为什么取这个标题呢?一是进程和线程是作为操作系统里最重要最核心的一部分。二是确实吃冰棍拉冰棍,没话,强行凑标题和之前的标题差不多字数。

前一章写了系统调用的过程,算是一个小插曲,这个部分不管在哪里应该都是可以的。

现在的这个系列已经和之前的标题渐行渐远了,原本是想以之前写的一个玩具型操作系统FragileOS为主线,但是在看书学习的过程中稍微改了一下方向,已经不是特别关注一个操作系统的实现的完整流程和内部的联系,更多的是想系统的学习操作系统的各个模块然后辅以一些代码,但是不管怎么样,都是属于自己在学习操作系统的过程的一个记录

进入正题

进程

进程的出现最最主要的原因就是想要提高CPU的利用率

进程的定义

  • 正在执行的程序
  • 正在计算机上执行的程序实例
  • 能够分配给处理器并由处理器执行的实体
  • 一组指令的执行、一个当前状态和相关的系统资源的集合

多进程的组织

单核CPU在同一时刻只能运行一条指令,所谓的多进程只是指令来回切换的假象,但是因为速度太快,就可以看成是同时进行的。所以在进程切换的时就需要去组织进程的切换

进程控制块(process control block)

控制进程的切换一个重要的数据结构就是进程控制块(process control block),是与每个进程相关的还有操作系统用于控制进程的许多属性的集合

进程控制块的作用,是使一个在多道程序环境下不能独立进行的程序(含数据),成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。或者说,操作系统是根据PCB来对并发执行的进程进行控制和管理。

一般情况下,PCB中包含以下内容:

  • 进程标识符(内部,外部)
  • 处理机的信息(通用寄存器,指令计数器,PSW,用户的栈指针)。
  • 进程调度信息(进程状态,进程的优先级,进程调度所需的其它信息,事件)
  • 进程控制信息(程序的数据的地址,资源清单,进程同步和通信机制,链接指针)

进程的五状态模型

进程的调度

一般来说,可能让进程发生切换有这几种事件:

但是随着PC的发展,这种从两方面情况发生了变化。第一,大多数时间都只有一个活跃的进程。毕竟一般来说,你在使用Word编辑文件时,不太可能还同时让系统在后台编译程序。这样的情况下,调度器其实不需要做很多工作来决定到底运行哪个进程——Word几乎就是唯一的选择。第二,计算机的速度越来越快,以至于CPU可能已经不再那么稀缺了。对于很多PC的程序来说,其限制主要在于用户能进行输入的比例,而不是CPU能够处理的比例。甚至就算是两个程序真的同时进行,其实先调度哪个运行也无伤大雅,例如,一个Word和一个Excel同时在运行,先调度哪个都行,因为用户可能同时在等待这两个程序的输出。

但是对于网络服务器来说,这种情况又不一样了。非常多的程序竞争CPU资源,因此,调度又变得非常重要了。举例来说,调度器需要决定到底是让日常统计进程运行还是让响应用户请求的进程运行。

调度器除了需要考虑选择哪个进程运行,还需要考虑到系统的性能。毕竟,进程之间的切换是开销很大的,这涉及到从用户态到内核状态的切换,进程状态的保存、恢复等等操作。

参考链接

进程的同步和合作

内存管理

在进程进行来回切换如何保证当前进程的运行不会影响其它进程的运行,比如对于一个内存进程的读写,就要保证不能越界

所以就需要一个机制来把进程之间的地址空间隔离开

进程的同步

不同进程间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,达到资源共享和进程协作,避免进程之间的冲突,就需要进程同步的概念。

多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所使用,我们把一次只允许一个进程使用的资源成为临界资源。
对临界资源的访问,必须互斥的进行。每个进程中,访问临界资源的那段代码成为临界区。
为了保证临界资源的正确使用,可以把临界资源的访问过程分为四个部分。

  • 进入区。为了进入临界区使用临界资源,在进入去要检查可否进入临界区。
  • 临界区。进程中访问临界资源的那段代码。
  • 退出区。将正在访问临界区的标志清除。
  • 剩余区。代码中的其余部分。

一般实现进程的同步有这几种方法:

  • 提过硬件提供的实现
  • 信号量
  • 管程

线程

进程是资源分配的最小单位,线程是CPU调度的最小单位

在进程的切换时还需要对内存资源的一个切换,但是线程则不需要对资源的切换,所以引入是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。

用户级线程和内核级线程

用户级线程是指不需要内核支持而在用户程序中实现的线程,内核对线程包一无所知。从内核角度考虑,就是按正常的方式管理,即单线程进程,但是它不能像内核级线程一样更好的运用多核CPU。

内核级线程建立和销毁都是由操作系统负责、通过系统调用完成的。在内核的支持下运行,无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。

  • 试想一下如果没有内核级线程,当用户级的一个线程进行到I/O阻塞时,将会导致所有的线程都堵塞,因为以操作系统的层面来看,它们都属于用一个进程,所以会直接切换进程,其它的线程就得不到执行

  • 在多处理器系统中,内核级线程能够真正的实现并行,能够执行同一进程内的多个线程

小结

这一篇主要是简略的总结书上的一些概念,没有干货,在后面进行代码实现的时候会再深入的去看。下一篇可能会去看Linux0.12在进程上面的实现。