当前位置: 首页 > 科技观察

操作系统线程详解

时间:2023-03-18 12:37:56 科技观察

前言这将是一个系列,一个关于进程、线程和协程的系列。主要用于:回顾和复习自己以前学过的东西希望这段经历能对正在学习编程的你有所帮助。前几章会讲一些相关的计算机理论知识,可能比较枯燥。但这是基础,是理解后面程序的必要概念。有疑问可以加微信讨论,我们共同进步。线程的定义线程(thread)是操作系统可以执行操作的最小单元。同一个进程中的多个线程会共享进程中的所有系统资源,如虚拟地址空间、文件描述符、信号处理等。线程是如何实现的根据线程管理发生的位置,我们将线程分为以下三类:内核支持线程内核线程驻留在内核空间中,是内核对象。对于内核线程,每个用户线程都映射或绑定到一个内核线程。用户线程在其生命周期内绑定到该内核线程。一旦用户线程终止,两个线程都将离开系统。这称为“一对一”线程映射。优点是调度灵活,缺点是内核线程在用户态和内核态之间进行上下文切换,资源开销大。用户级线程内核对线程包一无所知。从内核的角度来看,它是按正常方式管理的,即单线程进程(有运行时系统)。也就是说,如果进程中的一个线程被阻塞了(比如IO资源导致的),其他线程将不会被执行。Combinedthreading(posix线程调度模型,也称为posix规范)posix线程调度是一种混合模型,在标准的具体实现中,它足够灵活,可以同时支持用户级和内核级线程。模型中包含两个级别的调度——线程和内核实体级别。线程级与用户级线程类似,内核实体由内核调度。由线程库决定它需要多少内核实体,以及它们是如何映射的。上下文切换什么是上下文切换?在当今的计算机系统中,CPU上运行的线程数远远超过了CPU中的内核数,但用户感觉这些程序是同时运行的。这是由于分时系统的设计理念——人们把CPU时间分成几个小段。每个线程只能在有限数量的小段上执行。当时间到了,CPU会挂起线程,使其进入就绪状态,CPU会转而去执行下一个线程,但是这个切换过程太快了,用户察觉不到。在这个过程中,CPU需要保存当前线程的工作环境(移出工作区),然后将要执行的线程的数据加载到工作区中。这个过程称为上下文切换。展开,上面就是典型的被动上下文切换,也叫非自愿上下文切换。此外,还有由于当前进程资源不足导致的自愿上下文切换,以及中断信号引起的中断上下文切换。上下文切换的成本我在控制台上检查系统中上下文切换的次数。(满载)$sar-w110Linux4.15.0-153-generic(ubuntu-bionic)08/09/21_x86_64_(2CPU)15:26:02proc/scswch/s15:26:030.0065892.0015:26:040.00248868.0015:26:050.00368564.0015:26:060.0039148.0015:26:070.00349058.0015:26:080.00353089.0015:26:26:090.00381352.001550#proc/s每秒创建的任务总数。#cswch/s每秒上下文切换的总数。这是一个2核CPU。据统计,目前主流CPU每次上下文切换需要2~5微秒。我们取3微秒的中值。我们算一下单核CPU每秒上下文切换的时间:3*304202/2/1000=0.456s。可见,频繁的上下文切换对性能影响巨大。由于同一个进程中的多个线程共享进程资源,从这个角度我们将上下文切换分为两类:进程切换:不同进程的线程之间的切换。线程切换:统一进程中不同线程之间的切换。上图中绿色部分代表需要切换的上下文。我们可以看到,线程切换的开销要比进程切换小很多。今天的线程理论就到这里了。接下来,我们将以Python为主要编程语言,带大家进行多线程实践和性能分析。与枯燥的理论知识相比,它会变得更有趣。