Linux下进程信息procpidstatus的深⼊分析这⾥我们主要介绍进程的状态,进程的状态可以通过/proc/PID/status来查看,也可以通过/proc/PID/stat来查看.
如果说到⼯具⼤家⽤的最多的ps也可以看到进程的信息.这⾥我们通过/proc/PID/status来分析进程的信息.
在2.6.18之后的内核,多了capibilty/cpusets等信息.
查看进程状态信息如下:
more status
Name: rsyslogd
State: S (sleeping)
Tgid: 987
Pid: 987
PPid: 1
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
Utrace: 0
FDSize: 32
Groups:
VmPeak: 36528 kB
VmSize: 36528 kB
VmLck: 0 kB
VmHWM: 1432 kB
VmRSS: 1420 kB
VmData: 33980 kB
VmStk: 88 kB
VmExe: 320 kB
VmLib: 2044 kB
VmPTE: 56 kB
VmSwap: 0 kB
Threads: 3
SigQ: 1/7954
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001001206
SigCgt: 0000000180014c21
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: 3
Cpus_allowed_list: 0-1
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 1
nonvoluntary_ctxt_switches: 0
Name: rsyslogd
解释:进程名
State: S (sleeping)
解释:进程的状态我们前⽂已经做了很详细的分析,各进程的状态代表的意义如下:
R (running)", "S (sleeping)", "D (disk sleep)", "T (stopped)", "T(tracing stop)", "Z (zombie)", or "X (dead)"
Tgid: 987
解释:Tgid是线程组的ID,⼀个线程⼀定属于⼀个线程组(进程组).
Pid: 987
解释:这个是进程的ID,更准确的说应该是线程的ID.
例如:
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 987 1 987 0 3 00:18 ? 00:00:00 /sbin/rsyslogd -c 4
root 987 1 989 0 3 00:18 ? 00:00:00 /sbin/rsyslogd -c 4
root 987 1 990 0 3 00:18 ? 00:00:00 /sbin/rsyslogd -c 4
注:
/proc/pid/status中的Pid就是ps命令的LWP列输出,PID⼀列其实是进程组,⽽LWP是轻量级进程,也就是线程,因为所有的进程必须⼀个线程,那就是它⾃⼰.
PPid: 1
解释:当前进程的⽗进程
TracerPid: 0
解释:跟踪当前进程的进程ID,如果是0,表⽰没有跟踪.
例如:
⽤strace跟踪top程序
strace top
查看top进程
ps -axjf
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2491 2500 2500 2491 pts/2 2500 S+ 0 0:00 \_ strace top
2500 2501 2500 2491 pts/2 2500 S+ 0 0:00 \_ top
查看top进程的TracerPid位
cat /proc/2501/stat
stat statm status
test1:/proc/2431# cat /proc/2501/status
Name: top
State: S (sleeping)
Tgid: 2501
Pid: 2501
PPid: 2500
TracerPid: 2500
Uid: 0 0 0 0
Gid: 0 0 0 0
解释:
第⼀列数字(RUID):实际⽤户ID,指的是进程执⾏者是谁.
第⼆列数字(EUID):有效⽤户ID,指进程执⾏时对⽂件的访问权限.
第三列数字(SUID):保存设置⽤户ID,作为effective user ID的副本,在执⾏exec调⽤时后能重新恢复原来的effectiv user ID.
第四列数字(FSUID):⽬前进程的⽂件系统的⽤户识别码.⼀般情况下,⽂件系统的⽤户识别码(fsuid)与有效的⽤户识别码(euid)是相同的.
这⾥重点说明RUID和EUID,我们⽤test⽤户启动top,如下:
终端1)
su - test
top
查看该进程的EUID和RUID,如下:
终端2)
cat /proc/`pgrep top|grep -v grep`/status
前⾯略
Uid: 1002 1002 1002 1002
Gid: 1003 1003 1003 1003
后⾯略
注:这⾥我们看到进程的RUID和EUID都变成了1002.
我们将程序top加上setuid权限,如下:
chmod +s /usr/bin/top
重新运⾏top程序,并查看它的RUID和EUID,如下:
cat /proc/`pgrep top|grep -v grep`/status
前⾯略
Uid: 1002 0 0 0
Gid: 1003 0 0 0
后⾯略
注:我们看到RUID还是1002,说明程序是由test⽤户(UID=1002)启动的,⽽程序设定了setuid,那么在程序运⾏时是⽤程序的owner权限来运⾏程序,⽽不是启动的⽤户权限.
由于top的owner是root,那么它的EUID是0.
FDSize: 32
解释:
FDSize是当前分配的⽂件描述符,这个值不是当前进程使⽤⽂件描述符的上限.
我们看到这⾥是32,但实际并没有分配32个⽂件,如下:
ls -l /proc/`pgrep rsyslogd|grep -v grep`/fd
total 0
lrwx------ 1 root root 64 2011-04-20 20:03 0 -> socket:[5741]
l-wx------ 1 root root 64 2011-04-20 20:03 1 -> /var/log/auth.log
l-wx------ 1 root root 64 2011-04-20 20:03 10 -> /var/
l-wx------ 1 root root 64 2011-04-20 20:03 11 -> /var/log/it
l-wx------ 1 root root 64 2011-04-20 20:03 12 -> /var/log/
l-wx------ 1 root root 64 2011-04-20 20:03 13 -> /var/log/ice
l-wx------ 1 root root 64 2011-04-20 20:03 14 -> /var/log/debug
l-wx------ 1 root root 64 2011-04-20 20:03 15 -> /var/log/messages
lrwx------ 1 root root 64 2011-04-20 20:03 16 -> /dev/xconsole
lr-x------ 1 root root 64 2011-04-20 20:03 17 -> /proc/kmsg
l-wx------ 1 root root 64 2011-04-20 20:03 2 -> /var/log/syslog
l-wx------ 1 root root 64 2011-04-20 20:03 3 -> /var/log/daemon.log
l-wx------ 1 root root 64 2011-04-20 20:03 4 -> /var/log/kern.log
l-wx------ 1 root root 64 2011-04-20 20:03 5 -> /var/log/lpr.log
l-wx------ 1 root root 64 2011-04-20 20:03 6 -> /var/log/mail.log
l-wx------ 1 root root 64 2011-04-20 20:03 7 -> /var/log/user.log
l-wx------ 1 root root 64 2011-04-20 20:03 8 -> /var/log/mail.info
l-wx------ 1 root root 64 2011-04-20 20:03 9 -> /var/log/mail.warn
我们看到这⾥只⽤到了18个⽂件描述符.⽽如果超过32个⽂件描述符,将以32进⾏递增,如果是64位系统,将以64进⾏递增.
FDSize这个值不会减少,如果我们程序打开了300个⽂件,并不会因为关闭⽂件,⽽减少FDSize这个值.
Groups: 0
解释:
这⾥的groups表⽰启动这个进程的⽤户所在的组.
我们当前的⽤户test,现在在两个组(1000,2000)⾥⾯,如下:
id
uid=1002(test) gid=1002(nagcmd) groups=1000(chenkuo),1002(nagcmd)
⽤test⽤户启动top程序,并查看它的groups,如下:
终端1
top
终端2
cat /proc/`pgrep top|grep -v grep`/status
截取信息如下:
Groups: 1000 1002
VmPeak: 36528 kB
解释:这⾥的VmPeak代表当前进程运⾏过程中占⽤内存的峰值.
我们⽤下⾯的程序申请内存,然后释放内存,最后通pause()函数中⽌程序的运⾏,程序源码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char *argv[])
{
if (argc != 2)
exit (0);
size_t mb = strtoul(argv[1],NULL,0);
size_t nbytes = mb * 0x100000;
char *ptr = (char *) malloc(nbytes);
if (ptr == NULL){
perror("malloc");
exit (EXIT_FAILURE);
}
printf("allocated %d mb\n", mb);
free(ptr);
pause();
return 0;
}
gcc callmem.c -o callmem
./callmem 10
allocated 10 mb
终端2
我们打开status⽂件,查看VmPeak值,如下:
cat /proc/`pgrep callmem|grep -v grep`/status
Name: callmem
State: S (sleeping)
Tgid: 2930
Pid: 2930
PPid: 2831
TracerPid: 0
Uid: 1002 1002 1002 1002
linux下的sleep函数Gid: 1002 1002 1002 1002
FDSize: 256
Groups: 1000 1002
VmPeak: 11852 kB
VmSize: 1608 kB
VmLck: 0 kB
VmHWM: 396 kB
VmRSS: 396 kB
VmData: 28 kB
VmStk: 84 kB
VmExe: 4 kB
VmLib: 1468 kB
VmPTE: 12 kB
下⾯略
注:我们看到程序申请了10240kb(10MB)的内存,VmPeak的值为11852kb,为什么不是10MB呢,因为除了我们申请的内存外,程序还会为加载动态链接库⽽占⽤内存.
VmSize: 36528 kB
解释:VmSize代表进程现在正在占⽤的内存
这个值与pmap pid的值基本⼀致,如果略有不同,可能是内存裂缝所造成的.
VmLck: 0 kB
解释:VmLck代表进程已经锁住的物理内存的⼤⼩.锁住的物理内存不能交换到硬盘.
我们⽤下⾯的程序进⾏测试,如下:
#include <stdio.h>
#include <sys/mman.h>
int main(int argc, char* argv[])
{
char array[2048];
if (mlock((const void *)array, sizeof(array)) == -1) {
perror("mlock: ");
return -1;
}
printf("success to lock stack mem at: %p, len=%zd\n",
array, sizeof(array));
sleep(60);
if (munlock((const void *)array, sizeof(array)) == -1) {
perror("munlock: ");
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论