• 【4 进程与线程】



     每个进程都对应于一个运行中的程序。应用程序再运行时仿佛独自占用整个CPU,而不需要考虑何时需要把CPU让给其他应用程序:进程管理、CPU资源分配等任务交给操作系统。

    1.进程

    1.1 进程的状态

    新生状态new该状态表示—个进程刚刚被创建出来,还未完成初始化,不能被调度执行。在经过初始化过程之后,进程迁移至预备状态。
    预备状态ready该状态表示进程可以被调度执行,但还未被调度器选择。由于CPU数量可能少于进程数量,在某一时刻只有部分进程能被调度到CPU上执行。此时,系统中其他的可被调度的进程都处于预备状态。在被调度器选择执行后’进程迁移至运行状态。
    运行状态running该状态表示进程正在CPU上运行。当一个进程执行一段时间后,调度器可以选择中断它的执行并重新将其放回调度队列,它就迁移至预备状态。当进程运行结束,它会迁移至终止状态。如果一个进程需要等待某些外部事件,它可以放弃CPU并迁移至阻塞状态。
    阻塞状态blocked该状态表示进程需要等待外部事件,暂时无法被调度。当进程等待的外部事件完成后,它会迁移至预备状态。
    终止状态terminated:该状态表示进程已经完成了执行,且不会再被调度。

    在这里插入图片描述

    1.2 进程的内存空间布局

    进程具有独立的虚拟内存空间
    在这里插入图片描述

    • 内核部分: 每个进程的虚拟地址空间里都映射了相同的内核内存部分。当进程在用户态运行时,内核内存对其不可见,只有当进程进入内核态时,才能访问内核内存。
    • 用户栈 :进程存放临时变量。扩展方向为自顶向下
    • 代码库:进程执行时,需要依赖的共享的代码库,这些代码库映射到用户栈下方的虚拟地址处,并标记为只读。
    • 用户堆:堆的扩展方向是自底向上的,堆顶在高地址上。
    • 数据与代码段:数据段主要保存全局变量的值,而代码段保存的是进程执行所需的代码

    1.3 进程控制块和上下文切换

    进程控制块
     每个进程都通过一个数据结构来保存它的相关状态,如进程标识符(PID)、进程状态、虚拟内存状态、打开的文件等。

    struct task_st{
    	volatile long state;
    	struct mm_struct *mm;
    	pid_t pid;
    	pid_t tgid;
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    进程上下文
     包括进程运行时的寄存器状态,其能够用于保存和恢复一个进程在处理器上运行的状态。当操作系统需要切换当前执行的进程时,就会使用上下文切换机制

    上下文切换

     该机制会将前一个进程的寄存器状态保存到PCB中,然后将下一个进程先前保存的状态写人寄存器,从而切换到该进程执行。
    在这里插入图片描述

    1.4 进程的缺点

     第一:创建进程的开销较大,需要完成创建独立的地址空间、载人数据和代码段、初始化堆等步骤。即使使用fork接口创建进程,也需要对父进程的状态进行大量拷贝。
     第二:由于进程拥有独立的虚拟地址空间,在进程间进行数据共享和同步比较麻烦,一般只能基于共享虚拟内存页(粒度较粗)或者基于进程间通信(开销较高)。

    2.线程

     操作系统的设计人员提出在迸程内部添加可独立执行的单元,它们共享进程的地址空间,但又各自保存运行时所需的状态(即上下文),这就是线程。

    2.1 多线程的地址空间布局

    在这里插入图片描述

    • 分离的内核栈与用户栈
      进程为每个线程都准备了不同的栈,供它们存放临时数据,在内核中,每个线程也有对应的内核栈。当线程切换到内核中执行时,它的栈指针就会切换到对应的内核栈。
    • 共享的其他区域
      进程除栈以外的其他区域由该进程的所有线程共享,包括堆、数据段、代码段等。当同一个进程的多个线程需要动态内存分配更多内存时,它们的内存分配操作都是在同一个堆上完成的。因此malloc的实现需要使用到同步原语

    2.2 用户态线程和内核态线程

     根据线程是由用户态应用还是由内核创建与管理’可将线程分为两类:用户态线程(user level thread)与内核态线程(kemel level thread)。

    • 用户态线程: 是应用自己创建的,内核不可见,因此也不直接受系统调度器管理。
    • 内核态线程: 由内核创建,受操作系统调度器直接管理。

    与内核态线程相比,用户态线程更加轻量级,创建开销更小,但功能也较为受限’,与内核态相关的操作(如系统调用)需要内核态线程协助才能完成。

    多线程模型:为了实现用户态线程和内核态线程的协作。操作系统会建立两类线程之间的关系。
    在这里插入图片描述

    • 多对一模型
      将多个用户态线程映射给单一的内核态线程。
    • 一对一模型
      为每个用户态线程映射单独的内核态线程。
    • 多对多模型
      将N个用户态线程映射到M个内核态线程。

    2.3 线程控制块与线程本地存储

    线程也有自己的线程控制块(Thread Control Block,TCB),用于保存与自身相关的信息。

    线程本地存储(Thread Local Storage,TLS):一个名字,多份拷贝(与线程数量相同)的全局变量。
    在这里插入图片描述

  • 相关阅读:
    软件开发全文档整理(原件获取)
    MySQL如何记忆
    爬虫过程和反爬
    快速排序知识总结
    树莓派 Qt中 QCameraInfo 无法使用
    &2_PyTorch神经网络基础
    Go语言~反射
    wordpress redirected you too many times.(多重重定向)
    Snipaste安装及使用方法
    c++ 智能指针 (std::weak_ptr)(三)
  • 原文地址:https://blog.csdn.net/yuqian_ke/article/details/126558512