Linux内核设计基础(九)之进程管理和调度

版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/BlueCloudMatrix/article/details/30799225

在Linux中进程用结构体task_struct来管理一个进程所需的全部信息(所以一般较大,在32位机上。大约有1.7KB)。为了提高效率,Linux使用了一些卓越的技术。

  • 通过slab分配task_struct结构
Linux创建进程迅速。正是由于slab分配器预先分配和反复使用task_struct。这样就避免了动态分配和释放所带来的资源消耗(毕竟一个task_struct较大。并且内核中进程的创建和消除非常频繁)。

  • 将task_struct放置在内核栈的尾端
这样做是为了让那些像x86那样寄存器较少的硬件体系结构仅仅需通过栈指针就能计算出它的位置,而避免使用额外的寄存器专门记录。由于linux使用slab动态给一个进程分配task_struct,所以linux在栈底(向下增长的栈。如图,高地址在上。且栈从高地址向低地址延伸)用一个数据结构指向slab中为之分配的task_struct,而这个数据结构是结构体thread_info,它的一个成员是指向task_struct的指针。

  • 写时拷贝
Linux创建一个进程要依次调用fork()和exec()。fork()创建子进程时,父进程和子进程共享同一份资源(以仅仅读的方式共享),而仅仅有当须要写入时,数据才会被复制,从而使各个进程拥有各自的拷贝,这样的将拷贝推迟到实际发生写入时的技术称为写时拷贝。但对于那些fork()后立即调用exec()的就不用复制了(与父进程共享一份资源就可以),由于这时不会发生写入。而大多数情况下。进程创建后会立即执行一个可执行的文件,所以这样的写时拷贝能够避免拷贝大量根本就不会被使用的数据。这也是Linux能高速执行进程的原因。

  • 强大的进程调度算法
多任务给Linux的效率提出了严峻的挑战。既要有并发的效果,又要保证公平。当代多数现代操作系统是在时间片和抢占上下功夫,从全局的角度让每一个进程获得各自理想的时间片。但Linux独树一帜。它并没有採取时间片达到公平调度。

(1)O(1) 调度:无论输入有多大,调度程序都能够在恒定时间内完毕工作,这对于大server的工作负载非常理想。但在有非常多交互程序要执行的桌面环境表现不佳。

为此,2.6内核的开发者引入了著名的”反转楼梯最后期限调度算法“,也就是后来的全然公平调度算法CFS。


(2)CFS(全然公平调度):同意每一个进程执行一段时间、循环轮转、选择执行最少的进程作为下一个执行进程,而不再採用分配给每一个进程时间片的做法。CFS在全部可执行进程总数基础上计算出一个进程应该执行多久,而不是依靠优先级(nice值)来计算时间片,nice值在CFS中被作为进程获得处理器执行比的权重——更低的nice值(优先级越高)的进程获得更高的处理器使用权重。简而言之中的一个句话,以权重来取代实际的时间片。而这个调度周期则由CFS来定。为了较好的交互性。能够设置越小的调度周期,但同一时候要承受更高的切换代价和更差的系统总吞吐能力。但当进程趋于无穷时,高昂的切换开销肯定不可接受,为此CFS引入最小粒度1ms——即每一个进程最少能获得1ms的执行时间,确保切换开销被限制在一定范围内。

但这样就产生了不公平。由于会有一些进程在这个周期内得不到时间片,所以CFS并不是是一个完美的公平调度(实际上。我个人觉得不存在绝对公平的调度),只是通常情况下系统仅仅会有几百个可执行进程,所以CFS还是相当公平的:)


猜你喜欢

转载自www.cnblogs.com/ldxsuanfa/p/10571283.html