近日见闻
Electron v28.2.0 发布,一款跨平台的桌面应用开发工具 --electron社区
Linus 发飙,批评谷歌内核贡献者的代码是垃圾,“你复制了一段不理解为何执行此操作的函数,这就是垃圾代码!”
过年前的时间过的很快,想起来一句话,幸福在于等幸福到来的那段日子。
摘抄:
为最坏的情况做好准备,
为最好的情况敞开心扉。
——斯鲁日特尔《莫斯科小猫》
小记
这两天和同事讨论起linux进程调度的问题,比如进程统计、那些进程优先运行、怎么调度等,对此在这里和大家一同复习一下。先来说说怎么查看进程。在使用Linux操作系统的过程中,掌握如何查看和管理进程是系统管理的重要技能之一。进程管理不仅有助于监控系统资源的使用情况,还能帮助排查问题和优化系统性能。
查看进程的常见命令
ps (Process Status)
ps命令是最基本同时也是最常用的进程查看命令,它能够列出系统中当前运行的所有进程信息。
基本用法:
ps aux:显示所有进程信息
ps -ef:以全格式列出所有进程
ps -u [username]:列出指定用户的所有进程
如图所示
top
top命令提供了一个实时更新的进程状态动态视图。默认情况下,它以CPU使用率降序排列进程。
基本用法:
执行top即可进入top界面,按q退出。
htop
htop是top命令的一个增强版本,提供了更友好的界面和更多的信息展示。
基本用法:
安装htop(如果系统未预装):sudo apt-get install htop(Debian/Ubuntu)或者sudo yum install htop(CentOS/RedHat)
执行htop即可进入htop界面,按F10退出。
pstree
pstree命令展示的是进程之间的层级关系,以树状图的方式显示。
基本用法:
pstree:展示系统中的所有进程及其关系
pstree [username]:展示指定用户的进程树
进程信息解读
无论是ps、top还是htop,它们都会显示以下几个重要的进程信息:
PID:进程ID
USER:运行该进程的用户
PR:进程优先级
NI:进程的“nice”值,即优先级数值
VIRT:虚拟内存使用量
RES:常驻内存量
SHR:共享内存量
S:进程状态(S睡眠,R运行,T停止,Z僵尸)
%CPU:占用的CPU百分比
%MEM:占用的内存百分比
TIME+:总的CPU时间
COMMAND:启动命令/命令行
掌握了如何查看进程,我们再来讨论一下进程是如何调度的。在Linux操作系统中,进程调度是操作系统最为核心的功能之一。它负责合理分配处理器资源,决定哪个进程何时运行,以及运行多长时间。本文将深入探讨Linux中的进程调度机制。
什么是进程调度?
进程调度是指操作系统按照一定的策略,动态地将处理器分配给等待运行的进程。调度的目的是为了优化系统性能,保证各类进程合理、公平地获取CPU使用权。
Linux进程调度的类型
Linux系统中的进程调度主要有两种类型:
完全公平调度器(Completely Fair Scheduler,CFS):从Linux内核版本2.6.23开始,CFS成为默认的进程调度器。CFS的设计目标是最大化利用CPU,并在进程间提供公平的CPU时间分配。
实时调度器(Real-Time Scheduler):用于实时任务,确保任务在规定时间内完成。包含两种策略:
FIFO(先进先出)
RR(轮转)
Linux进程调度策略
完全公平调度器(CFS)
CFS的核心思想是所有进程都应该获得相等的CPU时间。CFS将CPU资源分成时间片,用红黑树来管理所有可运行的进程,保证每个进程都能获得公平的时间片。
红黑树
红黑树是一种自平衡的二叉查找树,一种特殊的数据结构。在这棵树中,每个节点都有颜色属性,要么是红色,要么是黑色。因为它涉及多个操作的细节,比如插入、删除、旋转(左旋和右旋)、重新着色等,每个操作都必须维护红黑树的性质。感兴趣的可以自行查阅,这里贴一个简单的算法示例。这个实现并不完整,主要用于展示红黑树操作的基本概念。
class Node:
def __init__(self, data, color="red"):
self.data = data
self.color = color
self.parent = None
self.left = None
self.right = None
class RedBlackTree:
def __init__(self):
self.TNULL = Node(0, color="black") # 创建一个空节点作为叶子节点
self.root = self.TNULL
def left_rotate(self, x):
# 左旋示意图:
# x y
# / \ / \
# a y => x c
# / \ / \
# b c a b
y = x.right
x.right = y.left
if y.left != self.TNULL:
y.left.parent = x
y.parent = x.parent
if x.parent == None: # x是根节点
self.root = y
elif x == x.parent.left: # x是其父节点的左子节点
x.parent.left = y
else: # x是其父节点的右子节点
x.parent.right = y
y.left = x
x.parent = y
def right_rotate(self, y):
# 右旋示意图:
# y x
# / \ / \
# x c => a y
# / \ / \
# a b b c
x = y.left
y.left = x.right
if x.right != self.TNULL:
x.right.parent = y
x.parent = y.parent
if y.parent == None: # y是根节点
self.root = x
elif y == y.parent.right: # y是其父节点的右子节点
y.parent.right = x
else: # y是其父节点的左子节点
y.parent.left = x
x.right = y
y.parent = x
def insert(self, key):
# 插入操作
node = Node(key)
node.parent = None
node.data = key
node.left = self.TNULL
node.right = self.TNULL
node.color = "red" # 新节点必须是红色
y = None
x = self.root
while x != self.TNULL:
y = x
if node.data < x.data:
x = x.left
else:
x = x.right
node.parent = y
if y == None:
self.root = node
elif node.data < y.data:
y.left = node
else:
y.right = node
if node.parent == None:
node.color = "black"
return
if node.parent.parent == None:
return
self.fix_insert(node) # 调用插入修复函数来维护红黑树的性质
def fix_insert(self, k):
# 插入节点后修复红黑树性质的函数
while k.parent.color == "red":
if k.parent == k.parent.parent.right:
u = k.parent.parent.left # 叔叔节点
if u.color == "red":
u.color = "black"
k.parent.color = "black"
k.parent.parent.color = "red"
k = k.parent.parent
else:
if k == k.parent.left:
k = k.parent
self.right_rotate(k)
k.parent.color = "black"
k.parent.parent.color = "red"
self.left_rotate(k.parent.parent)
else:
# 与上面的代码一模一样,只不过是方向相反
u = k.parent.parent.right
if u.color == "red":
u.color = "black"
k.parent.color = "black"
k.parent.parent.color = "red"
k = k.parent.parent
else:
if k == k.parent.right:
k = k.parent
self.left_rotate(k)
k.parent.color = "black"
k.parent.parent.color = "red"
self.right_rotate(k.parent.parent)
if k == self.root:
break
self.root.color = "black"
def print_tree(self, node, indent, last):
# 用于打印红黑树的辅助函数
if node != self.TNULL:
print(indent, end=' ')
if last:
print("R----", end=' ')
indent += " "
else:
print("L----", end=' ')
indent += "| "
s_color = "RED" if node.color == "red" else "BLACK"
print(str(node.data) + "(" + s_color + ")")
self.print_tree(node.left, indent, False)
self.print_tree(node.right, indent, True)
特点:
不基于固定时间片,而是动态分配
使用虚拟运行时间来进行比较,避免优先级倒置问题
当进程创建或唤醒时,它会被插入到红黑树中
当进程消耗时间片后,它会被重新插入到树中,保证调度的公平性
实时调度器
实时调度器为需要快速响应的实时任务提供服务,分为两种策略:
SCHED_FIFO(先进先出):没有时间片的概念,一旦获得CPU,除非自己放弃,或者有更高优先级的进程需要运行,否则会一直运行。
SCHED_RR(轮转):类似于SCHED_FIFO,但是每个进程运行一定的时间片后,如果还有其他同优先级的进程等待,则自动放弃CPU。
进程调度过程
当前运行进程的时间片用完或主动放弃CPU时,进程调度器被唤醒。
进程调度器选择下一个运行的进程。
如果有实时进程等待运行,根据实时调度策略选择进程。
如果没有实时进程,按照CFS策略从红黑树中选择下一个运行的进程。
结语
领取专属 10元无门槛券
私享最新 技术干货