用户级线程和内核级线程

来源:互联网 发布:李彦宏 知乎 编辑:程序博客网 时间:2024/05/16 17:20


一、关于用户空间以及内核空间的介绍                      



       Linux为内核代码和数据结构预留了几个页框。这些页永远不会被转出到磁盘上。从 0x0 到 0xc0000000(PAGE_OFFSET) 的线性地址可由用户代码 和 内核代码进行引用。从0xc0000000(PAGE_OFFSET)到 0xffffffff的线性地址只能由内核代码进行访问。内核代码及其数据结构都必须位于这 1 GB的地址空间中,但是对于此地址空间而言,更大的消费者是物理地址的虚拟映射。

       这意味着在 4 GB 的内存空间中,只有 3 GB 可以用于用户应用程序。一个进程只能运行在用户方式(usermode)或内核方式(kernelmode)下。用户程序运行在用户方式下,而系统调用运行在内核方式下。在这两种方式下所用的堆栈不一样:用户方式下用的是一般的堆栈,而内核方式下用的是固定大小的堆栈(一般为一个内存页的大小)


       每个进程都有自己的 3 G 用户空间,它们共享1GB的内核空间。当一个进程从用户空间进入内核空间时,它就不再有自己的进程空间了。



二、用户级线程(User-Level Thread)和内核线线程(Kernel-Level Thread)


1.线程实现的分类理解1


       线程的实现可以分为两类:用户级线程(User-Level Thread)和内核线线程(Kernel-Level Thread)。后者又称为内核支持的线程或轻量级进程。

      用户线程:指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。另外,用户线程是由应用进程利用线程库创建和管理,不依赖于操作系统核心。不需要用户态/核心态切换,速度快。操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。

      内核线程:  由操作系统内核创建和撤销。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。Windows  NT和2000/XP 支持内核线程  
 
 
 
 
 
2.线程实现的分类理解2(refer:http://blog.csdn.net/yanglovefeng/article/details/7887939)

     在有的系统中,特别是一些数据库管理系统如IBM的infomix系统,所实现的用户级线程(User Level Threads ,ULT);而另一些系统如(Mac os 的前身Macintosh 和OS/2操作系统)所实现的是内核支持线程 ( Kernel Supported threads, KST);还有一些是Solaris操作系统,则同时实现了这两中类型的线程。

  • ULT

       用户进程ULT仅存在于用户空间中。对于这种线程的创建、撤销、线程之间的同步和通信等功能,都无需系统调用来实现。对于同一进程的线程之间切换仍然是不需要内核支持的。所以呢,内核也完全不会知道用户级线程的存在。

但是有一点必须注意:设置了用户级线程的系统,其调度仍然是以进程为单位进行的。

       用户级线程仅存在于用户空间中,与内核无关;就内核而言,它只是管理常规的进程—单线程进程,而感知不到用户级线程的存在;每个线程控制块都设置在用户空间中,所有对线程的操作也在用户空间中由线程库中的函数完成,无需内核的帮助;设置了用户级线程的系统,其调度仍是以进程为单位进行的。


优点:

  1. 线程切换不需要转换到内核空间,节省了宝贵的内核空间;
  2. 调度算法可以是进程专用,由用户程序进行指定;
  3. 用户级线程实现和操作系统无关;

缺点:

  1. 系统调用阻塞,同一进程中一个线程阻塞和整个进程都阻塞了。
  2. 一个进程只能在一个cpu上获得执行。
  • KST

       对于一切的进程,无论是系统进程还是用户进程,进程的创建和撤销,以及I/O操作都是利用系统调用进入到内核,由内核处理完成,所以说在KST下,所有进程都是在操作系统内核的支持下运行的,是与内核紧密相关的。内核空间实现还为每个内核支持线程设置了一个线程控制快,内核是根据该控制快而感知某个线程是否存在,并加以控制。

      内核支持线程是在核心空间实现的;内核为每个线程在核心空间中设置了一个线程控制块,用来登记该线程的线程标识符、寄存器值、状态、优先级等信息;所有对线程的操作,如创建、撤消和切换等,都是通过系统功能调用由内核中的相应处理程序完成;设置了内核支持线程的系统,其调度是以线程为单位进行的。


优点:

  1.  在多处理器上,内核可以调用同一进程中的多个线程同时工作;
  2. 如果一个进程中的一个线程阻塞了,其他线程仍然可以得到运行;

缺点:对于用户线程的切换代价太大,在同一个线程中,从一个线程切换到另一个线程时,需要从用户态,进入到内核态并且由内核切换。因为线程调度和管理在内核实现。

  • 组合方式

        在很多的操作系统中ULT和KLT进行组合,整合了ULT和KLT的优点。其实我认为,现在操作提供肯定都是支持组合方式的,比如windows以及Unix中很多也是。




3.线程实现的分类理解3


(1)内核线程:

      内核线程实际上是直接由内核本身启动的进程。LINUX的内核线程是由kernel_thread()函数在内核态下创建的。(将创建时得到的函数永远执行下去,由一个循环组成,在需要的时候,内核线程将被唤醒执行)。当前系统中有一些工作是由内核线程完成的:

  • 周期性地将修改的内存页与页来源块设备同步
  • 如果内存页很少使用,则写入交换区
  • 管理延时动作
  • 实现文件系统的事务日志
  • 执行软中断(ksoftirqd)
内核线程可能用于两种场景:
  • 启动一个内核线程,然后一直处于等待状态直到被唤醒以完成某种服务
  • 启动一个周期性运行的内核线程,以检查特定资源的使用情况,并作出适当的反映
内核线程由内核自身生成,其特点在于:
  1. 它们在内核态执行,而不是用户态。
  2. 它们只可以访问虚拟地址空间的内核部分(高于TASK_SIZE的所有地址),但不能访问用户空间。


xxx备注:【系统调用】

       系统调用:系统调用指的是操作系统提供给应用程序调用的一组“特殊”接口。应用程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。
        从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口——系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序。
       系统服务之所以需要通过系统调用来提供给用户空间的根本原因是为了对系统进行“保护”,防止恶意用户破坏系统或者由于不小心而破坏了系统。系统调用的特殊之处在于规定了用户进程进入内核的具体位置。

        Linux系统只提供了最基本和最有用的系统调用,可以通过man 2 syscalls 命令查看,或到 ./include/linux/syscalls.h源文件中查看。




4.线程实现的分类理解4(refer:http://blog.csdn.net/kinado/article/details/8055321http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html   http://book.51cto.com/art/201006/206946.htm)


(1)用户级线程与内核级线程       

       根据在用户空间还是在核心实现多线程机制,线程又被分为用户级线程内核级线程

       用户级线程库有关线程的所有管理工作都有在用户级实现的线程库来支持。其用于用户级线程管理的例程包,支持线程的创建、终止,以及调度线程的执行并保存和恢复线程的上下文,这些操作都在用户空间运行,无需内核的支持,所以用户级线程的创建和管理等操作更快。对于那些内核本身不支持多线程的操作系统,通过用户级线程库可以使用户获得多线程编程的好处。

      由于内核不能感知到用户及线程的存在,内核仍然以进程为单位进行调度,当内核调度一个进程运行时,用户级线程库调度该进程的一个线程执行,如果时间片允许,进程的其他线程也可能被执行,该进程的多个线程共享该进程的运行时间片。如果一个线程需要进行i/o读写,该线程调用系统调用进入内核,在启动I/O设备后内核会把该进程值为阻塞态,并把CPU分配给其他进程。即使该进程的其他线程可以运行,内核也不会发现这一情况,在该进程的状态变为就绪之前内核不会调度该进程运行,因而属于该进程的线程都不可能运行,因而用户级线程的并行性会受到一定的限制。

       内核级线程的所有管理操作都是由操作系统内核完成的。内核保存线程的状态和上下文信息,当一个线程执行了引起阻塞的系统调用时,内核可以调度该进程的其他线程执行。在多处理器系统上,内核可以分派属于同一进程的多个线程在多个处理器上运行,提高进程执行的并行度。由于需要内核完成线程的创建、调度和管理,所以和用户级线程相比这些操作要慢得多,但是仍然比进程的创建和管理操作要快。大多数市场上的操作系统,如Windows

2000,Solaris 2,Linux等都支持内核级线程。

       有的操作系统提供了组合的线程模式,在Solaris 中,用户创建的多个用户级线程被映射到一些内核线程上,内核线程的数目可能少于用户级线程的数目,内核级线程的数目决定了该进程的并发度。


(2)多线程的映射模型

         对于实现了   用户级线程和内核级线程  的  操作系统,用户级线程和内核级线程之间可有不同的映射方式。

         也可一说是,线程有3种实现模型:用户级或应用程序级线程、内核级线程、用户级和内核级混合线程


A.多对一模型。(用户级或应用程序级线程



B.一对一模型。(内核级线程




C.多对多模型。(用户级和内核级混合线程





【注意对比】:

         //虽然多对一模型对创建用户级线程的数目并没有限制,但这些线程在同一时刻只能有一个被执行。

         //一对一模型可以获得高并发性,但因耗费资源而使线程数会受到限制。

         //多对多模型具有多对一和一对一两种模型的优势,用户可以创建所需要的用户级线程,通过分配适当数目的内核级线程获得并发执行的优势并节省系统资源。








0 0
原创粉丝点击