Pstree源码分析一.getopt_long获取参数,根据参数设置相应的变量。二.read_proc()主要函数,获取所有的process,生成tree.#definePROC_BASE "/proc"dir=opendir(PROC_BASE))while((de=readdir(dir))!=NULL)if((pid=(pid_t)atoi(de->d_name))!=0) //即读取/proc/numbersprintf(path,"%s/%d/stat",PROC_BASE,pid); //path赋值为/proc/number/statif((file=fopen(path,"r"))!=NULL)sprintf(path,"%s/%d",PROC_BASE,pid); //path赋值为/proc/numberfread(readbuf,1,BUFSIZ,file); //读取/proc/number/stat内容到readbufif((comm=strchr(readbuf,'('))&&(tm
r=strrchr(comm,')')))//comm指向/proc/number/stat第一次出现’(‘的位置//tmpptr指向/proc/number/stat最后一次出现’)‘的位置comm;*tmpptr=0;//即comm为/proc/number/stat中command内容if(sscanf(tmpptr2,"%*c%d",&ppid)==1)//从tmpptr2位置开始的第一个整数指向为ppidsprintf(taskpath,"%s/task",path);//taskpath赋值为/proc/number/taskif((taskdir=opendir(taskpath))!=0)sprintf(threadname,"{%s}",comm);//threadname赋值为commandwhile((dt=readdir(taskdir))!=NULL)if((thread=atoi(dt->d_name))!=0)//读取/proc/number/task中的numberif(thread!=pid)//即该number!=pid,也就是该process有子线程add_proc(threadname,thread,pid,st.st_uid,NULL,0);………………..…………………略add_proc(comm,pid,ppid,st.st_uid,NULL,0);add_proc()函数add_proc(constchar*comm,pid_tpid,pid_tppid,uid_tuid,constchar*args,intsize)if(!(this=find_proc(pid)))this=new_proc(comm,pid,uid);//如果没有该process,则生成该pid对应的PROC结构else{strcpy(this->comm,comm);this->uid=uid;}if(!(parent=find_proc(ppid)))parent=new_proc("?",ppid,0);//如果没有该ppid对应的process,则生成ppid对应的PROC结构…………………略add_child(parent,this);add_child()函数add_child(PROC*parent,PROC*child)CHILD*new,**walk;new=malloc(sizeof(CHILD))new->child=child;for(walk=&parent->children;*walk;walk=&(*walk)->next)//在该parent对应的children链中循环if((cmp=strcmp((*walk)->child->comm,child->comm))>0)break;elseif(!cmp&&(*walk)->child->uid>child->uid)break;new->next=*walk;*walk=new;//在children链中找到合适的位置将该child添加进去添加
:1.按children的command项的字母排序2.如果command相同,按children的uid从小到大排序三.dump_tree主要函数,将tree按规则输出dump_tree(PROC*current,intlevel,intrep,intleaf,intlast,uid_tprev_uid,intclosing)if(!leaf)…………输出一些符号if(rep>=2) out_string("*[") //即该PROC不止一个,有重复的for(here=current->comm;*here;here)………out_char(*here);……将该process对应的command输出if(print_args||!current->children)//该process没有children……..ut_char(']');……..else//该process有childrenfor(walk=current->children;walk;walk=next)count=0;next=walk->next;scan=&walk->next;while(*scan)if(!tree_equal(walk->child,(*scan)->child))//如果该child和parent的下一个child形成的tree并不equalscan=&(*scan)->next;else //如果tree是equal的{if(next==*scan)next=(*scan)->next;count; //count加,即
示该tree有多少*scan=(*scan)->next;……..dump_tree(walk->child,level1,count1,walk==current->children,!next,current->uid,closing(count?1:0));//递归调用dump_tree,dump该process的children四.改进需求:所有由supervise启动的程序,显示程序目录,gpid。Pstree在不加user显示的时候,出现init--2*[supervise---tncache---tncache---35*[tncache]]两个supervise并成一行改为分开显示思路:程序目录:/proc/number/exe符号链接,指向被执行的二进制代码.gpid:/proc/number/stat获取判断是否supervise启动:循环parent,找出是否直接或者间接parent的comand是supervise分开显示:改变dump_tree的时候,tree_equal的逻辑将parent是init进程,command是supervise,并且supervise所在的tree是equal的,按照原来非equal的逻辑处理。