linux /proc/pid/status 解析

目录

各个字段说明:

Name

State

Tgid

Pid

PPid

TracerPid

Uid

Gid

FDSize

Groups

 VmPeak

VmSize

VmLck

VmPin

VmHWM

VmRSS

VmData

VmStk

VmExe

VmLib

VmPTE

VmPMD

VmSwap

Threads

SigQ

SigPnd

ShdPnd

SigBlk

SigIgn

SigCgt

CapInh

CapPrm

CapEff

CapBnd

Cpus_allowed

Cpus_allowed_list

voluntary_ctxt_switches

nonvoluntary_ctxt_switches


示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

void* run(void* arg)
{
    sleep(10000);
    return NULL;
}

int main()
{
    char* arr[10240]={0};
    for(int i=0;i<10240;i++)
    {
        char *tmp = (char*)malloc(1024);
        if (tmp == NULL)
        {
            perror("malloc exception");
            exit(-1);
        }
        memset(tmp,1024,1);
        arr[i] =tmp;
    }

    pthread_t t;
    pthread_create(&t,NULL,run,NULL);
    pthread_join(t,NULL);

    pause();
    return 0;
}

cat  /proc/pid/status

Name:   a.out
State:  S (sleeping)
Tgid:   4869
Ngid:   0
Pid:    4869
PPid:   2072
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 256
Groups: 0 
NStgid: 4869
NSpid:  4869
NSpgid: 4869
NSsid:  2072
VmPeak:    25004 kB
VmSize:    25004 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     11492 kB
VmRSS:     11492 kB
VmData:    18692 kB
VmStk:       132 kB
VmExe:         4 kB
VmLib:      2040 kB
VmPTE:        52 kB
VmPMD:        12 kB
VmSwap:        0 kB
HugetlbPages:          0 kB
Threads:        2
SigQ:   0/15567
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000180000000
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
Seccomp:        0
Speculation_Store_Bypass:       thread vulnerable
Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
Cpus_allowed_list:      0-127
Mems_allowed:   00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        1
nonvoluntary_ctxt_switches:     1

各个字段说明:

Name

        进程名

State

        进程状态,"R (running)", "S (sleeping)", "D (disk sleep)", "T (stopped)", "T(tracing stop)",     "Z (zombie)", or "X (dead)"

Tgid

        线程ID,准确的说是主线程ID,因为程序a.out 有两个线程。

Pid

        进程ID

PPid

        父进程ID

TracerPid

        追逐当前进程的进程ID

测试:
strace top

Uid

         0       0       0       0


Gid

           0       0       0       0

解释:

        第一列RUID:实际UID,表示程序执行的用户UID。

        第二列EUID:有效UID,表示进程执行时,对文件的访问权限。

        第三列SUID:保存设置用户ID,作为effective user ID的副本,在执行exec调用时后能重新恢复原来的effectiv user ID。

        第四列FSUID:目前进程的文件系统的用户识别码.一般情况下,文件系统的用户识别码(fsuid)与有效的用户识别码(euid)是相同的。

使用普通用户执行top:

        su - humou

        top

        cat /proc/`pgrep top|grep -v grep`/status

        程序运行时,带有1001用户权限。

        

        chmod +s /usr/bin/top

        程序运行时,带有root权限。

        

FDSize

        进程分配的文件描述符的最大值。只增不减。

Groups

        启动该进程的用户所处组。由于是root,所以为0。

 切换到humou用户,cp ./a.out /home/humou && cd /home/humou && chmod 777 a.out && su - humou && ./a.out 

 VmPeak

        表示进程运行过程中占用内存的峰值。

示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>


int main(int argc,const char* argv[])
{
    if (argc != 2)
    {
        printf("invalid param\n");
        exit(-1);
    }
    size_t mb = strtoul(argv[1],NULL,0);
    size_t nbytes = mb << 20;
    char *ptr =(char*)malloc(nbytes);
    if (ptr == NULL)
    {
        printf("malloc failed\n");
        exit(-1);
    }
    printf("malloc %d MB\n",mb);
    free(ptr);
    pause();
    return 0;
}


gcc main.c && ./a.out 10

cat /proc/`pgrep a.out|grep -v grep`/status

 10MB = 10240 KB < 14588KB

因为进程加载动态链接库也需要内存。

VmSize

        表示进程所占用的内存,包含交换分区。

VmLck

        表示进程被锁住的内存,不允许交换到磁盘。需要使用系统调用mlock实现锁内存。相对于VMPin, VmLck被锁住的内存可以被内核在RAM中移动,程序下一次访问该页可能会触发软缺页中断,这对于一般程序来说没有影响,但对于硬实时的程序来说,这种错误不能被接受。

https://lwn.net/Articles/600502/

示例程序:

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    char arr[4097]={0};

    if ( mlock(arr,sizeof(arr)) != 0 )
    {
        perror("mlock failed");
        exit(-1);
    }

    sleep(5);

    if ( munlock(arr,sizeof(arr)) != 0 )
    {
        perror("munlock failed");
        exit(-1);
    }
    sleep(5);

    printf("success lock and unlock 8KB memory\n");

    return 0;
}

0~5s,因为操作系统内存页为4KB,所以申请4097会占用两页。

5~10s

 

VmPin

        固定内存是固定在特定页框位置的锁定内存。固定的页面既不能被移除物理内存,也不能被内核在RAM中移动。

VmHWM

        表示程序分配到的物理内存峰值

示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>


int main(int argc,const char* argv[])
{
    if (argc != 2)
    {
        printf("invalid param\n");
        exit(-1);
    }
    size_t mb = strtoul(argv[1],NULL,0);
    size_t nbytes = mb << 20;
    char *ptr =(char*)malloc(nbytes);
    if (ptr == NULL)
    {
        printf("malloc failed\n");
        exit(-1);
    }
    size_t psize = sysconf(_SC_PAGE_SIZE);
    for (int i = 0;i < nbytes; i += psize) 
    {
        ptr[i] = 0;
    }
    printf("malloc %d MB\n",mb);
    //free(ptr);
    pause();
    return 0;
}

cat /proc/`pgrep a.out|grep -v grep`/status

  103496kb > 102400kb


VmRSS

        表示程序现在使用的物理内存

测试:

在执行程序前,free -m,空闲内存为3651MB ,交换分区空闲832MB 

./a.out 2000 &  申请2000MB

cat /proc/`pgrep a.out|grep -v grep`/status

可以看到程序确实占用2G;

free -m,物理内存锐减2000MB,交换分区未被使用。

然后再启动另外一个进程,分配2000M

./a.out 2000 & ,很显然物理内存不够用,必须动用交换分区。

查看第一个a.out进程的物理内存占用情况: cat /proc/12915/status

查看第二个a.out进程的物理内存占用情况:cat /proc/12946/status

从现象来看,一定是第一个进程的部分数据被交换到 交换分区,腾出足够的内存来给第二个进程使用。

free -m,可以看到物理内存所剩无几,交换内存也使用了很大一部分。

VmData

        表示进程数据段的大小.

VmStk

        表示进程堆栈段的大小.

VmExe

        表示进程代码的大小.

VmLib

        表示进程所使用LIB库的大小.

关于代码段,堆栈段,数据段:

代码段可以为机器中运行同一程序的数个进程共享

堆栈段存放的是子程序(函数)的返回地址、子程序的参数及程序的局部变量

数据段则存放程序的全局变量、常数以及动态数据分配的数据空间(比如用malloc函数申请的内存)

与代码段不同,如果系统中同时运行多个相同的程序,它们不能使用同一堆栈段和数据段.

VmPTE

        占用的页表的大小。(since Linux 2.6.10)


VmPMD

        占用二级页表大小。(since Linux 4.0)


VmSwap

        进程占用交换分区的大小。

Threads

        线程数

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *run(void *arg)
{
	pause();
	return NULL;
}

int main()
{
	pthread_t t;
	pthread_create(&t, NULL, run, NULL);
	pthread_join(t, NULL);

	pause();
	return 0;
}

上述示例的进程会启动两个线程。

SigQ

        表示当前进程待处理信号数。

示例程序:
 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

volatile int done = 0;

void handler (int sig)
{
  const char *str = "handled...\n";
  write (1, str, strlen(str));
  done = 1;
}

void child(void)
{
  int i;
  for (i = 0; i < 3; i++){
    kill(getppid(), SIGRTMIN);
    printf("child - BANG!\n");
  }
  exit (0);
}

int main (int argc, char *argv[])
{
  signal (SIGRTMIN, handler);
  sigset_t newset, oldset;
  
  sigfillset(&newset);
  sigprocmask(SIG_BLOCK, &newset, &oldset);
  
  pid_t pid = fork();
  if (pid == 0)
  child();
  
  printf("parent sleeping \n");
  
  int r = sleep(30);
  
  printf("woke up! r=%d\n", r);
  
  sigprocmask(SIG_SETMASK, &oldset, NULL);
  
  while (!done){
  };
  
  printf("exiting\n");
  exit(0);
}

子进程向父进程发送3个信号,同时子进程退出时也会给父进程发送一个信号。

SigPnd

        0000000000000000

ShdPnd

         0000000000000000

SigBlk

        0000000000000000

SigIgn

        0000000001001206

SigCgt

        0000000180014c21

解释:

SigPnd:屏蔽位,存储了该线程的待处理信号,等同于线程的PENDING信号.

ShnPnd:屏蔽位,存储了该线程组的待处理信号.等同于进程组的PENDING信号.

SigBlk:存放被阻塞的信号,等同于BLOCKED信号.

SigIgn:存放被忽略的信号,等同于IGNORED信号.

SigCgt:存放捕获的信号,等同于CAUGHT信号.

CapInh

        0000000000000000

CapPrm

         ffffffffffffffff

CapEff

        ffffffffffffffff

CapBnd

         ffffffffffffffff

解释:

CapInh:表示能够被当前进程执行的程序继承的能力.

CapPrm:表示进程能够使用的能力,在cap_permitted中可以包含cap_effective中没有的能力,这些能力是被进程自己临时放弃的,也可以说cap_effective是cap_permitted的一个子集.

CapEff:当一个进程要进行某个特权操作时,操作系统会检查cap_effective的对应位是否有效,而不再是检查进程的有效UID是否为0.

CapBnd:是系统的边界能力,我们无法改变它.

Cpus_allowed

          3

Cpus_allowed_list

             0-1

解释:

Cpus_allowed:3指出该进程可以使用CPU的亲和性掩码,因为我们指定为两块CPU,所以这里就是3,如果该进程指定为4个CPU(如果有话),这里就是F(1111).

Cpus_allowed_list: 0-1指出该进程可以使用CPU的列表,这里是0-1.

修改前:

taskset -p 16184 ,限定该进程在第一个CPU上跑。

 

voluntary_ctxt_switches

        1

nonvoluntary_ctxt_switches

          0

说明:

voluntary_ctxt_switches表示进程主动切换的次数.

nonvoluntary_ctxt_switches表示进程被动切换的次数.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值