NPTL的解释

来源:互联网 发布:CBA个人数据 编辑:程序博客网 时间:2024/06/06 00:23

 

 

 并行技术
并行技术可分为三类,分别是线程库、消息传递库和编译器支持。线程库(如 POSIX* 线程和 Windows* API线程)可实现对线程的显性控制;如果需要对线程进行精细管理,可以考虑使用这些显性线程技术。借助消息传递库(如消息传递接口〔MPI〕),应用程序可同时利用多台计算机,它们彼此间不必共享同一内存空间。MPI广泛应用于科学计算领域。第三项技术是在编译器中实现的线程处理支持,采用的形式自动并行化。一旦将线程处理引入到应用程序中,开发人员就可能要面对一系列新的编程缺陷(Bug)。其中许多缺陷是难以检测到的,需要付出额外的时间和关注以确保程序的正确运行。一些比较常见的线程处理问题包括:数据争用,同步,线程停顿 ,死锁 ,共享错误.
并行技术可以分为多进程编程和多线程编程。人们总会用某种IPC(inter-processcommunication,进程间通信)的形式来实现进程间同步,如管道(pipes),信号量(semaphores),信息队列(messagequeues),或者共享存储(sharedmemory)。在所有的这些IPC形式中,共享存储器是最快的(除了门(doors)之外)。在处理进程间资源管理,IPC和同步时,你可以选择POSIX或者System V的定义。
线程技术早在20世纪60年代就被提出,但真正应用多线程到操作系统中还是在20世纪80年代中期。现在,多线程技术已经被许多操作系统所支持,包括Windows NT/2000和Linux。
在1999年1月发布的Linux 2.2内核中,进程是通过系统调用fork创建的,新的进程是原来进程的子进程。需要说明的是,在Linux 2.2.x中,不存在真正意义上的线程,Linux中常用的线程Pthread实际上是通过进程来模拟的。
也就是说,Linux中的线程也是通过fork创建的,是“轻”进程。Linux 2.2缺省只允许4096个进程/线程同时运行,而高端系统同时要服务上千的用户,所以这显然是一个问题。它一度是阻碍Linux进入企业级市场的一大因素。
2001年1月发布的Linux 2.4内核消除了这个限制,并且允许在系统运行中动态调整进程数上限。因此,进程数现在只受制于物理内存的多少。在高端服务器上,即使只安装了512MB内存,现在也能轻而易举地同时支持1.6万个进程。
在Linux 2.5内核中,已经做了很多改进线程性能的工作。在Linux 2.6中改进的线程模型仍然是由Ingo Molnar来完成的。它基于一个1:1的线程模型(一个内核线程对应一个用户线程),包括内核内在的对新NPTL(Native Posix ThreadingLibrary)的支持,这个新的NPTL是由Molnar和Ulrich Drepper合作开发的。
2003年12月发布的Linux 2.6内核,对进程调度经过重新编写,去掉了以前版本中效率不高的算法。进程标识号(PID)的数目也从3.2万升到10亿。内核内部的大改变之一就是Linux的线程框架被重写,以使NPTL可以运行其上。
在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_semaphore)、spinlock、BKL(Big KernelLock)、rwlock、brlock(只包含在2.4内核中)、RCU(只包含在2.6内核中)和seqlock(只包含在2.6内核中)。
现在的随着现在计算机体系结构的发展,指令级的并行和线程级的并行都在日新月异地发展着.

 

 

2.

2006 年 8 月 28 日

LinuxThreads 项目最初将多线程的概念引入了Linux®,但是 LinuxThreads 并不遵守 POSIX 线程标准。尽管更新的 Native POSIX ThreadLibrary(NPTL)库填补了一些空白,但是这仍然存在一些问题。本文为那些需要将自己的应用程序从 LinuxThreads 移植到NPTL 上或者只是希望理解有何区别的开发人员介绍这两种 Linux 线程模型之间的区别。

当 Linux 最初开发时,在内核中并不能真正支持线程。但是它的确可以通过 clone()系统调用将进程作为可调度的实体。这个调用创建了调用进程(callingprocess)的一个拷贝,这个拷贝与调用进程共享相同的地址空间。LinuxThreads项目使用这个调用来完全在用户空间模拟对线程的支持。不幸的是,这种方法有一些缺点,尤其是在信号处理、调度和进程间同步原语方面都存在问题。另外,这个线程模型也不符合 POSIX 的要求。

要改进 LinuxThreads,非常明显我们需要内核的支持,并且需要重写线程库。有两个相互竞争的项目开始来满足这些要求。一个包括IBM 的开发人员的团队开展了 NGPT(Next-Generation POSIX Threads)项目。同时,Red Hat的一些开发人员开展了 NPTL 项目。NGPT 在 2003 年中期被放弃了,把这个领域完全留给了 NPTL。

尽管从 LinuxThreads 到 NPTL 看起来似乎是一个必然的过程,但是如果您正在为一个历史悠久的 Linux发行版维护一些应用程序,并且计划很快就要进行升级,那么如何迁移到 NPTL上就会变成整个移植过程中重要的一个部分。另外,我们可能会希望了解二者之间的区别,这样就可以对自己的应用程序进行设计,使其能够更好地利用这两种技术。

本文详细介绍了这些线程模型分别是在哪些发行版上实现的。

LinuxThreads 设计细节

线程 将应用程序划分成一个或多个同时运行的任务。线程与传统的多任务进程之间的区别在于:线程共享的是单个进程的状态信息,并会直接共享内存和其他资源。同一个进程中线程之间的上下文切换通常要比进程之间的上下文切换速度更快。因此,多线程程序的优点就是它可以比多进程应用程序的执行速度更快。另外,使用线程我们可以实现并行处理。这些相对于基于进程的方法所具有的优点推动了 LinuxThreads 的实现。

LinuxThreads 最初的设计相信相关进程之间的上下文切换速度很快,因此每个内核线程足以处理很多相关的用户级线程。这就导致了一对一 线程模型的革命。

让我们来回顾一下 LinuxThreads 设计细节的一些基本理念:

  • LinuxThreads 非常出名的一个特性就是管理线程(manager thread)。管理线程可以满足以下要求:

    • 系统必须能够响应终止信号并杀死整个进程。
    • 以堆栈形式使用的内存回收必须在线程完成之后进行。因此,线程无法自行完成这个过程。
    • 终止线程必须进行等待,这样它们才不会进入僵尸状态。
    • 线程本地数据的回收需要对所有线程进行遍历;这必须由管理线程来进行。
    • 如果主线程需要调用 pthread_exit(),那么这个线程就无法结束。主线程要进入睡眠状态,而管理线程的工作就是在所有线程都被杀死之后来唤醒这个主线程。
  • 为了维护线程本地数据和内存,LinuxThreads 使用了进程地址空间的高位内存(就在堆栈地址之下)。
  • 原语的同步是使用信号 来实现的。例如,线程会一直阻塞,直到被信号唤醒为止。
  • 在克隆系统的最初设计之下,LinuxThreads 将每个线程都是作为一个具有惟一进程 ID 的进程实现的。
  • 终止信号可以杀死所有的线程。LinuxThreads 接收到终止信号之后,管理线程就会使用相同的信号杀死所有其他线程(进程)。
  • 根据 LinuxThreads 的设计,如果一个异步信号被发送了,那么管理线程就会将这个信号发送给一个线程。如果这个线程现在阻塞了这个信号,那么这个信号也就会被挂起。这是因为管理线程无法将这个信号发送给进程;相反,每个线程都是作为一个进程在执行。
  • 线程之间的调度是由内核调度器来处理的。

 

原创粉丝点击