Linux线程模型概述

来源:互联网 发布:linux登陆oracle命令 编辑:程序博客网 时间:2024/05/17 01:21

 

                                              By cszhao1980

1. 轻量进程(LWP)

我们知道进程拥有大量资源,如:

(1)寄存器信息,如pc等;

(2)Data段

(3)Stack;

(4)正文段(可与其他进程共享);

(5)open 的file;

(6)信号;

(7)etc。

 

在进行context switch时,os必须妥善的保存进程的各种资源,开销较大,故进程有也被称为重量进程(HWP)。传统的

操作系统中的并发由进程构成,其缺点有二:

(1)正如前面所说,其context switch的开销较大;

(2)进程间难以进行数据和资源的共享(事实上,这也是其优点之一)。

 

因此,人们逐步提出了线程的概念,其特点是掌控的资源较少,从而减少了thread switch的开销,故thread也被成为轻量进程。

 

线程拥有的资源主要有两个:

(1)寄存器信息;

(2)一些状态新型;

【注】:线程自己的Stack往往属于进程stack的一部分,switch时通常无需专门进行保存。

 

而在thread switch时,往往只需要保存寄存器信息,故switch的开销较小。而由于thread与进程共享大量资源,线程间的通讯

就要容易的多。

2. user level 与kernel level

线程的实现分为两种方式,user Level实现,和kernel Level实现。

 

所谓user Level的线程实现,指操作系统内核对Thread一无所知,它仍然以进程为单位进行调度。而线程以及线程调度,
完全由user进程完成。我们可以简单理解为user进程又实现了自己的一个“内核”,通过它进行线程调度。

比如,OS分给进程一个50毫秒的时间片,user进程可以将其分为5个10毫秒的小时间片,轮流安排5个线程运行。

 

User level thread的最大优点是,它真正实现了低消耗的thread switch——事实上,前面一直提到的低消耗指的就是同一

进程内的thread switch;不同进程间的Thread switch等同于进程switch。

 

它的另一个优点是,可以针对不同的应用灵活的设计switch策略,从而针对不同的应用进行优化。

 

但user Level也有其不可避免的缺陷,比如,由于操作系统不参与其中,无法使用os提供的各种便利,

比如,thread block时,会导致整个进程被block。当然,我们可以采用不同的手段来弥补这些缺陷,比如,对thread block,

可在编译器的协助下,对各种系统调用进行特殊的包装,比如将IO操作替换为相应的异步版本等等。但总的来说,很难完全

避免这些缺陷。

 

Kernel Level就比较好理解了,kernel明晰thread的存在并以thread为单位进行调度。 同样,kernel Level也有其优缺点,总

的来说它与user level基本属于“逆”的关系,它很好弥补了user Level的缺陷,但却在user level的长处上载了跟头。当然,

我们也可用通过一定的手段来弥补它的缺陷,比如在设计调度算法时,将thread的隶属关系也考虑进来,尽量安排同进程间

的thread switch。但总的来说,其缺陷也难以完全弥补。

 

我们还可用混合使用这两种模式,即在kernel线程的基础上,为某些应用采用user level的Thread调度,从而达到更好的使用效果。

 

在讨论线程模型时,我们还会看到另一套术语,如一对一,多对一和多对多。粗略说来,这套术语和前面所说基本上时一一对应的:

(1)一对一即kernel level的线程模型,一个线程是一个调度单元;

(2)多对一即user level的线程模型,调度以进程为单位,对应user态的多个线程;

(3)多对多即混合模式,内核中的线程在user态可调度多个user态的线程。

3. Linux线程模型概述

Linux的发展过程中,出现过很多个不同的线程库实现。其中两个实现先后成为了标准,即早期的LinuxThread库和后来的NPTL库。

LinuxThread采用一对一模型,它使用clone系统调用来产生“线程”——这里的线程加了引号,这是因为,它实在难以被看作是

传统意义上的线程。一方面,通过设置参数,可以使新生的线程与父进程共享资源,确实符合轻量进程的定义;但另一方面,它

又具备了进程的若干特性,如拥有独立的进程id和信号机制等等。事实上,在这种实现中linux kernel在进行调度时,仍然按照传

统的进程调度机制,在这个意义上,是将“线程”当作进程来处理的。

这样的实现有一些缺陷,比如:

(1)首先它不完全符合POSIX标准,比如在信号处理方面,它是基于“线程”的;

(2)基于clone的实现使其多线程程序移植困难;

(3)由于内核实际上将线程“认作”进程,因此针对进程的诸多限制也被应用在线程上,

        比如可用进程总数等等;

为改正这些缺陷,一个新的线程库被发展起来,即red hat开发的NPTL库。NPTL符合 POSIX 标准,且与LinuxThreads 相比,在性能

和稳定性方面也提供了重大的改进。自2.6内核以来,NPTL取代LinuxThreads成为了新的Linux线程标准。

需要注意的是使用2.6(或更好)内核并不等于使用了NPTL,有些发行版会同时携带NPTL和LinuxThreads,而使用哪个库是可以配置

的。用下面的命令可以查看你的系统上正在使用实现:

         >getconf GNU_LIBPTHREAD_VERSION

在笔者的fedora 17系统中,显示为“NPTL 2.15”。 您的呢?

 

原创粉丝点击