linux进程和线程实现

抛砖引玉,先说下fork和vfork的区别。

fork时,子进程是父进程的一个拷贝。子进程从父进程那得到了数据段和堆栈段,但不是与父进程共享而是单独分配内存。然而这里的非共享最初状态是共享的,linux下使用了写时复制技术,刚开始共享父进程的数据段,在写数据段的时候才进行复制。具体到底层的clone调用,形式是clone(0)

vfork时,因为实现为子进程先执行,所以是不拷贝(没必要)父进的虚存空间,clone(clone_vfork|clone_vm|sigchld,0),指明的参数是不会拷贝,注定共享的。因为现在的fork都是写实拷贝,所以vfork的优势便不明显了。

另外,内核都是优先让子进程先执行,考虑到调度问题,fork不保证;但是vfork可以保证这点!

 

下面说下线程的实现,首先从OS设计原理上阐明三种线程:内核线程、轻量级进程、用户线程

内核线程

内核线程就是内核的分身,一个分身可以处理一件特定事情。这在处理异步事件如异步IO时特别有用。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫做多线程内核(Multi-Threads kernel )。

轻量级进程[*]

轻量级线程(LWP)是一种由内核支持的用户线程。它是基于内核线程的高级抽象,因此只有先支持内核线程,才能有LWP。每一个进程有一个或多个LWPs,每个LWP由一个内核线程支持。这种模型实际上就是恐龙书上所提到的一对一线程模型。在这种实现的操作系统中,LWP就是用户线程。

由于每个LWP都与一个特定的内核线程关联,因此每个LWP都是一个独立的线程调度单元。即使有一个LWP在系统调用中阻塞,也不会影响整个进程的执行。

轻量级进程具有局限性。首先,大多数LWP的操作,如建立、析构以及同步,都需要进行系统调用。系统调用的代价相对较高:需要在user mode和kernel mode中切换。其次,每个LWP都需要有一个内核线程支持,因此LWP要消耗内核资源(内核线程的栈空间)。因此一个系统不能支持大量的LWP。

linux进程和线程实现 

注:

LWP 的术语是借自于 SVR4/MP 和 Solaris 2.x 。有些系统将 LWP 称为虚拟处理器。而将之称为轻量级进程的原因可能是:在内核线程的支持下, LWP 是独立的调度单元,就像普通的进程一样。所以 LWP 的最大特点还是每个 LWP 都有一个内核线程支持。

 

用户线程

LWP虽然本质上属于用户线程,但LWP线程库是建立在内核之上的,LWP的许多操作都要进行系统调用,因此效率不高。而这里的用户线程指的是完全建立在用户空间的线程库,用户线程的建立,同步,销毁,调度完全在用户空间完成,不需要内核的帮助。因此这种线程的操作是极其快速的且低消耗的。

linux进程和线程实现 

上图是最初的一个用户线程模型,从中可以看出,进程中包含线程,用户线程在用户空间中实现,内核并没有直接对用户线程进程调度,内核的调度对象和传统进程一样,还是进程本身,内核并不知道用户线程的存在。用户线程之间的调度由在用户空间实现的线程库实现。

这种模型对应着恐龙书中提到的多对一线程模型,其缺点是一个用户线程如果阻塞在系统调用中,则整个进程都将会阻塞。

加强版的用户线程——用户线程+LWP

这种模型对应着恐龙书中多对多模型。用户线程库还是完全建立在用户空间中,因此用户线程的操作还是很廉价,因此可以建立任意多需要的用户线程。操作系统提供了 LWP 作为用户线程和内核线程之间的桥梁。 LWP 还是和前面提到的一样,具有内核线程支持,是内核的调度单元,并且用户线程的系统调用要通过 LWP ,因此进程中某个用户线程的阻塞不会影响整个进程的执行。用户线程库将建立的用户线程关联到 LWP 上, LWP 与用户线程的数量不一定一致。当内核调度到某个 LWP 上时,此时与该 LWP 关联的用户线程就被执行。
linux进程和线程实现 

很多文献中都认为轻量级进程就是线程,实际上这种说法并不完全正确,从前面的分析中可以看到,只有在用户线程完全由轻量级进程构成时,才可以说轻量级进程就是线程。

一句话点睛:

LinuxThreads 所实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库(我们常用的pthread库)中实现。

 

参考文献:linux内核设计与实现 3.4 线程在linux中的实现

     APUE 8.4 VFORK函数

       linux内核源代码情景分析 4.3 系统调用fork vfork clone

     Linux 线程实现机制分析 http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
     关于进程、线程和轻量级进程的一些笔记 http://www.cnitblog.com/tarius.wu/articles/2277.html

     

 

linux进程和线程实现,布布扣,bubuko.com

linux进程和线程实现

上一篇:数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现


下一篇:二叉查找树实现实例(C语言)