操做系统中的进程和线程

操做系统中的进程和线程

1.进程和线程的学习中容易混乱的地方

之因此以为进程和线程难以理解,大概有这么几个缘由:html

  • 进程,线程的概念是不断发展的,不一样时期的书籍会有不一样的阐述,如一开始内核不支持线程到后来内核开始支持线程
  • 经典的书籍如《现代操做系统》可能是从原理的角度去说,高屋建瓴,可是难以有切身感觉
  • 操做系统对进程和线程的实现也是不一样的,架构者对进程和线程的理念有所不一样,Linux和Windows内核对线程的实现不一样。

2.进程模型的演变

最初,进程的内涵分为两个方面:linux

  • 调度,执行的基本单位

最初操做系统不支持线程的概念,内核中维护着进程的各类信息,如运行状态,优先级,寄存器等,也就是说OS能够根据这些信息调度和执行进程。算法

  • 资源全部权

包括程序,数据,文件,socket 等资源。编程

将两个独立的功能分离,出现了线程的概念:windows

  • 做为执行与调度的基本单位——thread
  • 资源全部权: process

这也就是常常说的:"process是资源容器,thread是执行单位"。这样带来的巨大好处是:多线程

  • 线程的建立成本远远低于进程,由于线程中包含的数据量少于进程,线程只须要执行相关的数据便可,如,pc,寄存器,栈,执行状态
  • 进程中的线程共享地址空间,进程间的通讯的代价远大于线程间的通讯。

3.三种线程模型

<1>用户级线程

彼时操做系统没有提供对线程的支持,只是在应用层面实现了线程,操做系统并不知道,,内核维护着进程表,仍然以进程为单位进行系统调用。进程自身维护着线程表,维护线程的状态。架构

  • 优点socket

    • 不用切换到内核态,性能极佳,
    • 进程本身能够有定制的调度算法
    • 在不支持多线程的操做系统实现多线程程序,如DOS
  • 劣势性能

    • 对线程的操做,如建立,调度,都是应用程序实现,致使编程困难
    • 由于操做系统只知进程不知线程,也就只能调度进程而没法调度线程,全部只要一个线程所在的进程发生了阻塞,那操做系统即阻塞该进程,那么该进程的其余线程也就没法被调度,至关于阻塞了。目前使用用户线程的程序愈来愈少了。
<2>内核级线程

后来,操做系统内核开始支持线程,就出现了内核级线程模型。这种线程模型中,内核维护着进程表和线程表,也就是说,内核能够对线程直接进行调度,学习

  • 优点

    • 内核的调度粒度小至线程,就不会出现用户级进程那种阻塞了进程,进程中全部线程都被迫“阻塞”的状况,内核线程被阻塞,不会致使进程被阻塞,进程中的其余线程依然能够继续执行
  • 劣势

    • 开销挺大,从用户态到内核态的切换有必定的开销
    • 支持的线程总量较小,由于内核线程占据内核的空间,而内核所持有的空间是有限的

通常而言,程序不会直接使用内核线程,而是使用内核线程的高级接口——轻量级进程。轻量级进程和内核线程是1:1的关系。

<3>混合线程

有些操做系统支持,如Solaris平台。比较主流的windows和linux不支持。

4.归纳进程和线程的本质

  • 进程:当用户启动一个应用,系统将程序的源码和数据从磁盘加载到内存中,而且开始执行他的源码。一个进程即一个正被执行中的程序。与程序不一样, 一个进程是一个活跃的实体 ,而且包含了程序做为单个实例在执行期间状态的快照。
  • 线程:一个线程的本质是一组寄存器的状态,是操做系统对寄存器状态的抽象

5.特殊的Linux线程实现

Linux对进程与线程的实现比较特殊,对于Linux内核来讲,并不存在线程的说法,可是Linux中进程与进程能够是有区别的。对于linux内核来讲,只有进程,建立进使用系统调用clone,可经过设置该方法的参数设置进程是否共享某些数据,好比:

  • fork():建立子进程,经过调用0共享的clone,建立的进程是彻底复制父进程的数据,两者不共享不可见。
  • pthread_create:经过调用最多共享的clone实现,就至关于通常意义上的线程了。

能够看到Linus对进程与线程的观点:
Linus的观点,Re: proc fs and shared pids

相关文章
相关标签/搜索