Chapter 5: Threads 线程 综述 5.2 Multithreading Models 多线程模型 5.3 Threading Issues 线程问题 5.4 Pthreads POSIX线程 5.5 Solaris 2 Threads Solaris 2线程 5.6 Windows 2000 Threads Windows2000线程 5.7 Linux Threads Linux线程 5.8 Java Threads Java线程 5.1 Overview Operating System Concepts 5.1 Silberschatz, Galvin and Gagne 2002 5.1 Overview 概述 The concept of a process as embodying two characteristics :进程概 念的两个特征 Unit of Resource ownership - process is allocated a virtual address space to hold the process image 拥有资源的单位-进程被分派保存进程映像的续地址空间 Unit of Dispatching - process is an execution path through one or more programs 分派的单位-进程是由一个或多个程序的一次执行 execution may be interleaved with other processes 可能会与其他进程交替执行 These two characteristics are treated independently by the operating system 这两个特征有操作系统进行独立处理(改进) Dispatching is referred to as a thread or lightweight process 分派被称为一个线程或轻型进程 Resource of ownership is referred to as a processor task 分派资源被称为进程或任务 Operating System Concepts 5.2 Silberschatz, Galvin and Gagne 2002 线程的引入 进程:资源分配单位(存储器、文件)和CPU调度(分派)单位。又称 为"任务(task)" 线程:作为CPU调度单位,而进程只作为其他资源分配单位。 只拥有必不可少的资源,如:线程状态、寄存器上下文和栈 同样具有就绪、阻塞和执行三种基本状态 线程的优点:减小并发执行的时间和空间开销(线程的创建、退出和调 度),因此容许在系统中建立更多的线程来提高并发程度。 线程的创建时间比进程短; 线程的终止时间比进程短; 同进程内的线程切换时间比进程短; 由于同进程内线程间共享内存和文件资源,可直接进行不通过内核的 通信; Operating System Concepts 5.3 Silberschatz, Galvin and Gagne 2002 5.1.1 Motivation 动机 A thread (or lightweight process) is a basic unit of CPU utilization; it consists of: 线程(轻型进程)是CPU运用的一个基本单元,包括 a thread ID 一个线程标识符 program counter 程序计数器 register set 寄存器集 stack space 栈空间 (Has an execution state (running, ready, etc.);Saves thread context when not running;Has an execution stack;Has some per-thread static; storage for local variables;Has access to the memory and resources of its process,all threads of a process share this。) (有一个执行状态(运行、就绪等);不运行时保存线程的上下文;存储 局部变量;访问它的进程的内存和资源,进程的所有线程共享它) Operating System Concepts 5.4 Silberschatz, Galvin and Gagne 2002 Motivation (Cont.) A thread shares with threads belonging to the same process its: 一个线程与属于同一进程的线程共享: code section 代码段 data section 数据段 operating-system resources 操作系统资源 (Process Have a virtual address space which holds the process image Protected access to processors, other processes, files, and I/O resources) (进程有一个保存进程映像的虚地址空间,为保护访问处理器、其他进 程、文件和I/O资源) A traditional or heavyweight process is equal to a task with one thread 传统的或重型进程等价于只有一个线程的任务 Operating System Concepts 5.5 Silberschatz, Galvin and Gagne 2002 Motivation (Cont.) A single application may be required to perform several similar tasks. For example, a web server accepts client required for web pages. 一个单一应用程序可以被要求完成若干相似的任务。例如, 一个web服务 器接受客户要求网页。 In a multiple threaded task, while one server thread is blocked and waiting, a second thread in the same task can run. 在一个多线程任务中,当一个服务器线程被阻塞后,在同一 个任务中的第2个线程可运行 Operating System Concepts 5.6 Silberschatz, Galvin and Gagne 2002 Fig 5.1 Single and Multithreaded Processes 单个和多线程进程 Operating System Concepts 5.7 Silberschatz, Galvin and Gagne 2002 5.1.2 Benefits 益处 Responsiveness响应 Resource Sharing资源共享 Economy经济性 Utilization of MP Architectures MP体系结构的运用 Operating System Concepts 5.8 Silberschatz, Galvin and Gagne 2002 Benefits(Cont.) Takes less time to create ( or to terminate ) a new thread than a process 比进程花费更少时间创建 ( 或终止 ) 一个新线程 Less time to switch between two threads within the same process 在同一个进程内两个线程切换时间更少 Since threads within the same process share memory and files, they can communicate with each other without invoking the kernel 由于在同一个进程内线程共享存储器和文件,在没有调用内核下他 们能相互通信 Operating System Concepts 5.9 Silberschatz, Galvin and Gagne 2002 5.1.3 User and Kerel Threads 用户和内核线程 User Threads用户线程: 用户线程(user-level thread):不依赖于OS核心(内核不了解用户线 程的存在),应用进程利用线程库提供创建、同步、调度和管理线程 的函数来控制用户线程。如:数据库系统informix,图形处理Aldus PageMaker。调度由应用软件内部进行,通常采用非抢先式和更简 单的规则,也无需用户态/核心态切换,所以速度特别快。一个线程 发起系统调用而阻塞,则整个进程在等待。 用户线程的维护由应用进程完成; 内核不了解用户线程的存在; Examples例子 用户线程切换不需要内核特权; 用户线程调度算法可针对应用优化; - POSIX Pthreads - Mach C-threads - Solaris threads Operating System Concepts 5.10 Silberschatz, Galvin and Gagne 2002 Kernel Threads内核线程 内核线程(kernel-level thread):依赖于OS核心,由内核的内 部需求进行创建和撤销,用来执行一个指定的函数。一个线程发 起系统调用而阻塞,不会影响其他线程。时间片分配给线程,所 以多线程的进程获得更多CPU时间。 内核维护进程和线程的上下文信息; 线程切换由内核完成; 一个线程发起系统调用而阻塞,不会影响其他线程的运 行。 时间片分配给线程,所以多线程的进程获得更多CPU 时间。 Examples例子 - Windows 95/98/NT/2000 - Solaris - Tru64 UNIX - BeOS - Linux Operating System Concepts 5.11 Silberschatz, Galvin and Gagne 2002 5.1.4 进程和线程的比较 地址空间和其他资源(如打开文件):进程间相互独 立,同一进程的各线程间共享--某进程内的线程在 其他进程不可见 通信:进程间通信IPC,线程间可以直接读写进程数 据段(如全局变量)来进行通信--需要进程同步和 互斥手段的辅助,以保证数据的一致性 调度和切换:线程上下文切换比进程上下文切换要快 得多; Operating System Concepts 5.12 Silberschatz, Galvin and Gagne 2002 5.2 Multithreading Models 多线程模型 5.2.1 Many-to-One 多对一 5.2.2 One-to-One 一对一 5.2.3 Many-to-Many 多对多 Operating System Concepts 5.13 Silberschatz, Galvin and Gagne 2002 5.2.1 Many-to-One多对一 Many user-level threads mapped to single kernel thread. 多个用户级线程映像进单个内核线程 Thread management is done in user space, so it is efficient, but true concurrency is not gained because the kernel can schedule only one thread at a time. 在用户空间完成线程管理,所以它是有效率的,但是由于在某一时刻内核 只能调度一个线程,没有得到真正的并行操作。 Used on systems that do not support kernel threads. 用于不支持内核线程的系统中 Examples : Green threads -- a thread library available for Solaris 2 Operating System Concepts 5.14 Silberschatz, Galvin and Gagne 2002 Fig 5.2 Many-to-One Model多对一模型 Operating System Concepts 5.15 Silberschatz, Galvin and Gagne 2002 5.2.2 One-to-One一对一 Each user-level thread maps to kernel thread. 每个用户级线程映像进内核线程 It allows multiple threads to run in parallel on multiprocessors. Most implementations of this model restrict the number of threads supported by the system . 在多处理机上允许多个线程并行运行。这个模型的大 多数实现限制了系统支持线程的数目 Examples - Windows 95/98/NT/2000 - OS/2 Operating System Concepts 5.16 Silberschatz, Galvin and Gagne 2002 Fig 5.3 One-to-one Model一对一模型 Operating System Concepts 5.17 Silberschatz, Galvin and Gagne 2002 5.2.3 Many-to-Many Model多对多模型 Allows many user level threads to be mapped to many kernel threads. 允许许多用户级线程被映射到许多内核线程。 Allows the operating system to create a sufficient number of user threads and corresponding kernel threads can run in parallel on a multiprocessor. 允许操作系统创建足够数目用户线程和相应的能在一台多处理机上 并行运行内核线程。 Examples Solaris 2 Windows NT/2000 with the Thread Fiber package IRIX HP-UX Tru64 UNIX Operating System Concepts 5.18 Silberschatz, Galvin and Gagne 2002 Fig 5.4 Many-to-Many Model多对多模型 Operating System Concepts 5.19 Silberschatz, Galvin and Gagne 2002 5.3 Threading Issues 线程问题 5.3.1 Semantics of fork() and exec() system calls. fork和exec系统调用语义 5.3.2 Thread cancellation. 撤销线程 5.3.3 Signal handling信号处理 5.3.4 Thread pools线程池 5.3.5 Thread specific data线程专用数据 Operating System Concepts 5.20 Silberschatz, Galvin and Gagne 2002 5.3.1 fork() and exec() system calls fork和exec系统调用 In a multithreaded program, semantics of the fork and exec system calls change. 在多线程的程序环境中,fork和 exec 系统调用的语义变化 Question: 在调用fork时,新的进程究竟是copy 父进程的所有thread 还是仅仅创建一个单thread的进程? Some UNIX systems have chosen to have two versions of fork , one that duplicates all threads and another that duplicates only the thread that invoked that fork system call. 一些 UNIX 系统选择了两种fork : 复制所有的线程 – 适用于fork后不调用exec的应用场合 仅仅复制调用fork系统调用的线程。 – 适用于fork后即exec执行其它应用的场合 Operating System Concepts 5.21 Silberschatz, Galvin and Gagne 2002 5.3.2 Cancellation 取消 Thread Cancellation is the task of terminating a thread before it has completed. 在它完成了以前,线程取消是终止一个线程的任务 例如,多个线程同时搜索一个数据, 或则按“Stop”键中止一个 网页 A thread that cancelled is often referred to as the target thread. Cancellation of a target thread may occur in two different scenarios: 取消一个线程经常作为目标线程被提交。一个目标线程的取消可 以在 2 种不同情形发生: Asynchronous cancellation :异步的取消 (立即) May not free a resource Deferred cancellation:推迟的取消: (定期检查) Can cancel a thread at a proper point safely – cancellation points Operating System Concepts 5.22 Silberschatz, Galvin and Gagne 2002 5.3.3 Signal Handling信号处理 信号:提示进程发生了什么特殊事件 (in Unix) 同步接收 异步接收 信号特征: 由一个特殊事件发生所引起 信号被发送给了一个进程 信号必须处理 例子: 同步:内存访问出错、除零 异步:Ctril-C、定时器时间到 信号处理: 缺省处理(in Kernel) 用户定义(优先级高于缺省处理) Operating System Concepts 5.23 Silberschatz, Galvin and Gagne 2002 Signal Handling信号处理(Cont.) 多线程信号处理方法:比单线程复杂 将信号发给使用该信号的线程 将信号发给进程中的每个线程 将信号发给进程中的所有线程 在进程中设定一个特殊线程,接收所有信号 Solaris 2 选用方案4, Windows 2000 通过异步过程调用(APC)选用方案4 Operating System Concepts 5.24 Silberschatz, Galvin and Gagne 2002 5.3.4Thread Pools线程池 多线程服务进程存在的问题 线程创建需要时间 无限制地创建线程会耗尽系统资源 解决方案 建立线程池(Thread pool)(在进程创建时) 好处 提供快速服务响应 限制线程数量 Operating System Concepts 5.25 Silberschatz, Galvin and Gagne 2002 5.3.5 Thread-specific Data指定线程数据 进程中的所有线程共享进程的数据和代码 每个线程在需要自己特定的数据时,分配 Thread- specific Data Operating System Concepts 5.26 Silberschatz, Galvin and Gagne 2002 5.4 Pthreads POSIX线程 a POSIX standard (IEEE 1003.1c) API for thread creation and synchronization. 为线程创建和同步的一个 POSIX 标准 ( IEEE 1003.1c ) API 。 API specifies behavior of the thread library, implementation is up to development of the library. API 指定线程库的行为, 实现直到库的开发。 Common in UNIX operating systems. 共同在 UNIX 操作系统 Operating System Concepts 5.27 Silberschatz, Galvin and Gagne 2002 附:POSIX介绍 POSIX 表示可移植操作系统接口(Portable Operating System Interface ,缩写为 POSIX 是为了读音更像 UNIX) 。电气和电子工程师协会(Institute of Electrical and Electronics Engineers,IEEE)最初开发 POSIX 标准,是 为了提高 UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于 UNIX。许多其它的操作系统,例如 DEC OpenVMS 和 Microsoft Windows NT,都支持 POSIX 标准 ,尤其是 IEEE Std. 1003.1-1990(1995 年修订)或 POSIX.1,POSIX.1 提供了源代码级别的 C 语言应用编程接 口(API)给操作系统的服务程序,例如读写文件。POSIX.1 已经被国际标准化组织(International Standards Organization,ISO)所接受,被命名为 ISO/IEC 99451:1990 标准。 POSIX 现在已经发展成为一个非常庞大的标准族,某些部分 正处在开发过程中。 要想得到关于 IEEE 标准的最新信息,可以访问 IEEE 标准的 主页,网址是 http://standard.ieee.org/。 有关 POSIX 标准的概述信息,请访问 Web 站点 http://standards.ieee.org/reading/ieee/stad_public/descri ption/posix/。 Operating System Concepts 5.28 Silberschatz, Galvin and Gagne 2002 <Look at the example at page 140 in the book> Operating System Concepts 5.29 Silberschatz, Galvin and Gagne 2002 5.5 Solaris 2 Threads Solaris 2 线程 Operating System Concepts 5.30 Silberschatz, Galvin and Gagne 2002 Three level User level thread Lightweight process (LWP) Kernel thread Each process contains at least one LWP Each LWP has a kernel-level thread Some kernel-level threads have no associated LWP Kernel-level threads are the only object of CPU scheduler Many-to-many model Operating System Concepts 5.31 Silberschatz, Galvin and Gagne 2002 用户级线程(User-level thread)在使用系统调用时(如文件 读写),需要“捆绑(bound)”在一个LWP上。 永久捆绑:一个LWP固定被一个用户级线程占用,该 LWP移到LWP池之外 (bound user-level thread) 临时捆绑:从LWP池中临时分配一个未被占用的LWP (unbound user-level thread, default) 在使用系统调用时,如果所有LWP已被其他用户级线程所占 用(捆绑),则该线程阻塞直到有可用的LWP--例如6个 用户级线程,而LWP池中有4个LWP 如果LWP执行系统调用时阻塞(如read()调用),则当前捆 绑在LWP上的用户级线程也阻塞。 Operating System Concepts 5.32 Silberschatz, Galvin and Gagne 2002 Solaris 2 Process data structure Operating System Concepts 5.33 Silberschatz, Galvin and Gagne 2002 线程举例 1. SUN Solaris 2.3 Solaris支持内核线程(Kernel threads)、轻权进程 (Lightweight Processes)和用户线程(User Level Threads)。一个进程可有大量用户线程;大量用户线 程复用少量的轻权进程,不同的轻权进程分别对应 不同的内核线程。 Operating System Concepts 5.34 Silberschatz, Galvin and Gagne 2002 Stop 用户级线程 Runnable Wakeup Continue Stop Stopped Sleeping Dispatch Stop Sleep Active Timeslice or Preempt Running Wakeup Dispatch Stop Stopped Runnable Blocking System Call Continue Wakeup 轻权进程 Operating System Concepts Active Solaris Preempt 用 户 线 程 和 轻 权 进 程 Stop 5.35 Silberschatz, Galvin and Gagne 2002 Process 1 Process 1 Permanently Bound Threads UT UT LWP UT UT Unbound Threads UT LWP LWP LWP KT KT KT Pool of LWPs for Unbound Threads Kernal KT KT CPU 1 KT CPU 1 用户线程、轻权进程和核心线程的关系 Operating System Concepts 5.36 Silberschatz, Galvin and Gagne 2002 有关的C库函数 /* 创建用户级线程 */ int thr_create(void *stack_base, size_t stack_size, void *(*start_routine)(void *), void *arg, long flags, thread_t *new_thread_id); 其中flags包括:THR_BOUND(永久捆绑), THR_NEW_LWP (创建新LWP放入LWP池),若两者同时指定则创建两个新LWP, 一个永久捆绑而另一个放入LWP池 有关的系统调用 /* 在当前进程中创建LWP */ int _lwp_create(ucontext_t *contextp, unsigned long flags, lwpid_t *new_lwp_id); /* 构造LWP上下文 */ void _lwp_makecontext(ucontext_t *ucp, void (*start_routine)( void *), void *arg, void *private, caddr_t stack_base, size_t stack_size); /* 注意:没有进行"捆绑"操作的系统调用 */ Operating System Concepts 5.37 Silberschatz, Galvin and Gagne 2002 5.6 Windows 2000 Threads Implements the one-to-one mapping. 实现一对一映射; 但也支持一个“fiber”库,提供many-to-many 模型 Each thread contains 每个线程包含: - a thread id 一个线程 id - register set 寄存器集合 - separate user and kernel stacks 独立的用户和内核 栈 - private data storage area 私有数据存储区域 Operating System Concepts 5.38 Silberschatz, Galvin and Gagne 2002 Windows NT 就绪状态(Ready):进程已获得除处理机外的所需资源,等 待执行。 备用状态(Standby):特定处理器的执行对象,系统中每个 处理器上只能有一个处于备用状态的线程。 运行状态(Running):完成描述表切换,线程进入运行状态 ,直到内核抢先、时间片用完、线程终止或进行等待状态。 等待状态(Waiting):线程等待对象句柄,以同步它的执行。 等待结束时,根据优先级进入运行、就绪状态。 转换状态(Transition):线程在准备执行而其内核堆栈处于 外存时,线程进入转换状态;当其内核堆栈调回内存,线程 进入就绪状态。 终止状态(Terminated):线程执行完就进入终止状态;如执 行体有一指向线程对象的指针,可将线程对象重新初始化, 并再次使用。 初始化状态(Initialized):线程创建过程中的线程状态; Operating System Concepts Silberschatz, Galvin and Gagne 2002 5.39 创建和初始化 线程对象 Windows NT的线程状态 初始化 重新 初始 化 抢 执行 先 就绪 抢先或 时间片结束 的 入 栈 换 堆 核 内 等待完成 选 择 表 述 换 切 转换 描 放入 就绪队列 备用 完 换出的 内核堆栈 等待 Operating System Concepts 成 等 待 待 句 运行 执行完成 柄 象 对 等 5.40 Silberschatz, Galvin and Gagne 2002 终止 Windows NT的线程状态 Runnable Standby Pick to Run Preempted Ready Unblock/Resume Resource Available Resource Available Switch Transition Waiting Running Block/ Suspend Terminate Terminated Unblock Resource Not Available Not Runnable Operating System Concepts 5.41 Silberschatz, Galvin and Gagne 2002 NT线程的有关API CreateThread()函数在调用进程的地址空间上创建一个线 程,以执行指定的函数;返回值为所创建线程的句柄。 ExitThread()函数用于结束本线程。 SuspendThread()函数用于挂起指定的线程。 ResumeThread()函数递减指定线程的挂起计数,挂起计 数为0时,线程恢复执行。 Operating System Concepts 5.42 Silberschatz, Galvin and Gagne 2002 5.7 Linux Threads Linux refers to them as tasks rather than threads or processes. Linux 被他们作为任务而非线程。 Thread creation is done through clone() system call. 线程创建是通过clone () 系统调用完成的。 fork() – duplicate/copy a process clone() – create a thread and share the address space of calling process Clone() allows a child task to share the address space of the parent task (process) clone ()允许一项子任务共享父任务( 进程)的地址空间 Operating System Concepts 5.43 Silberschatz, Galvin and Gagne 2002 Linux线程 已经开发出了LINUX下的一种线程库,该线程库实现了一个叫“一 对 一 ”模型(One-to-One), 它可以利用多处理器。 在许多实现了多线程的操作系统中(如:Solaris,Digital Unix 等), 线程和进程通过两种数据结构来抽象表示: 进程表项和线 程表项,一个进程表项可以指向若干个线程表项, 调度器在进程 的时间片内再调度线程。 但是在Linux中没有做这种区分, 而是 统一使用task_struct来管理所有进程/线程,只是线程与线程之间 的资源是共享的,这些资源可是是前面提到过的:虚存、文件系统 、文件I/O以及信号处理函数甚至PID中的几种。 Operating System Concepts 5.44 Silberschatz, Galvin and Gagne 2002 Linux线程 也就是说Linux中,每个线程都有一个task_struct,所以线 程和进程可以使用同一调度器调度。其实Linux核心中,轻 量级进程和进程没有质上的差别,因为Linux中进程的概念 已经被抽象成了计算状态加资源的集合,这些资源在进程间 可以共享。如果一个task独占所有的资源,则是一个HWP, 如果一个task和其它task共享部分资源,则是LWP。 clone系统调用就是一个创建轻量级进程的系统调用: int clone(int (*fn)(void * arg), void *stack, int flags, void * arg); clone的用法和pthread_create有些相似,两者的最根本的 差别在于clone是创建一个LWP,对核心是可见的,由核心 调度,而pthread_create通常只是创建一个用户线程,对核 心是不可见的,由线程库调度。 Operating System Concepts 5.45 Silberschatz, Galvin and Gagne 2002 5.8 Java Threads Java线程 Java的线程是通过Java的软件包Java.lang中定义的类Thread来 实现的。 Java threads may be created by: Java线程可如下创建: Extending Thread class 继承线程类 Implementing the Runnable interface 实现Runnable接口对象 Java threads are managed by the JVM. Java 线程被 JVM 管理 Operating System Concepts 5.46 Silberschatz, Galvin and Gagne 2002 Java Thread States Java线程状态 Operating System Concepts 5.47 Silberschatz, Galvin and Gagne 2002