linux进程家族树怎么画

linux进程家族树怎么画,第1张

pstree

pstree显示正在运行进程的树形结构,树以PID为根;如果省略了pid则以init为根。如果指定了用户名,则显示根植于该用户拥有的进程的所有进程树。如果pstree被调用为pstree.x11,那么它将提示行尾的用户按RETURE,并且在这种情况发生之前不会返回。这对于在x终端中运行pstree非常有用。

pstree通过将相同的分支放在方括号中并以重复计数作为前缀,在视觉上合并它们。例如:

init-+-getty

|-getty

|-getty

‘-getty

变成下面的样子

init---4*[getty]

进程的子线程在父进程下找到,并以大括号显示进程名,例如:

icecast2---13*[{icecast2}]

此命令的适用范围:RedHat、RHEL、Ubuntu、CentOS、SUSE、openSUSE、Fedora。

1、语法

pstree [选项]

2、选项列表

选项

说明

-a

显示每个进程的完整指令,包括路径、参数

-A

使用ascii码显示树形

-c

关闭精简表示法

-G

使用VT 100线条绘制字符

-h

高亮显示正在执行的程序

-H

类似“-h”,但是突出显示指定的进程。与-h不同,如果高亮显示不可用,pstree在使用-H时会失败。

-l

长格式显示

-n

以进程号排序,默认以名字排序

-p

显示pid

-u

显示用户

-U

以utf-8显示字符

-V

显示命令版本信息

-Z

每个SELinux的上下文

3、实例

1)显示完成的树形结构

[root@localhost ~]# pstree -a

init

├─NetworkManager --pid-file=/var/run/NetworkManager/NetworkManager.pid

│ ├─dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-eth0.pid ...

│ └─{NetworkManager}

├─VBoxClient --clipboard

│ └─VBoxClient --clipboard

2)显示进程号

[root@localhost ~]# pstree -p

init(1)─┬─NetworkManager(6362)─┬─dhclient(6377)

│ └─{NetworkManager}(6379)

├─VBoxClient(7869)───VBoxClient(7870)───{VBoxClient}(7872)

├─VBoxClient(7882)───VBoxClient(7883)

├─VBoxClient(7890)───VBoxClient(7891)───{VBoxClient}(7894)

├─VBoxClient(7898)───VBoxClient(7899)─┬─{VBoxClient}(7901)

│└─{VBoxClient}(7903)

├─VBoxClient(7306)───VBoxClient(7308)

├─VBoxClient(7312)───VBoxClient(7314)───{VBoxClient}(7317)

├─VBoxClient(7318)───VBoxClient(7320)─┬─{VBoxClient}(7323)

│└─{VBoxClient}(7325)

上回书说到 Linux进程的由来 和 Linux进程的创建 ,其实在同一时刻只能支持有限个进程或线程同时运行(这取决于CPU核数量,基本上一个进程对应一个CPU),在一个运行的 *** 作系统上可能运行着很多进程,如果运行的进程占据CPU的时间很长,就有可能导致其他进程饿死。为了解决这种问题, *** 作系统引入了 进程调度器 来进行进程的切换,轮流让各个进程使用CPU资源。

1)rq: 进程的运行队列( runqueue), 每个CPU对应一个 ,包含自旋锁(spinlock)、进程数量、用于公平调度的CFS信息结构、当前运行的进程描述符等。实际的进程队列用红黑树来维护(通过CFS信息结构来访问)。

2)cfs_rq: cfs调度的进程运行队列信息 ,包含红黑树的根结点、正在运行的进程指针、用于负载均衡的叶子队列等。

3)sched_entity: 把需要调度的东西抽象成调度实体 ,调度实体可以是进程、进程组、用户等。这里包含负载权重值、对应红黑树结点、 虚拟运行时vruntime 等。

4)sched_class:把 调度策略(算法)抽象成调度类 ,包含一组通用的调度 *** 作接口。接口和实现是分离,可以根据调度接口去实现不同的调度算法,使一个Linux调度程序可以有多个不同的调度策略。

1) 关闭内核抢占 ,初始化部分变量。获取当前CPU的ID号,并赋值给局部变量CPU, 使rq指向CPU对应的运行队列 。 标识当前CPU发生任务切换 ,通知RCU更新状态,如果当前CPU处于rcu_read_lock状态,当前进程将会放入rnp->blkd_tasks阻塞队列,并呈现在rnp->gp_tasks链表中。 关闭本地中断 ,获取所要保护的运行队列的自旋锁, 为查找可运行进程做准备 。

2) 检查prev的状态,更新运行队列 。如果不是可运行状态,而且在内核态没被抢占,应该从运行队列中 删除prev进程 。如果是非阻塞挂起信号,而且状态为TASK_INTER-RUPTIBLE,就把该进程的状态设置为TASK_RUNNING,并将它 插入到运行队列 。

3)task_on_rq_queued(prev) 将pre进程插入到运行队列的队尾。

4)pick_next_task 选取将要执行的next进程。

5)context_switch(rq, prev, next)进行 进程上下文切换 。

1) 该进程分配的CPU时间片用完。

2) 该进程主动放弃CPU(例如IO *** 作)。

3) 某一进程抢占CPU获得执行机会。

Linux并没有使用x86 CPU自带的任务切换机制,需要通过手工的方式实现了切换。

进程创建后在内核的数据结构为task_struct , 该结构中有掩码属性cpus_allowed,4个核的CPU可以有4位掩码,如果CPU开启超线程,有一个8位掩码,进程可以运行在掩码位设置为1的CPU上。

Linux内核API提供了两个系统调用 ,让用户可以修改和查看当前的掩码:

1) sched_setaffinity():用来修改位掩码。

2) sched_getaffinity():用来查看当前的位掩码。

在下次task被唤醒时,select_task_rq_fair根据cpu_allowed里的掩码来确定将其置于哪个CPU的运行队列,一个进程在某一时刻只能存在于一个CPU的运行队列里。

在Nginx中,使用了CPU亲和度来完成某些场景的工作:

worker_processes      4

worker_cpu_affinity 0001001001001000

上面这个配置说明了4个工作进程中的每一个和一个CPU核挂钩。如果这个内容写入Nginx的配置文件中,然后Nginx启动或者重新加载配置的时候,若worker_process是4,就会启用4个worker,然后把worker_cpu_affinity后面的4个值当作4个cpu affinity mask,分别调用ngx_setaffinity,然后就把4个worker进程分别绑定到CPU0~3上。

worker_processes      2

worker_cpu_affinity 01011010

上面这个配置则说明了两个工作进程中的每一个和2个核挂钩。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7469582.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-06
下一篇2023-04-06

发表评论

登录后才能评论

评论列表(0条)

    保存