Linux性能优化实战:上下文切换

摘 学习笔记

1、多任务竞争CPU,cpu变换任务的时候进行CPU上下文切换(context switch)。

CPU执行任务有4种方式:进程、线程、或者硬件通过触发信号导致中断的调用。

 

 

2、当切换任务的时候,需要记录任务当前的状态和获取下一任务的信息和地址(指针),这就是上下文的内容。

因此,上下文是指某一时间点CPU寄存器(CPU register)和程序计数器(PC)的内容, 广义上还包括内存中进程的虚拟地址映射信息。

CPU寄存器:CPU用来存储指令

程序计数器:CPU用来存储下一条要执行的指令

 

3、上下文切换的过程:

(1)记录当前任务的上下文(即寄存器和计算器等所有的状态);

(2)找到新任务的上下文并加载;

(3)切换到新任务的程序计算器位置,恢复其任务。

 

4、根据任务的执行形式,相应的下上文切换,有进程上下文切换、线程上下文切换、以及中断上下文切换三类。

 

5、进程和线程的区别: 进程是资源分配和执行的基本单位;线程是任务调度和运行的基本单位。线程没有资源,进程给指针提供虚拟内存、栈、变量等共享资源,而线程可以共享进程的资源。

 

6、进程上下文切换:是指从一个进程切换到另一个进程。

(1)进程运行态为内核运行态和进程运行态。内核空间态资源包括内核的堆栈、寄存器等;用户空间态资源包括虚拟内存、栈、变量、正文、数据等

(2)系统调用(软中断)在内核态完成的,需要进行2次CPU上下文切换(用户空间-->内核空间-->用户空间),不涉及用户态资源,也不会切换进程。属于同进进程内的切换。

(3)进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了用户空间的资源,也包括内核空间资源。

(4)进程的上下文切换过程:

(a)接收到切换信号,挂起进程,记录当前进程的虚拟内存、栈等资源存储;

(b)将这个进程在 CPU 中的上下文状态存储于起来;

(c)然后在内存中检索下一个进程的上下文;

(d)并将其加载到 CPU的寄存器中恢复;

(e)还需要刷新进程的虚拟内存和用户栈;

(f)最后跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。

(5)、下列将会触发进程上下文切换的场景:

(a)、根据调度策略,将CPU时间划片为对应的时间片,当时间片耗尽,当前进程必须挂起。

(b)、资源不足的,在获取到足够资源之前进程挂起。

(c)、进程sleep挂起进程。

(d)、高优先级进程导致当前进度挂起

(e)、硬件中断,导致当前进程挂起

 

7、线程上下文切换: (1)、不通进程之间的线程上下文切换,其过程和进程上下文切换大致相同。 (2)、进程内部的线程进上下文切换。不需要切换进程的用户资源,只需要切换线程私有的数据和寄存器等。这会比进程上下文进程切换消耗的资源少,所以多线程相比多进程的优势。

 

8、中断上下文切换 快速响应硬件的事件,中断处理会打断进程的正常调度和执行。同一CPU内,硬件中断优先级高于进程。切换过程类似于系统调用的时候,不涉及到用户运行态资源。但大量的中断上下文切换同样可能引发性能问题。

 

9、案例分析

登录到服务器,现在系统负载怎么样 。

高的话有三种情况,首先是cpu使用率 ,其次是io使用率 ,之后就是两者都高 。

  • cpu 使用率高,可能确实是使用率高, 也的可能实际处理不高而是进程太多切换上下文频繁 , 也可能是进程内线程的上下文切换频繁。
  • io 使用率高 , 说明 io 请求比较大, 可能是 文件io 、 网络io 。

工具 :

系统负载 : uptime ( watch -d uptime)看三个阶段平均负载

系统整体情况 : mpstat (mpstat -p ALL 3) 查看 每个cpu当前的整体状况,可以重点看用户态、内核态、以及io等待三个参数

系统整体的平均上下文切换情况 : vmstat (vmstat 3) 可以重点看 r (进行或等待进行的进程)、b (不可中断进程/io进程) 、in (中断次数) 、cs(上下文切换次数)

查看详细的上下文切换情况 : pidstat (pidstat -w(进程切换指标)/-u(cpu使用指标)/-wt(线程上下文切换指标)) 注意看是自愿上下文切换、还是被动上下文切换

io使用情况 : iostat

 

 

模拟场景工具 :

  • stress : 模拟进程 、 io
  • sysbench : 模拟线程数

stree进程执行的计算是sqrt函数(库函数,所以usr cpu高),sysbench命令执行的是线程的各种同步操作(系统调用,所以sys cpu高),例如lock。通过stree --help 和 sysbench thread help 就能查看到。

stress压测在用户态的cpu占用高,是因为调用的函数在用户空间执行,而不是在内核空间执行。

 

10、其他参考

进程状态说明

  • R (task_running) :可执行状态
  • S (task_interruptible): 可中断的睡眠状态
  • D (task_uninterruptible): 不可中断的睡眠状态
  • T(task_stopped or task_traced):暂停状态或跟踪状态
  • Z (task_dead - exit_zombie):退出状态,进程成为僵尸进程
  • X (task_dead - exit_dead):退出状态,进程即将被销毁

 

posted @ 2022-03-30 21:35  CathyGao2018  阅读(510)  评论(0编辑  收藏  举报