操作系统页表&进程调度Tips

本文说两个关于时间和空间的小Tips,即CPU和内存这一对冤家…近期爆出的CVE-2019-11478竟然让这一对冤家握手言和一起做恶…详见:
https://blog.csdn.net/dog250/article/details/94654620

不说TCP了,接下来说说页表和进程调度,这可是现代操作系统的核心之核心。

页表

  1. 但凡可以索引的,就一定可以转换为查找,时间换空间。
  2. 但凡可以查找的,就一定可以转换为索引,空间换时间。
  3. 分级页表索引表占用内存比较多,但在32位系统还不算太多,所以可以使用。
  4. 分级页表索引表占用内存比较多,但在64位系统非稀疏地址结构下,也不太多,所以可以使用。
  5. 分级页表索引占用内存比较多,在64位系统稀疏地址结构情况下,将不可用。
  6. 分级页表索引全部虚拟地址映射的话,级数越多,越消耗内存,级数增加的意义在于索引稀疏地址空间有好处。

由于系统中所有的进程共享同一个物理内存空间,可以想象,由于地址空间的隔离性,每一个物理页面基本上都是属于一个进程的,那么虚拟页面向物理页面的映射就可以转换为 逐个物理页面遍历询问“你是不是已经被分配给了我?” 这样的问题。

但是物理地址空间虽然没有虚拟地址空间大,但是也不小,逐个遍历将不现实,于是,常规哈希便是立即的解决方案。即先将虚拟地址连同其进程ID哈希到一个较小的物理地址空间,然后遍历这个较小的空间即可。

考虑到页面的共享,比如Glibc这种,所谓的 冲突链表 将会有两类,即 哈希冲突共享冲突

于是,一个合理的上述类型的页表就是下面的样子:
操作系统页表&进程调度Tips_第1张图片

这就是反置页表,注意,系统中只有一张表,超级节省内存。性能取决于哈希算法性能以及同步互斥。

核心思想就是 索引一定能改成查找。

进程调度

在早期,UNIX进程调度策略五花八门,各种算法,但是那个时代已经过去了,现在是多核心时代,有更重要的事情需要关注,而不是调度策略。

在早期的单CPU时代,所有的进程都要在这唯一的CPU上排队串行,所以公平性效率就完全取决于调度算法。比如长进程不能饿死短进程,短进程要尽快结束等等。

现如今到了多核心时代,由于存在多个执行核心,调度的重点转换为了 为进程/线程寻找最合适的处理核心。 而不再是 为进程/线程选择最合适的执行时间。

那么,嵌套的问题便是,对于单独的一个处理核心,还需不需要 为进程/线程选择最合适的执行时间。 答案是需要,但是并不再重要。因为存在多个处理核心,进程/线程便不会憋住,大不了去别的处理核心呗。

那么,多核心时代,需要关注什么?

注意,多核心和多CPU并不是一个概念,稍微有区别,多核心结构中必要的东西就是缓存架构,而缓存的架构决定了进程/线程在处理核心之间的迁移,而这个正是调度的核心算法之一。

在不过度饥饿的情况下,能不迁移进程/线程就不迁移,这会提高缓存的利用率。

其次,对于单独的处理核心,我们会发现,不管是Windows NT 4.0+,还是Linux 2.6/3.x/4.x/5.x,或者FreeBSD,各种UNIX变体,千篇一律的都是类似Linux 2.6的 O ( 1 ) O(1) O(1)算法,即便Linux新的CFS也不例外:

  1. 动态优先级调整。
  2. 惩罚计算型任务,奖励IO型任务。

对于单独的一个核心,以上的技术显得成熟且足够,然而多核心之间的进程/线程迁移却还不尽人意,还有很长的路要走。参见下面的链接:
The Linux Scheduler: a Decade of Wasted Cores
原文如下:
http://www.ece.ubc.ca/~sasha/papers/eurosys16-final29.pdf

之所以会是如此糟糕,在我看来在于设计的思路,人们依然循着古老的思路做调度算法的设计,即在一个单独的处理核心上,希望找出一个最佳的时机调度一个最合适的进程/线程。

但是正相反,我觉得这并不是一个时间维度的算法,而是转换成了一个空间维度的算法,类似于内存分配的问题,而不是CPU时间分配的问题。

是的,多核心调度,类似于设计一个高效率的内存分配算法,无碎片(无忙无闲),缓存利用率高。


━━━●━━━─皮鞋湿─不会胖── 2:07
⇆ ㅤㅤ◁                       ❚❚                           ▷ ㅤㅤ

浙江温州皮鞋湿,下雨进水不会胖!!

你可能感兴趣的:(操作系统页表&进程调度Tips)