top工具全字段解析+实战(三)

-----------接上篇,本文开始介绍进程信息。

 

9、进程信息

依次来看下top展示的进程任务信息:

 (1)PID:进程号,一个任务的进程号。

注意:top默认是显示的进程模式,也就是说一个创建了多个线程的程序不会被展开显示,而这个pid号是整个进程的pid。事实上,线程在内核中也是进程,它也是有唯一pid。因为不管是进程还是线程,在内核中通通都用task_struct表示。Top没有展开线程模式的时候,这个pid号对应内核的tgid。

 Tgid为是thread group id,也就是说一个多线程的进程,相当于一个group,这个组里面有一个leader,那么这个leader的pid就是整个进程的tgid。所以我们从top上看到的进程pid是线程组id,也就是tgid。Top -H命令来展开线程模式,这样我们就可以看到每个任务的自己的pid了。

 

(2)User:运行这个进程的有效用户名。 (linux有很多种uid,如ruid、euid、suid等。这个用户名实际上对应EUID,effective user id,下面会讲到)

这个USER字段直接用户名称(字符串),而这个字符串是由用户的uid + /etc/passwd转换而来的。为什么呢?这是因为linux使用id来标示每一个用户,而实际的用户名称(字符串)保存在/etc/passwd文件中,当我们运行top的时候,top是先通过/proc/pid/status接口读出uid字段,然后在/etc/passwd文件中根据uid读出用户名。

Linux里面的User ID Definition,简称UID,是识别每个用户的一个ID号,而我们看到的用户名称通常只不过是作为一种人机接口的手段,符合人类阅读记忆,其实在linux内部完全可以用id来做管理/识别。

通常,UID的1到99通常是为特殊系统用户保留的,比如系统里的daemon, lp, ftp, news, mail,这些用户。而还有一个更特殊的用户UID=0,这个就是我们的超级用户root,没有比它更牛逼的了,有且仅有一个。

所以在linux系统中,非特权用户的uid(也就是一些普通用户)一般从100开始。但也有些特别的。比如Red-hat系统uid从500开始,centos系统从1000开始,总之不跟系统用户冲突就好。

 

看下red-hat服务器(Red-hat):

 

Passwd中的用户:(UID从500开始)

看下centos服务器(centos):

 

Passwd中的用户:(UID从1000开始)

刚才我们说到,这个USER字段对应的是EUID,EUID是什么?

通常来说,一个用户使用shell登陆到系统就确认了其身份,这个身份就是用户的user id,而user name和user id身份等同,只不过使用字符串来标识该用户。从系统的角度来看,UID确认了一个用户的唯一身份而对进程而言,这个UID分化成了real user ID,effective user ID,save set-user-ID和file system user ID。(别忘了我们的主题,top是在看进程状态哦)上面已经说过,这个EUID代表是有效的用户,有效用户不一定就是当前用户。也就是说当一个用户A去执行一个程序时,这个USER字段不一定就是A。这取决于该二进制文件的可执行标记位是否设置了s属性。

当一个文件设置了s属性后,执行这个文件的进程会具备该文件属主的权限(也就是设置EUID)。如何设置一个文件的可执行标记位的s属性,如下图:

所以,这个EUID是对进程而言的,进程执行时,会拥有有不同的uid属性(ruid/euid/suid),来标记进程的属主和权限等,这个EUID控制了进程运行时所预备的权限。

举例:比如系统当前有一个用户A,他去运行一个可执行文件的时候,通常这个USER字段就是A。但是如果可执行文件设置了s属性,那么A用户执行时,这个USER字段可能是root或是其他。A用户会使用该文件的属主的权限。

 

实验1:

用普通用户来执行一个程序,观察USER字段。 通过ls -l命令可以看出这个可执行文件是属于root用户的,但“-rwxr-xr-x”表明普通用户是有可执行权限的。

可以看到进程18369的USER字段是yuchen,和当前shell用户一致。通常情况下USER都是和用户一致。

实验2:

设置可执行程序的s属性,“-rwsr-xr-x”,使用普通用户,再次执行测试程序:

使用另一个终端运行top,可以看到这个程序的USER字段是root!这是因为这个可执行文件本身的属主是root,普通用户执行它时,具备了root权限。

当然top也提供了查看当前真实有用户的字段,也就是RUID,可以看到ruid为yuchen,而uid是root。

S属性的另外一个例子是/usr/bin/passwd,我们知道用户和密码相关都是存放在/etc/passwd和/etc/shadow文件中,看下这2个文件的属性信息:

-bash-4.1$ ls -l /etc/passwd

-rw-r--r-- 1 root root 3324  6月 21 11:26 /etc/passwd

-bash-4.1$ ls -l /etc/shadow

---------- 1 root root 3973  6月 21 11:27 /etc/shadow

-bash-4.1$

 

-bash-4.1$ cat /etc/shadow

cat: /etc/shadow: 权限不够

-bash-4.1$

 

假如我是一个普通用户,显然我是可以修改我的密码的,通过passwd命令,地球人都知道。自己修改自己的密码肯定是被允许的。但是/etc/passwd文件只允许root用户来修改,我作为一个普通用户登录后,我的实际用户ID和有效用户ID都是我自己的UID。从上面可以看出,显然我不具有修改/etc/shadow和/etc/passwd文件的权限,那我执行passwd命令时怎么改我的密码的呢?从前面描述的基本概念中我们知道决定我们权限的是执行操作时的有效用户ID,所有我们在执行passwd命令时,我们的有效用户ID肯定被修改了。

OK,我们再来看下passwd可执行文件的属性,果然不出所料,passwd工具设置s属性,也就是说运行这个程序的进程会提升到root权限,那么自然就可以修改shadow文件啦。

[root@localhost top]# ls -l /usr/bin/passwd

-rwsr-xr-x. 1 root root 27832 Jun 10  2014 /usr/bin/passwd

[root@localhost top]#

一个可执行文件设置了S属性后,意味要保存用户id的作用,也就是suid,为什么要保存用户id呢,因为设置S属性,通常是意味着一个普通用户要临时提升权限来操作一些资源,操作后还要还原。所以将用户id保存到suid中,用于恢复进程用户权限。

总结:

RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个linux系统后就唯一确定了他的RUID.

EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID。系统判断一个用户是否有权限,都是在判断EUID。

设置用户ID位(s属性):用于对外的权限的开发,它的作用是去修改有效用户ID获取和文件属主一样的操作权限。

SUID是有效用户ID副本,既然有效用户ID是副本,那么它的作用肯定是为了以后恢复有效用户ID用的。

 

Ruid、euid、suid这些概念,涉及到linux的权限管理,用户管理知识,在linux源码中称credential,感兴趣的同学可以对照kernel源码及文档继续深挖。

http://man7.org/linux/man-pages/man7/credentials.7.html

http://www.unix.org/version3/ieee_std.html

http://pubs.opengroup.org/onlinepubs/9699919799/

 

 

(3)PR:任务优先级

Priority,在linux系统中共有140个优先级,并将任务分成2类:实时任务和普通任务。
(1) 实时任务是霸道型任务,任务优先级范围是0~99,实时任务基于优先级进行调度,高优先级任务具有优先运行权。所以当系统中有实时任务时,top的PR字段会显示rt字样,表示是实时任务。而普通任务在它面前就是个小赤佬,没有任何话语权,它不运行完,你休想运行。

(2) 普通任务是nice型任务,为什么取名nice呢?前面已经提到过nice的概念,nice的英文意思不仅有漂亮,美好之意,另外还有善良的意思。在linux系统中,普通任务被描述成一种“善良”的任务,它不像rt任务那么霸道,它的调度规则是基于时间片轮转的,让大家都有机会执行,它不会占着cpu不放。

扩展知识(调度相关)
注意,上面说的实时任务太霸道了,在早期的调度算法中,这种rt任务的存在可能会引起严重的系统问题,想想假设系统里有个高优先级实时任务如果存在bug,跑着跑着,跑到死循环里了,那么其他任务就永久无法被调度执行,这个时候系统就像死机一样,想登陆到系统里看看是啥情况,这都没有机会了。。所以linux2.6版本期间内核发布了一个非常重要的patch,出现了实时任务的带宽限制,linux为了避免rt任务一直占着cpu不放,在单位周期内rt任务只能跑一定的比例时间,默认1秒钟内只能跑0.95秒,也就是95%。这样的话,即使实时任务写成死循环也不能完全占着cpu不放,当内核发现某个rt任务1秒内已经运行了0.95秒,内核马上启动熔断机制,你就是再牛逼我也不能让你跑了,起码得让我们那些“善良的任务”跑一跑。

好了,我们回到正题,来看下top的PR字段,有哪些取值?通过前面的介绍。我们可以知道如果PR字段显示rt字样,那么该任务一定实时任务。但是top并没有显示所有rt任务,通常优先级是最高级99才会被显示,系统里只有watchdog和migration内核线程才会显示rt。

Top源码中,对任务的priority字段进行了判断,rt任务priority范围是-100~-1,所有只有-100才会显示。

看下内核线程migration/0的priority字段值。就是-100。rt_priority是99,是最高优先级。

[root@localhost top]# cat /proc/7/comm

migration/0

[root@localhost top]# cat /proc/7/stat |awk '{print $18}'

-100

[root@localhost top]# cat /proc/7/stat |awk '{print $40}'

99

[root@localhost top]#

但是其他的实时任务但是优先级值是多少呢?遗憾的是top工具貌似并没有给出,不过,我们可以手动读取/proc/pid/stat第40个字段来查看rt_prio。另外ps –oe rt_prio也可以查看。


除了实时任务,系统里大部分都是普通任务,普通任务的优先级是可以看到的,PR的范围是0~39。普通任务的默认优先级是20,相当于NICE=0。普通任务可以通过调整nice值,来改变任务的优先级。

基本公式: PRI = 20-NICE

用几张图总结上面所说的内容:

 

在实时任务中还有另外一种调度策略,即deadline,这可谓是真正的实时任务,相比较SCHED_RR和SCHED_FIFO而言,它具备更高的优先执行权,因为这种任务是以任务的执行期限而调度的。它规定了cpu调度时,在一定周期内必须要运行必备参数。运行周期(period)、运行时间(runtime)和最后期限(deadline)。这些参数大大的保证了任务的实时性。

--十万火急,限期完成 SCHED_DEADLINE调度属性, 3.14加入内核。

此策略支持的是一种非常严格的实时任务。对于某些实时任务,具有阵发性(sporadic), 它们阵发性地醒来执行任务,且任务有 deadline 要求,因此要保证在 deadline 时间到来前完成。为了完成此目标,采用该 SCHED_DEADLINE 的任务是系统中最高优先级的,它们醒来时可以抢占任何进程。

https://lwn.net/Articles/575497/

那deadline任务有优先级吗?是多少? 答案是有,deadline任务的优先级是-1,可见,-1比0还小,所以它的优先级更高。我们在内核源码task_struct结构中可以看到好几个prio字段,描述动态优先级、静态优先级、实时优先级、优先级等概念,prio字段是归一化优先级,把所有调度策略的优先级,归一化到prio字段,按照优先级排序,所以就有了上面说的0~139优先级,和deadline优先级-1。

struct task_struct {
……
	int prio, static_prio, normal_prio;
	unsigned int rt_priority;
……
}

但我们要清楚事实上DL调度器并不根据优先级去调度,那是RR和FIFO策略的原理,DL任务是有执行期限的,它比RT任务更猛,更牛逼!

 

 

 

 

 

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页