标签:
由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现。
目前,pthreads的实现有3种方式:
(1)第一,多对一,也就是库实现。
(2)第二种,1:1模式。
1:1模式适合CPU密集型的机器。我们知道,进程(线程)在运行中会由于等待某种资源而阻塞,可能是I/O资源,也可能是CPU。在多CPU机器上1:1模式是个很不错的选择。因此1:1的优点就是,能够充分发挥SMP的优势。
这种模式也有它的缺点。由于OS为每个线程建立一个内核线程,导致内核级的内存空间(IA32机器的4G虚存空间的最高1G)的大开销。第二个缺点在于,在传统意义上,在mutex互斥锁和条件变量上的操作要求进入内核态,这是因为OS负责调度,它要为线程的转态转换负全责。后面我们会看到,Linux的NPTL库避免了这个缺点,它的互斥锁与条件变量的操作在用户态完成。
(3)第三种,M:N模式。
这种模式试图兼有上面2种模式的优点。它要求一个分层的模型。比方说,某个进程内有4个线程,其中每2个线程对应一个内核线程。这样,OS知道2个实体的存在,负责它们的调度。而在一个实体内有2个线程,这2个线程间的调度就是OS不加干涉、也不知道的了。
简单的说,M:N模型的OS级调度上,跟1:1模型相似;线程间调度上,跟n:1模型相似。
优点是,既可以在进程内利用SMP的优势,又可以节省系统空间内存的消耗,而且环境切换大多在用户态完成。
缺点是显然的:复杂。
Linux线程是通过进程来实现。Linux kernel为进程创建提供一个clone()系统调用,clone的参数包括如 CLONE_VM, CLONE_FILES, CLONE_SIGHAND 等。通过clone()的参数,新创建的进程,也称为LWP(Lightweight process)与父进程共享内存空间,文件句柄,信号处理等,从而达到创建线程相同的目的。
在Linux 2.6之前,Linux kernel并没有真正的thread支持,一些thread library都是在clone()基础上的一些基于user space的封装,因此通常在信号处理、进程调度(每个进程需要一个额外的调度线程)及多线程之间同步共享资源等方面存在一定问题。Linux 2.6的线程库叫NPTL(Native POSIX Thread Library)。POSIX thread(pthread)是一个编程规范,通过此规范开发的多线程程序具有良好的跨平台特性。尽管是基于进程的实现,但新版的NPTL创建线程的效率非常高。一些测试显示,基于NPTL的内核创建10万个线程只需要2秒,而没有NPTL支持的内核则需要长达15分钟。
在Linux中,每一个线程都有一个task_struct。线程和进程可以使用同一调度其调度。内核角度上来将LWP和Process没有区别,有的仅仅是资源的共享。如果独享资源则是HWP,共享资源则是LWP。而在真正内核实现的NPTL的实现是在kernel增加了futex(fast userspace mutex)支持用于处理线程之间的sleep与wake。futex是一种高效的对共享资源互斥访问的算法。kernel在里面起仲裁作用,但通常都由进程自行完成。NPTL是一个1×1的线程模型,即一个线程对于一个操作系统的调度进程,优点是非常简单。而其他一些操作系统比如Solaris则是MxN的,M对应创建的线程数,N对应操作系统可以运行的实体。(N<M),优点是线程切换快,但实现稍复杂。
注:
(1)pthread线程库--NPTL(Native POSIX Threading Library)
在1:1核心线程模型中,应用程序创建的每一个线程(也有书称为LWP)都由一个核心线程直接管理。OS内核将每一个核心线程都调到系统CPU上,
因此,所有线程都工作在“系统竞争范围”(system contention scope):线程直接和“系统范围”内的其他线程竞争。
(2)NGPT(Next Generation POSIX Threads)
N:M混合线程模型提供了两级控制,将用户线程映射为系统的可调度体以实现并行,这个可调度体称为轻量级进程(LWP:light weight process),LWP
再一一映射到核心线程。如下图所示。OS内核将每一个核心线程都调到系统CPU上,因此,所有线程都工作在“系统竞争范围”。
标签:
原文地址:http://www.cnblogs.com/how-are-you/p/5572073.html