📄 display.c
字号:
if( ( (proc_format_needs|task_format_needs|needs_for_sort) & PROC_FILLWCHAN) && !wchan_is_number) if (open_psdb(namelist_file)) wchan_is_number = 1; if(thread_flags&TF_loose_tasks) needs_for_threads |= PROC_LOOSE_TASKS;}///////////////////////////////////////////////////////////////////////////***** fill in %CPU; not in libproc because of include_dead_children *//* Note: for sorting, not display, so 0..0x7fffffff would be OK */static int want_this_proc_pcpu(proc_t *buf){ unsigned long long used_jiffies; unsigned long pcpu = 0; unsigned long long avail_jiffies; if(!want_this_proc(buf)) return 0; used_jiffies = buf->utime + buf->stime; if(include_dead_children) used_jiffies += (buf->cutime + buf->cstime); avail_jiffies = seconds_since_boot * Hertz - buf->start_time; if(avail_jiffies) pcpu = (used_jiffies << 24) / avail_jiffies; buf->pcpu = pcpu; // fits in an int, summing children on 128 CPUs return 1;}/***** just display */static void simple_spew(void){ proc_t buf; PROCTAB* ptp; ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads); if(!ptp) { fprintf(stderr, "Error: can not access /proc.\n"); exit(1); } memset(&buf, '#', sizeof(proc_t)); switch(thread_flags & (TF_show_proc|TF_loose_tasks|TF_show_task)){ case TF_show_proc: // normal non-thread output while(readproc(ptp,&buf)){ if(want_this_proc(&buf)){ show_one_proc(&buf, proc_format_list); } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse } break; case TF_show_proc|TF_loose_tasks: // H option while(readproc(ptp,&buf)){ proc_t buf2; // must still have the process allocated while(readtask(ptp,&buf,&buf2)){ if(!want_this_proc(&buf)) continue; show_one_proc(&buf2, task_format_list); } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse } break; case TF_show_proc|TF_show_task: // m and -m options while(readproc(ptp,&buf)){ if(want_this_proc(&buf)){ proc_t buf2; show_one_proc(&buf, proc_format_list); // must still have the process allocated while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2, task_format_list); } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse } break; case TF_show_task: // -L and -T options while(readproc(ptp,&buf)){ if(want_this_proc(&buf)){ proc_t buf2; // must still have the process allocated while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2, task_format_list); } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse } break; } closeproc(ptp);}/***** forest output requires sorting by ppid; add start_time by default */static void prep_forest_sort(void){ sort_node *tmp_list = sort_list; const format_struct *incoming; if(!sort_list) { /* assume start time order */ incoming = search_format_array("start_time"); if(!incoming) fprintf(stderr, "Could not find start_time!\n"); tmp_list = malloc(sizeof(sort_node)); tmp_list->reverse = 0; tmp_list->typecode = '?'; /* what was this for? */ tmp_list->sr = incoming->sr; tmp_list->need = incoming->need; tmp_list->next = sort_list; sort_list = tmp_list; } /* this is required for the forest option */ incoming = search_format_array("ppid"); if(!incoming) fprintf(stderr, "Could not find ppid!\n"); tmp_list = malloc(sizeof(sort_node)); tmp_list->reverse = 0; tmp_list->typecode = '?'; /* what was this for? */ tmp_list->sr = incoming->sr; tmp_list->need = incoming->need; tmp_list->next = sort_list; sort_list = tmp_list;}/* we rely on the POSIX requirement for zeroed memory *///static proc_t *processes[98*1024]; // FIXMEstatic proc_t **processes;/***** compare function for qsort */static int compare_two_procs(const void *a, const void *b){ sort_node *tmp_list = sort_list; while(tmp_list){ int result; result = (*tmp_list->sr)(*(const proc_t *const*)a, *(const proc_t *const*)b); if(result) return (tmp_list->reverse) ? -result : result; tmp_list = tmp_list->next; } return 0; /* no conclusion */}/***** show pre-sorted array of process pointers */static void show_proc_array(PROCTAB *restrict ptp, int n){ proc_t **p = processes; while(n--){ if(thread_flags & TF_show_proc) show_one_proc(*p, proc_format_list); if(thread_flags & TF_show_task){ proc_t buf2; // must still have the process allocated while(readtask(ptp,*p,&buf2)) show_one_proc(&buf2, task_format_list); // must not attempt to free cmdline and environ } /* no point freeing any of this -- won't need more mem */// if((*p)->cmdline) free((void*)*(*p)->cmdline);// if((*p)->environ) free((void*)*(*p)->environ);// memset(*p, '%', sizeof(proc_t)); /* debug */// free(*p); p++; }}/***** show tree *//* this needs some optimization work */#define ADOPTED(x) 1static void show_tree(const int self, const int n, const int level, const int have_sibling){ int i = 0; if(level){ /* add prefix of "+" or "L" */ if(have_sibling) forest_prefix[level-1] = '+'; else forest_prefix[level-1] = 'L'; forest_prefix[level] = '\0'; } show_one_proc(processes[self],format_list); /* first show self */ /* no point freeing any of this -- won't need more mem */// if(processes[self]->cmdline) free((void*)*processes[self]->cmdline);// if(processes[self]->environ) free((void*)*processes[self]->environ); for(;;){ /* look for children */ if(i >= n) return; /* no children */ if(processes[i]->ppid == processes[self]->XXXID) break; i++; } if(level){ /* change our prefix to "|" or " " for the children */ if(have_sibling) forest_prefix[level-1] = '|'; else forest_prefix[level-1] = ' '; forest_prefix[level] = '\0'; } for(;;){ int self_pid; int more_children = 1; if(i >= n) break; /* over the edge */ self_pid=processes[self]->XXXID; if(i+1 >= n) more_children = 0; else if(processes[i+1]->ppid != self_pid) more_children = 0; if(self_pid==1 && ADOPTED(processes[i]) && forest_type!='u') show_tree(i++, n, level, more_children); else show_tree(i++, n, level+1, more_children); if(!more_children) break; } /* chop prefix that children added -- do we need this? */ forest_prefix[level] = '\0';// memset(processes[self], '$', sizeof(proc_t)); /* debug */}/***** show forest */static void show_forest(const int n){ int i = n; int j; while(i--){ /* cover whole array looking for trees */ j = n; while(j--){ /* search for parent: if none, i is a tree! */ if(processes[j]->XXXID == processes[i]->ppid) goto not_root; } show_tree(i,n,0,0);not_root: ; } /* don't free the array because it takes time and ps will exit anyway */}static int want_this_proc_nop(proc_t *dummy){ (void)dummy; return 1;}/***** sorted or forest */static void fancy_spew(void){ proc_data_t *pd = NULL; PROCTAB *restrict ptp; int n = 0; /* number of processes & index into array */ ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads); if(!ptp) { fprintf(stderr, "Error: can not access /proc.\n"); exit(1); } if(thread_flags & TF_loose_tasks){ pd = readproctab2(want_this_proc_nop, want_this_proc_pcpu, ptp); }else{ pd = readproctab2(want_this_proc_pcpu, (void*)0xdeadbeaful, ptp); } n = pd->n; processes = pd->tab; if(!n) return; /* no processes */ if(forest_type) prep_forest_sort(); qsort(processes, n, sizeof(proc_t*), compare_two_procs); if(forest_type) show_forest(n); else show_proc_array(ptp,n); closeproc(ptp);}/***** no comment */int main(int argc, char *argv[]){#if (__GNU_LIBRARY__ >= 6) setlocale (LC_CTYPE, "");#endif#ifdef DEBUG init_stack_trace(argv[0]);#else do { struct sigaction sa; int i = 32; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigfillset(&sa.sa_mask); while(i--) switch(i){ default: sigaction(i,&sa,NULL); case 0: case SIGINT: /* ^C */ case SIGTSTP: /* ^Z */ case SIGTTOU: /* see stty(1) man page */ case SIGQUIT: /* ^\ */ case SIGPROF: /* profiling */ case SIGKILL: /* can not catch */ case SIGSTOP: /* can not catch */ case SIGWINCH: /* don't care if window size changes */ ; } } while (0);#endif reset_global(); /* must be before parser */ arg_parse(argc,argv);/* arg_show(); */ trace("screen is %ux%u\n",screen_cols,screen_rows);/* printf("sizeof(proc_t) is %d.\n", sizeof(proc_t)); */ trace("======= ps output follows =======\n"); init_output(); /* must be between parser and output */ lists_and_needs(); if(forest_type || sort_list) fancy_spew(); /* sort or forest */ else simple_spew(); /* no sort, no forest */ show_one_proc((proc_t *)-1,format_list); /* no output yet? */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -