欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > linux >内容正文

linux

linux的top命令源码解析:RES指标

发布时间:2023/12/20 linux 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 linux的top命令源码解析:RES指标 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

CLion:2019.3.6
源码管理平台:Macbook Pro 10.12.6
C语言源码程序:Makefile格式的linux系统的top命令源码。
top所在的系统:ubuntu 14.04

一、源码导入

linux的top命令采用的是procps-ng项目,可以通过Clion 导入Makefile格式的C语言源程序:procps项目 这篇博客将源码进行下载和导入。

二、RES 指标的源码分析

1、输入top命令后显示如下:

对于RES指标, 代表PID进程占用的物理内存,其中包括共享库内存,RES的数据是怎么计算得来的呢,接下来我们将通过查看源码来了解这个数据的源头。

2、top的源码分析
top的源码位于top.c文件中:

top.c通过task_show如下进行获取res的数值,

/** Build the information for a single task row and* display the results or return them to the caller. */ static const char *task_show (const WIN_t *q, const int idx) {... 省略....#define pages2K(n) (unsigned long)( (n) << Pg2K_shft )... 省略....// we must begin a row with a possible window number in mind...*(rp = rbuf) = '\0';if (Rc.mode_altscr) rp = scat(rp, " ");... 省略....for (x = 0; x < q->maxpflgs; x++) {const char *cp = NULL;FLG_t i = q->procflgs[x];... 省略....switch (i) {... 省略....case EU_MEM:cp = scale_pcnt((float)pages2K(p->resident) * 100 / kb_main_total, W, Jn);... 省略....case EU_NMA:cp = make_num(numa_node_of_cpu(p->processor), W, Jn, AUTOX_NO, 0);break;case EU_RES:cp = scale_mem(S, pages2K(p->resident), W, Jn);break;case EU_SHR:cp = scale_mem(S, pages2K(p->share), W, Jn);break;case EU_SWP:cp = scale_mem(S, p->vm_swap, W, Jn);break;... 省略....default: // keep gcc happycontinue;} // end: switch 'procflag'#undef pages2K } // end: task_show

其中RES获取的片段如下:

其中p->resident 是res的数据源,p的结构:

proc_t *p = q->ppt[idx];

其中proc_t的结构体主要内容如下所示:

// Basic data structure which holds all information we can get about a process. // (unless otherwise specified, fields are read from /proc/#/stat) // // Most of it comes from task_struct in linux/sched.h // typedef struct proc_t { // 1st 16 bytesinttid, // (special) task id, the POSIX thread ID (see also: tgid)ppid; // stat,status pid of parent processunsigned long // next 2 fields are NOT filled in by readproc..........省略.........longpriority, // stat kernel scheduling prioritynice, // stat standard unix nice level of processrss, // stat identical to 'resident'alarm, // stat ?// the next 7 members come from /proc/#/statmsize, // statm total virtual memory (as # pages)resident, // statm resident non-swapped memory (as # pages)share, // statm shared (mmap'd) memory (as # pages)trs, // statm text (exe) resident set (as # pages)lrs, // statm library resident set (always 0 w/ 2.6)drs, // statm data+stack resident set (as # pages)dt; // statm dirty pages (always 0 w/ 2.6)unsigned longvm_size, // status equals 'size' (as kb)vm_lock, // status locked pages (as kb)vm_rss, // status equals 'rss' and/or 'resident' (as kb)vm_rss_anon, // status the 'anonymous' portion of vm_rss (as kb)vm_rss_file, // status the 'file-backed' portion of vm_rss (as kb)vm_rss_shared, // status the 'shared' portion of vm_rss (as kb)vm_data, // status data only size (as kb)vm_stack, // status stack only size (as kb)vm_swap, // status based on linux-2.6.34 "swap ents" (as kb)..........省略.........const char*lxcname; // n/a lxc container name } proc_t;

所以top的res是从proc_t->resident获取的,其中resident的单位是页面,是通过pages2K将页面数量转换成字节数, 页面的大小是4K:

case EU_RES:cp = scale_mem(S, pages2K(p->resident), W, Jn);

其中pages2K函数:

/* The run-time acquired page stuff */static unsigned Pg2K_shft = 0;// get virtual page stuffi = page_bytes; // from sysinfo.c, at lib initwhile(i > 1024) { i >>= 1; Pg2K_shft++; }#define pages2K(n) (unsigned long)( (n) << Pg2K_shft )

如上所示:q->ppt[idx]又是从哪儿初始化的呢?
如下代码所示:q作为task_show函数传递进来:

static const char *task_show (const WIN_t *q, const int idx) {

WIN_t的结构定义如下:

/* This structure stores configurable information for each window.By expending a little effort in its creation and user requestedmaintenance, the only real additional per frame cost of havingwindows is an extra sort -- but that's just on pointers! */ typedef struct WIN_t {FLG_t pflgsall [PFLAGSSIZ], // all 'active/on' fieldscur, as enumprocflgs [PFLAGSSIZ]; // fieldscur subset, as enumRCW_t rc; // stuff that gets saved in the rcfileint winnum, // a window's number (array pos + 1)winlines, // current task window's rows (volatile)maxpflgs, // number of displayed procflgs ("on" in fieldscur)totpflgs, // total of displayable procflgs in pflgsall arraybegpflg, // scrolled beginning pos into pflgsall arrayendpflg, // scrolled ending pos into pflgsall arraybegtask, // scrolled beginning pos into Frame_maxtaskbegnext, // new scrolled delta for next frame's begtask #ifndef SCROLLVAR_NOvarcolbeg, // scrolled position within variable width col #endifvarcolsz, // max length of variable width column(s)usrseluid, // validated uid for 'u/U' user selectionusrseltyp, // the basis for matching above uidusrselflg, // flag denoting include/exclude matcheshdrcaplen; // column header xtra caps len, if anychar capclr_sum [CLRBUFSIZ], // terminfo strings built fromcapclr_msg [CLRBUFSIZ], // RCW_t colors (& rebuilt too),capclr_pmt [CLRBUFSIZ], // but NO recurring costs !capclr_hdr [CLRBUFSIZ], // note: sum, msg and pmt strscapclr_rowhigh [CLRBUFSIZ], // are only used when thiscapclr_rownorm [CLRBUFSIZ], // window is the 'Curwin'!cap_bold [CAPBUFSIZ], // support for View_NOBOLD togglegrpname [GRPNAMSIZ], // window number:name, printable #ifdef USE_X_COLHDRcolumnhdr [ROWMINSIZ], // column headings for procflgs #elsecolumnhdr [SCREENMAX], // column headings for procflgs #endif*captab [CAPTABMAX]; // captab needed by show_special()struct osel_s *osel_1st; // other selection criteria anchorint osel_tot; // total of other selection criteriachar *findstr; // window's current/active search stringint findlen; // above's strlen, without call overheadproc_t **ppt; // this window's proc_t ptr arraystruct WIN_t *next, // next window in window stack*prev; // prior window in window stack } WIN_t;

关键的代码在readproc.c,如下代码所示:

// // This reads process info from /proc in the traditional way, for one process. // The pid (tgid? tid?) is already in p, and a path to it in path, with some // room to spare. static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) {......省略.......if (flags & PROC_FILLMEM) { // read /proc/#/statmif (likely(file2str(path, "statm", &ub) != -1))statm2proc(ub.buf, p);}......省略.......

其中statm2proc的函数实现如下:

static void statm2proc(const char* s, proc_t *restrict P) {sscanf(s, "%ld %ld %ld %ld %ld %ld %ld",&P->size, &P->resident, &P->share,&P->trs, &P->lrs, &P->drs, &P->dt); }

可以看出,top的RES是从/proc/pid/statm文件中格式化读出来的。

总结

以上是生活随笔为你收集整理的linux的top命令源码解析:RES指标的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。