posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

 

1、线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属于1:1模型。html


(一)、N:1用户线程模型linux

“线程实现”创建在“进程控制”机制之上,由用户空间的程序库来管理。OS内核彻底不知道线程信息。这些线程称为用户空间线程。这些线程都工做在“进编程

程竞争范围”(process contention scope):各个线程在同一进程竞争“被调度的CPU时间”(但不直接和其余进程中的线程竞争)。
服务器



在N:1线程模型中,内核不干涉线程的任何生命活动,也不干涉同一进程中的线程环境切换。
网络

在N:1线程模型中,一个进程中的多个线程只能调度到一个CPU,这种约束限制了可用的并行总量。
多线程

第二个缺点是若是某个线程执行了一个“阻塞式”操做(如read),那么,进程中的全部线程都会阻塞,直至那个操做结束。为此,一些线程的实现是为函数

这些阻塞式函数提供包装器,用非阻塞版本替换这些系统调用,以消除这种限制。
性能


(二)、1:1核心线程模型 pthread线程库--NPTL(Native POSIX Threading Library)学习

在1:1核心线程模型中,应用程序建立的每个线程(也有书称为LWP)都由一个核心线程直接管理。OS内核将每个核心线程都调到系统CPU上,网站

所以,全部线程都工做在“系统竞争范围”(system contention scope):线程直接和“系统范围”内的其余线程竞争。

这种线程的建立与调度由内核完成,由于这种线程的系统开销比较大(但通常来讲,比进程开销小)




(三)、N:M混合线程模型  NGPT(Next Generation POSIX Threads)

N:M混合线程模型提供了两级控制,将用户线程映射为系统的可调度体以实现并行,这个可调度体称为轻量级进程(LWP:light weight process),LWP
再一一映射到核心线程。以下图所示。OS内核将每个核心线程都调到系统CPU上,所以,全部线程都工做在“系统竞争范围”。


听说一些类UNIX系统(如Solaris)已经实现了比较成熟的M:N线程模型, 其性能比起linux的线程仍是有着必定的优点,但不能利用SMP结构。

按照2003年3月NGPT官方网站上的通知,NGPT考虑到NPTL日益普遍地为人所接受,为避免不一样的线程库版本引发的混乱,从此将再也不进行进一步开发,而今进行支持性的维护工做。也就是说,NGPT已经放弃与NPTL竞争下一代Linux POSIX线程库标准。


2、posix 线程概述

咱们知道,进程在各自独立的地址空间中运行,进程之间共享数据须要用进程间通讯机制,有些状况须要在一个进程中同时执行多个控制流程,这时候

线程就派上了用场,好比实现一个图形界面的下载软件,一方面须要和用户交互,等待和处理用户的鼠标键盘事件,另外一方面又须要同时下载多个文

件,等待和处理从多个网络主机发来的数据,这些任务都须要一个“等待-处理”的循环,能够用多线程实现,一个线程专门负责与用户交互,另外几个线

程每一个线程负责和一个网络主机通讯。


之前咱们讲过,main函数和信号处理函数是同一个进程地址空间中的多个控制流程,多线程也是如此,可是比信号处理函数更加灵活,信号处理函数的

控制流程只是在信号递达时产生,在处理完信号以后就结束,而多线程的控制流程能够长期并存,操做系统会在各线程之间调度和切换,就像在多个进

程之间调度和切换同样。因为同一进程的多个线程共享同一地址空间,所以Text Segment、Data Segment都是共享的,若是定义一个函数,在各线程

中均可以调用,若是定义一个全局变量,在各线程中均可以访问到,除此以外,各线程还共享如下进程资源和环境:


文件描述符表

每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)

当前工做目录

用户id和组id


但有些资源是每一个线程各有一份的:

线程id

上下文,包括各类寄存器的值、程序计数器和栈指针

栈空间

errno变量

信号屏蔽字

调度优先级


咱们将要学习的线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。在Linux上线程函数位于libpthread共享库中,所以在编译时要加上-lpthread选项。


注:linux 2.6 之后的线程就是由用户态的pthread库实现的.使用pthread之后在用户看来每个task_struct就对应一个线程而一组线程以及它们所共同引用的一组资源就是一个进程.在linux 2.6中, 内核有了线程组的概念, task_struct结构中增长了一个tgid(thread group id)字段. getpid(获取进程ID)系统调用返回的也是tast_struct中的tgid, 而tast_struct中的pid则由gettid系统调用来返回。

当线程中止/继续, 或者是收到一个致命信号时, 内核会将处理动做施加到整个线程组中。
比 如程序a.out运行时,建立了一个线程。假设主线程的pid是1000一、子线程是10002(它们的tgid都是10001)。这时若是你kill 10002,是能够把10001和10002这两个线程一块儿杀死的,尽管执行ps命令的时候根本看不到10002这个进程。若是你不知道linux线程背 后的故事,确定会以为遇到灵异事件了。
 
 

参考:

《linux c 编程一站式学习》

《UNP》

《APUE》

http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/index.html

http://hi.baidu.com/_kouu/item/282b80a933ccc3a829ce9dd9

http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
相关文章
相关标签/搜索