/**linux/fs/proc/array.c**Copyright(C)1992byLinusTorvalds*basedonideasbyDarrenSenn**Fixes:*Michael.K.Johnson:stat,statmextensions.*<johnsonm@stolaf.edu>**Pauline
Middelink:Madecmdline,envlineonlybreakat'\0's,to*makesureSETPROCTITLEworks.Alsoremoved*bad'!'whichforcedaddressrecalculationfor*EVERYcharacteronthecurrentpage.*<
middelin@polyware.iaf.nl>**DannyterHaar:addedcpuinfo*<dth@cistron.nl>**AlessandroRubini:profileextension.*<rubini@ipvvis.unipv.it>**JeffTranter:addedBogoMipsfiel
dtocpuinfo*<JeffTranter@Mitel.COM>**BrunoHaible:remove4Klimitforthemapsfile*<haible@ma2s2.mathematik.uni-karlsruhe.de>**YvesArrouye:removeremovaloftrailingspaces
ingetarray.*<Yves.Arrouye@marin.fdn.fr>**JeromeForissier:addedper-CPUtimeinformationto/proc/stat*and/proc/<pid>/cpuextension*<forissier@isia.cma.fr>*-Incorporati
onandnon-SMPsafeoperation*offorissierpatchin2.1.78by*HansMarcus<crowbar@concepts.nl>**aeb@cwi.nl:/proc/partitions***AlanCox:securityfixes.*<Alan.Cox@linux.org>**
GerhardWichert:addedBIGMEMsupport*SiemensAG<Gerhard.Wichert@pdb.siemens.de>*/#include<linux/types.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/
kernel.h>#include<linux/kernelstat.h>#include<linux/tty.h>#include<linux/user.h>#include<linux/a.out.h>#include<linux/string.h>#include<linux/mman.h>#include<lin
ux/procfs.h>#include<linux/ioport.h>#include<linux/config.h>#include<linux/mm.h>#include<linux/pagemap.h>#include<linux/swap.h>#include<linux/slab.h>#include<lin
ux/smp.h>#include<linux/signal.h>#include<asm/uaccess.h>#include<asm/pgtable.h>#include<asm/io.h>#defineLOADINT(x)((x)>>FSHIFT)#defineLOADFRAC(x)LOADINT(((x)&(FI
XED1-1))*100)#ifdefCONFIGDEBUGMALLOCintgetmalloc(char*buffer);#endifstaticintopenkcore(structinode*inode,structfile*filp){returncapable(CAPSYSRAWIO)?0:-EPERM;}st
aticssizetreadcore(structfile*file,char*buf,sizetcount,lofft*ppos){unsignedlongp=*ppos,memsize;ssizetread;ssizetcount1;char*pnt;structuserdump;#ifdefined(i386)||
defined(mc68000)#defineFIRSTMAPPEDPAGESIZE/*wedon'thavepage0mappedonx86..*/#else#defineFIRSTMAPPED0#endifmemset(&dump,0,sizeof(structuser));dump.magic=CMAGIC;dum
p.udsize=maxmapnr;#ifdefined(i386)dump.startcode=PAGEOFFSET;#endif#ifdefalphadump.startdata=PAGEOFFSET;#endifmemsize=(maxmapnr+1)<<PAGESHIFT;if(p>=memsize)return
0;if(count>memsize-p)count=memsize-p;read=0;if(p<sizeof(structuser)&&count>0){count1=count;if(p+count1>sizeof(structuser))count1=sizeof(structuser)-p;pnt=(char*)
&dump+p;copytouser(buf,(void*)pnt,count1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0&&p<PAGESIZE+FIRSTMAPPED){count1=PAGESIZE+FIRSTMAPPED-p;if(
count1>count)count1=count;clearuser(buf,count1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0){copytouser(buf,(void*)(PAGEOFFSET+p-PAGESIZE),count
);read+=count;}*ppos+=read;returnread;}staticstructfileoperationsprockcoreoperations={NULL,/*lseek*/readcore,NULL,/*write*/NULL,/*readdir*/NULL,/*poll*/NULL,/*io
ctl*/NULL,/*mmap*/openkcore};structinodeoperationsprockcoreinodeoperations={&prockcoreoperations,};/**Thisfunctionaccessesprofilinginformation.Thereturneddatais*
binary:thesamplingstepandtheactualcontentsoftheprofile*buffer.Useoftheprogramreadprofileisrecommendedinorderto*getmeaningfulinfooutofthesedata.*/staticssizetread
profile(structfile*file,char*buf,sizetcount,lofft*ppos){unsignedlongp=*ppos;ssizetread;char*pnt;unsignedintsamplestep=1<<profshift;if(p>=(proflen+1)*sizeof(unsig
nedint))return0;if(count>(proflen+1)*sizeof(unsignedint)-p)count=(proflen+1)*sizeof(unsignedint)-p;read=0;while(p<sizeof(unsignedint)&&count>0){putuser(*((char*)
(&samplestep)+p),buf);buf++;p++;count--;read++;}pnt=(char*)profbuffer+p-sizeof(unsignedint);copytouser(buf,(void*)pnt,count);read+=count;*ppos+=read;returnread;}
/**Writingto/proc/profileresetsthecounters**Writinga'profilingmultiplier'valueintoitalsore-setstheprofiling*interruptfrequency,onarchitecturesthatsupportthis.*/s
taticssizetwriteprofile(structfile*file,constchar*buf,sizetcount,lofft*ppos){#ifdefSMPexternintsetupprofilingtimer(unsignedintmultiplier);if(count==sizeof(int)){
unsignedintmultiplier;if(copyfromuser(&multiplier,buf,sizeof(int)))return-EFAULT;if(setupprofilingtimer(multiplier))return-EINVAL;}#endifmemset(profbuffer,0,prof
len*sizeof(*profbuffer));returncount;}staticstructfileoperationsprocprofileoperations={NULL,/*lseek*/readprofile,writeprofile,};structinodeoperationsprocprofilei
nodeoperations={&procprofileoperations,};staticintgetloadavg(char*buffer){inta,b,c;a=avenrun[0]+(FIXED1/200);b=avenrun[1]+(FIXED1/200);c=avenrun[2]+(FIXED1/200);
returnsprintf(buffer,"%d.%02d%d.%02d%d.%02d%d/%d%d\n",LOADINT(a),LOADFRAC(a),LOADINT(b),LOADFRAC(b),LOADINT(c),LOADFRAC(c),nrrunning,nrtasks,lastpid);}staticintg
etkstat(char*buffer){inti,len;unsignedsum=0;externunsignedlongtotalforks;unsignedlongticks;ticks=jiffies*smpnumcpus;#ifndefCONFIGARCHS390for(i=0;i<NRIRQS;i++)sum
+=kstatirqs(i);#endif#ifdefSMPlen=sprintf(buffer,"cpu%u%u%u%lu\n",kstat.cpuuser,kstat.cpunice,kstat.cpusystem,jiffies*smpnumcpus-(kstat.cpuuser+kstat.cpunice+kst
at.cpusystem));for(i=0;i<smpnumcpus;i++)len+=sprintf(buffer+len,"cpu%d%u%u%u%lu\n",i,kstat.percpuuser[cpulogicalmap(i)],kstat.percpunice[cpulogicalmap(i)],kstat.
percpusystem[cpulogicalmap(i)],jiffies-(kstat.percpuuser[cpulogicalmap(i)]\+kstat.percpunice[cpulogicalmap(i)]\+kstat.percpusystem[cpulogicalmap(i)]));len+=sprin
tf(buffer+len,"disk%u%u%u%u\n""diskrio%u%u%u%u\n""diskwio%u%u%u%u\n""diskrblk%u%u%u%u\n""diskwblk%u%u%u%u\n""page%u%u\n"#ifdefCONFIGARCHS390"swap%u%u\n""intr10",
#else"swap%u%u\n""intr%u",#endif#elselen=sprintf(buffer,"cpu%u%u%u%lu\n""disk%u%u%u%u\n""diskrio%u%u%u%u\n""diskwio%u%u%u%u\n""diskrblk%u%u%u%u\n""diskwblk%u%u%u
%u\n""page%u%u\n"#ifdefCONFIGARCHS390"swap%u%u\n""intr10",#else"swap%u%u\n""intr%u",#endifkstat.cpuuser,kstat.cpunice,kstat.cpusystem,ticks-(kstat.cpuuser+kstat.
cpunice+kstat.cpusystem),#endifkstat.dkdrive[0],kstat.dkdrive[1],kstat.dkdrive[2],kstat.dkdrive[3],kstat.dkdriverio[0],kstat.dkdriverio[1],kstat.dkdriverio[2],ks
tat.dkdriverio[3],kstat.dkdrivewio[0],kstat.dkdrivewio[1],kstat.dkdrivewio[2],kstat.dkdrivewio[3],kstat.dkdriverblk[0],kstat.dkdriverblk[1],kstat.dkdriverblk[2],
kstat.dkdriverblk[3],kstat.dkdrivewblk[0],kstat.dkdrivewblk[1],kstat.dkdrivewblk[2],kstat.dkdrivewblk[3],kstat.pgpgin,kstat.pgpgout,kstat.pswpin,#ifdefCONFIGARCH
S390kstat.pswpout);#elsekstat.pswpout,sum);for(i=0;i<NRIRQS;i++)len+=sprintf(buffer+len,"%u",kstatirqs(i));#endiflen+=sprintf(buffer+len,"\nctxt%u\n""btime%lu\n"
"processes%lu\n",kstat.contextswtch,xtime.tvsec-jiffies/HZ,totalforks);returnlen;}staticintgetuptime(char*buffer){unsignedlonguptime;unsignedlongidle;uptime=jiff
ies;idle=task[0]->times.tmsutime+task[0]->times.tmsstime;/*Theformulaforthefractionpartsreallyis((t*100)/HZ)%100,butthatwouldoverflowabouteveryfivedaysatHZ==100.
Thereforetheidentitya=(a/b)*b+a%bisusedsothatitiscalculatedas(((t/HZ)*100)+((t%HZ)*100)/HZ)%100.Thepartinfrontofthe'+'alwaysevaluatesas0(mod100).Alldivisionsinth
eaboveformulasaretruncating.ForHZbeingapowerof10,thecalculationssimplifytotheversioninthe#elsepart(iftheprintfformatisadaptedtothesamenumberofdigitsaszeroesinHZ.
*/#ifHZ!=100returnsprintf(buffer,"%lu.%02lu%lu.%02lu\n",uptime/HZ,(((uptime%HZ)*100)/HZ)%100,idle/HZ,(((idle%HZ)*100)/HZ)%100);#elsereturnsprintf(buffer,"%lu.%02
lu%lu.%02lu\n",uptime/HZ,uptime%HZ,idle/HZ,idle%HZ);#endif}staticintgetmeminfo(char*buffer){structsysinfoi;intlen;simeminfo(&i);siswapinfo(&i);len=sprintf(buffer
,"total:used:free:shared:buffers:cached:\n""Mem:%8lu%8lu%8lu%8lu%8lu%8lu\n""Swap:%8lu%8lu%8lu\n",i.totalram,i.totalram-i.freeram,i.freeram,i.sharedram,i.bufferra
m,pagecachesize*PAGESIZE,i.totalswap,i.totalswap-i.freeswap,i.freeswap);/**Taggedformat,foreasygreppingandexpansion.Theabovewillgoaway*eventually,oncethetoolshav
ebeenupdated.*/returnlen+sprintf(buffer+len,"MemTotal:%8lukB\n""MemFree:%8lukB\n""MemShared:%8lukB\n""Buffers:%8lukB\n""Cached:%8lukB\n""BigTotal:%8lukB\n""BigFr
ee:%8lukB\n""SwapTotal:%8lukB\n""SwapFree:%8lukB\n",i.totalram>>10,i.freeram>>10,i.sharedram>>10,i.bufferram>>10,pagecachesize<<(PAGESHIFT-10),i.totalbig>>10,i.f
reebig>>10,i.totalswap>>10,i.freeswap>>10);}staticintgetversion(char*buffer){externchar*linuxbanner;strcpy(buffer,linuxbanner);returnstrlen(buffer);}staticintget
cmdline(char*buffer){externcharsavedcommandline[];returnsprintf(buffer,"%s\n",savedcommandline);}staticunsignedlonggetphysaddr(structtaskstruct*p,unsignedlongptr
){pgdt*pagedir;pmdt*pagemiddle;ptetpte;if(!p||!p->mm||ptr>=TASKSIZE)return0;/*CheckforNULLpgd..shouldn'thappen!*/if(!p->mm->pgd){printk("getphysaddr:pid%dhasNULL
pgd!\n",p->pid);return0;}pagedir=pgdoffset(p->mm,ptr);if(pgdnone(*pagedir))return0;if(pgdbad(*pagedir)){printk("badpagedirectoryentry%08lx\n",pgdval(*pagedir));p
gdclear(pagedir);return0;}pagemiddle=pmdoffset(pagedir,ptr);if(pmdnone(*pagemiddle))return0;if(pmdbad(*pagemiddle)){printk("badpagemiddleentry%08lx\n",pmdval(*pa
gemiddle));pmdclear(pagemiddle);return0;}pte=*pteoffset(pagemiddle,ptr);if(!ptepresent(pte))return0;returnptepage(pte)+(ptr&~PAGEMASK);}#include<linux/bigmem.h>s
taticintgetarray(structtaskstruct*p,unsignedlongstart,unsignedlongend,char*buffer){unsignedlongaddr;intsize=0,result=0;charc;if(start>=end)returnresult;for(;;){a
ddr=getphysaddr(p,start);if(!addr)returnresult;addr=kmap(addr,KMREAD);do{c=*(char*)addr;if(!c)result=size;if(size<PAGESIZE)buffer[size++]=c;else{kunmap(addr,KMRE
AD);returnresult;}addr++;start++;if(!c&&start>=end){kunmap(addr,KMREAD);returnresult;}}while(addr&~PAGEMASK);kunmap(addr-1,KMREAD);}returnresult;}staticintgetenv
(intpid,char*buffer){structtaskstruct*p;readlock(&tasklistlock);p=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p||!
p->mm)return0;returngetarray(p,p->mm->envstart,p->mm->envend,buffer);}staticintgetarg(intpid,char*buffer){structtaskstruct*p;readlock(&tasklistlock);p=findtaskby
pid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p||!p->mm)return0;returngetarray(p,p->mm->argstart,p->mm->argend,buffer);}/**The
sebracketthesleepingfunctions..*/externvoidschedulingfunctionsstarthere(void);externvoidschedulingfunctionsendhere(void);#definefirstsched((unsignedlong)scheduli
ngfunctionsstarthere)#definelastsched((unsignedlong)schedulingfunctionsendhere)staticunsignedlonggetwchan(structtaskstruct*p){if(!p||p==current||p->state==TASKRU
NNING)return0;#ifdefined(i386){unsignedlongebp,esp,eip;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;esp=p->tss.esp;if(!stackpage||esp<stackpage||es
p>=8188+stackpage)return0;/*include/asm-i386/system.h:switchto()pushesebplast.*/ebp=*(unsignedlong*)esp;do{if(ebp<stackpage||ebp>=8188+stackpage)return0;eip=*(un
signedlong*)(ebp+4);if(eip<firstsched||eip>=lastsched)returneip;ebp=*(unsignedlong*)ebp;}while(count++<16);}#elifdefined(alpha)/**Thisonedependsontheframesizeofs
chedule().Doa*"disassschedule"ingdbtofindtheframesize.Also,the*codeassumesthatsleepon()followsimmediatelyafter*interruptiblesleepon()andthataddtimer()follows*imm
ediatelyafterinterruptiblesleep().Ugly,isn'tit?*Maybeaddingawchanfieldtotaskstructwouldbebetter,*afterall...*/{unsignedlongscheduleframe;unsignedlongpc;pc=thread
savedpc(&p->tss);if(pc>=firstsched&&pc<lastsched){scheduleframe=((unsignedlong*)p->tss.ksp)[6];return((unsignedlong*)scheduleframe)[12];}returnpc;}#elifdefined(m
ips)/**ThesamecommentasontheAlphaapplieshere,too...*/{unsignedlongscheduleframe;unsignedlongpc;pc=threadsavedpc(&p->tss);if(pc>=(unsignedlong)interruptiblesleepo
n&&pc<(unsignedlong)addtimer){scheduleframe=((unsignedlong*)(long)p->tss.reg30)[16];return(unsignedlong)((unsignedlong*)scheduleframe)[11];}returnpc;}#elifdefine
d(mc68000){unsignedlongfp,pc;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;fp=((structswitchstack*)p->tss.ksp)->a6;do{if(fp<stackpage+sizeof(structt
askstruct)||fp>=8184+stackpage)return0;pc=((unsignedlong*)fp)[1];/*FIXME:Thisdependsontheorderofthesefunctions.*/if(pc<firstsched||pc>=lastsched)returnpc;fp=*(un
signedlong*)fp;}while(count++<16);}#elifdefined(powerpc){unsignedlongip,sp;unsignedlongstackpage=(unsignedlong)p;intcount=0;sp=p->tss.ksp;do{sp=*(unsignedlong*)s
p;if(sp<stackpage||sp>=stackpage+8188)return0;if(count>0){ip=*(unsignedlong*)(sp+4);if(ip<firstsched||ip>=lastsched)returnip;}}while(count++<16);}#elifdefined(ar
m){unsignedlongfp,lr;unsignedlongstackpage;intcount=0;stackpage=4096+(unsignedlong)p;fp=getcssfp(&p->tss);do{if(fp<stackpage||fp>4092+stackpage)return0;lr=pcpoin
ter(((unsignedlong*)fp)[-1]);if(lr<firstsched||lr>lastsched)returnlr;fp=*(unsignedlong*)(fp-12);}while(count++<16);}#elifdefined(sparc){unsignedlongpc,fp,bias=0;
unsignedlongtaskbase=(unsignedlong)p;structregwindow*rw;intcount=0;#ifdefsparcv9bias=STACKBIAS;#endiffp=p->tss.ksp+bias;do{/*Bogusframepointer?*/if(fp<(taskbase+
sizeof(structtaskstruct))||fp>=(taskbase+(2*PAGESIZE)))break;rw=(structregwindow*)fp;pc=rw->ins[7];if(pc<firstsched||pc>=lastsched)returnpc;fp=rw->ins[6]+bias;}w
hile(++count<16);}#elifdefined(s390){unsignedlongksp,backchain,ip;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;ksp=p->tss.ksp;if(!stackpage||ksp<st
ackpage||ksp>=8188+stackpage)return0;backchain=(*(unsignedlong*)ksp)&0x7fffffff;do{if(backchain<stackpage||backchain>=8188+stackpage)return0;ip=(*(unsignedlong*)
(backchain+56))&0x7fffffff;if(ip<firstsched||ip>=lastsched)returnip;backchain=(*(unsignedlong*)backchain)&0x7fffffff;}while(count++<16);}#endifreturn0;}#ifdefine
d(i386)#defineKSTKEIP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1019])#defineKSTKESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1022])#elifdefined(a
lpha)/**Seearch/alpha/kernel/ptrace.cfordetails.*/#definePTREG(reg)(PAGESIZE-sizeof(structptregs)\+(long)&((structptregs*)0)->reg)#defineKSTKEIP(tsk)\(*(unsigned
long*)(PTREG(pc)+PAGESIZE+(unsignedlong)(tsk)))#defineKSTKESP(tsk)((tsk)==current?rdusp():(tsk)->tss.usp)#elifdefined(arm)#defineKSTKEIP(tsk)(((unsignedlong*)(40
96+(unsignedlong)(tsk)))[1022])#defineKSTKESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1020])#elifdefined(mc68000)#defineKSTKEIP(tsk)\({\unsignedlongeip=
0;\if((tsk)->tss.esp0>PAGESIZE&&\MAPNR((tsk)->tss.esp0)<maxmapnr)\eip=((structptregs*)(tsk)->tss.esp0)->pc;\eip;})#defineKSTKESP(tsk)((tsk)==current?rdusp():(tsk
)->tss.usp)#elifdefined(powerpc)#defineKSTKEIP(tsk)((tsk)->tss.regs->nip)#defineKSTKESP(tsk)((tsk)->tss.regs->gpr[1])#elifdefined(sparcv9)#defineKSTKEIP(tsk)((ts
k)->tss.kregs->tpc)#defineKSTKESP(tsk)((tsk)->tss.kregs->uregs[UREGFP])#elifdefined(sparc)#defineKSTKEIP(tsk)((tsk)->tss.kregs->pc)#defineKSTKESP(tsk)((tsk)->tss
.kregs->uregs[UREGFP])#elifdefined(mips)#definePTREG(reg)((long)&((structptregs*)0)->reg\-sizeof(structptregs))#defineKSTKTOS(tsk)((unsignedlong)(tsk)+KERNELSTAC
KSIZE-32)#defineKSTKEIP(tsk)(*(unsignedlong*)(KSTKTOS(tsk)+PTREG(cp0epc)))#defineKSTKESP(tsk)(*(unsignedlong*)(KSTKTOS(tsk)+PTREG(regs[29])))#elifdefined(s390)#d
efineKSTKEIP(tsk)((tsk)->tss.regs->psw.addr)#defineKSTKESP(tsk)((tsk)->tss.ksp)#endif/*Gccoptimizesaway"strlen(x)"forconstantx*/#defineADDBUF(buffer,string)\do{m
emcpy(buffer,string,strlen(string));\buffer+=strlen(string);}while(0)staticinlinechar*taskname(structtaskstruct*p,char*buf){inti;char*name;ADDBUF(buf,"Name:\t");
name=p->comm;i=sizeof(p->comm);do{unsignedcharc=*name;name++;i--;*buf=c;if(!c)break;if(c=='\\'){buf[1]=c;buf+=2;continue;}if(c=='\n'){buf[0]='\\';buf[1]='n';buf+
=2;continue;}buf++;}while(i);*buf='\n';returnbuf+1;}/**Thetaskstatearrayisastrange"bitmap"of*reasonstosleep.Thus"running"iszero,and*youcantestforcombinationsofot
herswith*simplebittests.*/staticconstchar*taskstatearray[]={"R(running)",/*0*/"S(sleeping)",/*1*/"D(disksleep)",/*2*/"Z(zombie)",/*4*/"T(stopped)",/*8*/"W(paging
)"/*16*/};staticinlineconstchar*gettaskstate(structtaskstruct*tsk){unsignedintstate=tsk->state&(TASKRUNNING|TASKINTERRUPTIBLE|TASKUNINTERRUPTIBLE|TASKZOMBIE|TASK
STOPPED|TASKSWAPPING);constchar**p=&taskstatearray[0];while(state){p++;state>>=1;}return*p;}staticinlinechar*taskstate(structtaskstruct*p,char*buffer){intg;buffe
r+=sprintf(buffer,"State:\t%s\n""Pid:\t%d\n""PPid:\t%d\n""Uid:\t%d\t%d\t%d\t%d\n""Gid:\t%d\t%d\t%d\t%d\n""Groups:\t",gettaskstate(p),p->pid,p->ppptr->pid,p->uid,
p->euid,p->suid,p->fsuid,p->gid,p->egid,p->sgid,p->fsgid);for(g=0;g<p->ngroups;g++)buffer+=sprintf(buffer,"%d",p->groups[g]);buffer+=sprintf(buffer,"\n");returnb
uffer;}staticinlinechar*taskmem(structtaskstruct*p,char*buffer){structmmstruct*mm=p->mm;if(mm&&mm!=&initmm){structvmareastruct*vma=mm->mmap;unsignedlongdata=0,st
ack=0;unsignedlongexec=0,lib=0;for(vma=mm->mmap;vma;vma=vma->vmnext){unsignedlonglen=(vma->vmend-vma->vmstart)>>10;if(!vma->vmfile){data+=len;if(vma->vmflags&VMG
ROWSDOWN)stack+=len;continue;}if(vma->vmflags&VMWRITE)continue;if(vma->vmflags&VMEXEC){exec+=len;if(vma->vmflags&VMEXECUTABLE)continue;lib+=len;}}buffer+=sprintf
(buffer,"VmSize:\t%8lukB\n""VmLck:\t%8lukB\n""VmRSS:\t%8lukB\n""VmData:\t%8lukB\n""VmStk:\t%8lukB\n""VmExe:\t%8lukB\n""VmLib:\t%8lukB\n",mm->totalvm<<(PAGESHIFT-
10),mm->lockedvm<<(PAGESHIFT-10),mm->rss<<(PAGESHIFT-10),data-stack,stack,exec-lib,lib);}returnbuffer;}staticvoidcollectsigignsigcatch(structtaskstruct*p,sigsett
*ign,sigsett*catch){structksigaction*k;inti;sigemptyset(ign);sigemptyset(catch);if(p->sig){k=p->sig->action;for(i=1;i<=NSIG;++i,++k){if(k->sa.sahandler==SIGIGN)s
igaddset(ign,i);elseif(k->sa.sahandler!=SIGDFL)sigaddset(catch,i);}}}staticinlinechar*tasksig(structtaskstruct*p,char*buffer){sigsettign,catch;buffer+=sprintf(bu
ffer,"SigPnd:\t");buffer=rendersigsett(&p->signal,buffer);*buffer++='\n';buffer+=sprintf(buffer,"SigBlk:\t");buffer=rendersigsett(&p->blocked,buffer);*buffer++='
\n';collectsigignsigcatch(p,&ign,&catch);buffer+=sprintf(buffer,"SigIgn:\t");buffer=rendersigsett(&ign,buffer);*buffer++='\n';buffer+=sprintf(buffer,"SigCgt:\t")
;/*Linux2.0uses"SigCgt"*/buffer=rendersigsett(&catch,buffer);*buffer++='\n';returnbuffer;}externinlinechar*taskcap(structtaskstruct*p,char*buffer){returnbuffer+s
printf(buffer,"CapInh:\t%016x\n""CapPrm:\t%016x\n""CapEff:\t%016x\n",capt(p->capinheritable),capt(p->cappermitted),capt(p->capeffective));}staticintgetstatus(int
pid,char*buffer){char*orig=buffer;structtaskstruct*tsk;readlock(&tasklistlock);tsk=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthe
lastuse*/if(!tsk)return0;buffer=taskname(tsk,buffer);buffer=taskstate(tsk,buffer);buffer=taskmem(tsk,buffer);buffer=tasksig(tsk,buffer);buffer=taskcap(tsk,buffer
);#ifs390buffer=taskshowregs(tsk,buffer);#endifreturnbuffer-orig;}staticintgetstat(intpid,char*buffer){structtaskstruct*tsk;unsignedlongvsize,eip,esp,wchan;longp
riority,nice;intttypgrp;sigsettsigign,sigcatch;charstate;readlock(&tasklistlock);tsk=findtaskbypid(pid);if(!tsk){readunlock(&tasklistlock);return0;}state=*gettas
kstate(tsk);vsize=eip=esp=0;if(tsk->mm&&tsk->mm!=&initmm){structvmareastruct*vma=tsk->mm->mmap;while(vma){vsize+=vma->vmend-vma->vmstart;vma=vma->vmnext;}if((cur
rent->fsuid==tsk->euid&&tsk->dumpable&&capissubset(tsk->cappermitted,current->cappermitted))||capable(CAPDACOVERRIDE)){eip=KSTKEIP(tsk);esp=KSTKESP(tsk);}}readun
lock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/wchan=getwchan(tsk);collectsigignsigcatch(tsk,&sigign,&sigcatch);if(tsk->tty)ttypgrp=tsk->tty->pgrp
;elsettypgrp=-1;/*scalepriorityandnicevaluesfromtimeslicesto-20..20*//*tomakeitlooklikea"normal"Unixpriority/nicevalue*/priority=tsk->counter;priority=20-(priori
ty*10+DEFPRIORITY/2)/DEFPRIORITY;nice=tsk->priority;nice=20-(nice*20+DEFPRIORITY/2)/DEFPRIORITY;returnsprintf(buffer,"%d(%s)%c%d%d%d%d%d%lu%lu\%lu%lu%lu%lu%lu%ld
%ld%ld%ld%ld%ld%lu%lu%ld%lu%lu%lu%lu%lu\%lu%lu%lu%lu%lu%lu%lu%lu%d%d\n",pid,tsk->comm,state,tsk->ppptr->pid,tsk->pgrp,tsk->session,tsk->tty?kdevttonr(tsk->tty->d
evice):0,ttypgrp,tsk->flags,tsk->minflt,tsk->cminflt,tsk->majflt,tsk->cmajflt,tsk->times.tmsutime,tsk->times.tmsstime,tsk->times.tmscutime,tsk->times.tmscstime,p
riority,nice,0UL/*removed*/,tsk->itrealvalue,tsk->starttime,vsize,tsk->mm?tsk->mm->rss:0,/*youmightwanttoshiftthisleft3*/tsk->rlim?tsk->rlim[RLIMITRSS].rlimcur:0
,tsk->mm?tsk->mm->startcode:0,tsk->mm?tsk->mm->endcode:0,tsk->mm?tsk->mm->startstack:0,esp,eip,/*Thesignalinformationhereisobsolete.*ItmustbedecimalforLinux2.0co
mpatibility.*Use/proc/#/statusforreal-timesignals.*/tsk->signal.sig[0]&0x7fffffffUL,tsk->blocked.sig[0]&0x7fffffffUL,sigign.sig[0]&0x7fffffffUL,sigcatch.sig[0]&0
x7fffffffUL,wchan,tsk->nswap,tsk->cnswap,tsk->exitsignal,tsk->processor);}staticinlinevoidstatmpterange(pmdt*pmd,unsignedlongaddress,unsignedlongsize,int*pages,i
nt*shared,int*dirty,int*total){ptet*pte;unsignedlongend;if(pmdnone(*pmd))return;if(pmdbad(*pmd)){printk("statmpterange:badpmd(%08lx)\n",pmdval(*pmd));pmdclear(pm
d);return;}pte=pteoffset(pmd,address);address&=~PMDMASK;end=address+size;if(end>PMDSIZE)end=PMDSIZE;do{ptetpage=*pte;address+=PAGESIZE;pte++;if(ptenone(page))con
tinue;++*total;if(!ptepresent(page))continue;++*pages;if(ptedirty(page))++*dirty;if(MAPNR(ptepage(page))>=maxmapnr)continue;if(atomicread(&memmap[MAPNR(ptepage(p
age))].count)>1)++*shared;}while(address<end);}staticinlinevoidstatmpmdrange(pgdt*pgd,unsignedlongaddress,unsignedlongsize,int*pages,int*shared,int*dirty,int*tot
al){pmdt*pmd;unsignedlongend;if(pgdnone(*pgd))return;if(pgdbad(*pgd)){printk("statmpmdrange:badpgd(%08lx)\n",pgdval(*pgd));pgdclear(pgd);return;}pmd=pmdoffset(pg
d,address);address&=~PGDIRMASK;end=address+size;if(end>PGDIRSIZE)end=PGDIRSIZE;do{statmpterange(pmd,address,end-address,pages,shared,dirty,total);address=(addres
s+PMDSIZE)&PMDMASK;pmd++;}while(address<end);}staticvoidstatmpgdrange(pgdt*pgd,unsignedlongaddress,unsignedlongend,int*pages,int*shared,int*dirty,int*total){whil
e(address<end){statmpmdrange(pgd,address,end-address,pages,shared,dirty,total);address=(address+PGDIRSIZE)&PGDIRMASK;pgd++;}}staticintgetstatm(intpid,char*buffer
){structtaskstruct*tsk;intsize=0,resident=0,share=0,trs=0,lrs=0,drs=0,dt=0;readlock(&tasklistlock);tsk=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!This
shouldbedoneafterthelastuse*/if(!tsk)return0;if(tsk->mm&&tsk->mm!=&initmm){structvmareastruct*vma=tsk->mm->mmap;while(vma){pgdt*pgd=pgdoffset(tsk->mm,vma->vmstar
t);intpages=0,shared=0,dirty=0,total=0;statmpgdrange(pgd,vma->vmstart,vma->vmend,&pages,&shared,&dirty,&total);resident+=pages;share+=shared;dt+=dirty;size+=tota
l;if(vma->vmflags&VMEXECUTABLE)trs+=pages;/*text*/elseif(vma->vmflags&VMGROWSDOWN)drs+=pages;/*stack*/elseif(vma->vmend>0x60000000)lrs+=pages;/*library*/elsedrs+
=pages;vma=vma->vmnext;}}returnsprintf(buffer,"%d%d%d%d%d%d%d\n",size,resident,share,trs,lrs,drs,dt);}/**Thewaywesupportsyntheticfiles>4K*-withoutstoringtheircon
tentsinsomebufferand*-withoutwalkingthroughtheentiresyntheticfileuntilwereachthe*positionoftherequesteddata*istocleverlyencodethecurrentpositioninthefile'sfposfi
eld.*Thereisnorequirementthataread()callwhichreturns`count'bytes*ofdataincreasesfposbyexactly`count'.**ThisideaisLinus'one.Brunoimplementedit.*//**Forthe/proc/<p
id>/mapsfile,weusefixedlengthrecords,eachcontaining*asingleline.*/#defineMAPSLINELENGTH4096#defineMAPSLINESHIFT12/**fpos=(numberofthevmainthetask->mm->mmaplist)*
MAPSLINELENGTH*+(indexintotheline)*//*forsystemswithsizeof(void*)==4:*/#defineMAPSLINEFORMAT4"%08lx-%08lx%s%08lx%s%lu"#defineMAPSLINEMAX449/*sumof8181418151101*/
/*forsystemswithsizeof(void*)==8:*/#defineMAPSLINEFORMAT8"%016lx-%016lx%s%016lx%s%lu"#defineMAPSLINEMAX873/*sumof1611614116151101*/#defineMAPSLINEMAXMAPSLINEMAX8
staticssizetreadmaps(intpid,structfile*file,char*buf,sizetcount,lofft*ppos){structtaskstruct*p;structvmareastruct*map,*next;char*destptr=buf,*buffer;lofftlineno;
ssizetcolumn,i;intvolatiletask;longretval;/**Wemightsleepgettingthepage,sogetitfirst.*/retval=-ENOMEM;buffer=(char*)getfreepage(GFPKERNEL);if(!buffer)gotoout;ret
val=-EINVAL;readlock(&tasklistlock);p=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p)gotofreepageout;if(!p->mm||p->
mm==&initmm||count==0)gotogetlenout;/*Checkwhetherthemmapscouldchangeifwesleep*/volatiletask=(p!=current||atomicread(&p->mm->count)>1);/*decodefpos*/lineno=*ppos
>>MAPSLINESHIFT;column=*ppos&(MAPSLINELENGTH-1);/*quicklygotolinelineno*/for(map=p->mm->mmap,i=0;map&&(i<lineno);map=map->vmnext,i++)continue;for(;map;map=next){
/*producethenextline*/char*line;charstr[5],*cp=str;intflags;kdevtdev;unsignedlongino;intmaxlen=(sizeof(void*)==4)?MAPSLINEMAX4:MAPSLINEMAX8;intlen;/**Getthenextv
manow(butitwon'tbeusedifwesleep).*/next=map->vmnext;flags=map->vmflags;*cp++=flags&VMREAD?'r':'-';*cp++=flags&VMWRITE?'w':'-';*cp++=flags&VMEXEC?'x':'-';*cp++=fl
ags&VMMAYSHARE?'s':'p';*cp++=0;dev=0;ino=0;if(map->vmfile!=NULL){dev=map->vmfile->fdentry->dinode->idev;ino=map->vmfile->fdentry->dinode->iino;line=dpath(map->vm
file->fdentry,buffer,PAGESIZE);buffer[PAGESIZE-1]='\n';line-=maxlen;if(line<buffer)line=buffer;}elseline=buffer;len=sprintf(line,sizeof(void*)==4?MAPSLINEFORMAT4
:MAPSLINEFORMAT8,map->vmstart,map->vmend,str,map->vmoffset,kdevname(dev),ino);if(map->vmfile){for(i=len;i<maxlen;i++)line[i]='';len=buffer+PAGESIZE-line;}elselin
e[len++]='\n';if(column>=len){column=0;/*continuewithnextlineatcolumn0*/lineno++;continue;/*wehaven'tslept*/}i=len-column;if(i>count)i=count;copytouser(destptr,l
ine+column,i);/*mayhaveslept*/destptr+=i;count-=i;column+=i;if(column>=len){column=0;/*nexttime:nextlineatcolumn0*/lineno++;}/*done?*/if(count==0)break;/*Bywriti
ngtouserspace,wemighthaveslept.*Stoptheloop,toavoidaracecondition.*/if(volatiletask)break;}/*encodefpos*/*ppos=(lineno<<MAPSLINESHIFT)+column;getlenout:retval=de
stptr-buf;freepageout:freepage((unsignedlong)buffer);out:returnretval;}#ifdefSMPstaticintgetpidcpu(intpid,char*buffer){structtaskstruct*tsk=current;inti,len;read
lock(&tasklistlock);if(pid!=tsk->pid)tsk=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(tsk==NULL)return0;len=sprintf(
buffer,"cpu%lu%lu\n",tsk->times.tmsutime,tsk->times.tmsstime);for(i=0;i<smpnumcpus;i++)len+=sprintf(buffer+len,"cpu%d%lu%lu\n",i,tsk->percpuutime[cpulogicalmap(i
)],tsk->percpustime[cpulogicalmap(i)]);returnlen;}#endif#ifdefCONFIGMODULESexternintgetmodulelist(char*);externintgetksymslist(char*,char**,offt,int);#endifexter
nintgetdevicelist(char*);externintgetpartitionlist(char*,char**,offt,int);externintgetfilesystemlist(char*);externintgetfilesysteminfo(char*);#ifndefCONFIGARCHS3
90externintgetirqlist(char*);#endifexternintgetdmalist(char*);externintgetcpuinfo(char*);externintgetpcilist(char*);externintgetmdstatus(char*);externintgetrtcst
atus(char*);externintgetlocksstatus(char*,char**,offt,int);externintgetswapareainfo(char*);externintgethardwarelist(char*);externintgetstramlist(char*);staticlon
ggetrootarray(char*page,inttype,char**start,offtoffset,unsignedlonglength){switch(type){casePROCLOADAVG:returngetloadavg(page);casePROCUPTIME:returngetuptime(pag
e);casePROCMEMINFO:returngetmeminfo(page);#ifdefCONFIGPCIOLDPROCcasePROCPCI:returngetpcilist(page);#endif#ifdefCONFIGNUBUScasePROCNUBUS:returngetnubuslist(page);
#endifcasePROCCPUINFO:returngetcpuinfo(page);casePROCVERSION:returngetversion(page);#ifdefCONFIGDEBUGMALLOCcasePROCMALLOC:returngetmalloc(page);#endif#ifdefCONFI
GMODULEScasePROCMODULES:returngetmodulelist(page);casePROCKSYMS:returngetksymslist(page,start,offset,length);#endifcasePROCSTAT:returngetkstat(page);casePROCSLAB
INFO:returngetslabinfo(page);casePROCDEVICES:returngetdevicelist(page);casePROCPARTITIONS:returngetpartitionlist(page,start,offset,length);#ifndefCONFIGARCHS390c
asePROCINTERRUPTS:returngetirqlist(page);#endifcasePROCFILESYSTEMS:returngetfilesystemlist(page);#ifndefCONFIGARCHS390casePROCDMA:returngetdmalist(page);#endifca
sePROCIOPORTS:returngetioportlist(page);#ifdefCONFIGBLKDEVMDcasePROCMD:returngetmdstatus(page);#endifcasePROCCMDLINE:returngetcmdline(page);casePROCMTAB:returnge
tfilesysteminfo(page);casePROCSWAP:returngetswapareainfo(page);#ifdefCONFIGRTCcasePROCRTC:returngetrtcstatus(page);#endif#ifdefCONFIGSGIDS1286casePROCRTC:returng
etds1286status(page);#endifcasePROCLOCKS:returngetlocksstatus(page,start,offset,length);#ifdefCONFIGPROCHARDWAREcasePROCHARDWARE:returngethardwarelist(page);#end
if#ifdefCONFIGSTRAMPROCcasePROCSTRAM:returngetstramlist(page);#endif}return-EBADF;}staticintprocessunauthorized(inttype,intpid){structtaskstruct*p;uidteuid=0;/*S
avetheeuidkeepthelockshort*/intok=0;readlock(&tasklistlock);/**Grabthelock,findthetask,savetheuidand*checkithasanmmstill(ieitsnotdead)*/p=findtaskbypid(pid);if(p
){euid=p->euid;ok=p->dumpable;if(!capissubset(p->cappermitted,current->cappermitted))ok=0;if(!p->mm)/*Scoobyscoobydoowhereareyou?*/p=NULL;}readunlock(&tasklistlo
ck);if(!p)return1;switch(type){casePROCPIDSTATUS:casePROCPIDSTATM:casePROCPIDSTAT:casePROCPIDMAPS:casePROCPIDCMDLINE:casePROCPIDCPU:return0;}if((current->fsuid==
euid&&ok)||capable(CAPDACOVERRIDE))return0;return1;}staticintgetprocessarray(char*page,intpid,inttype){switch(type){casePROCPIDSTATUS:returngetstatus(pid,page);c
asePROCPIDENVIRON:returngetenv(pid,page);casePROCPIDCMDLINE:returngetarg(pid,page);casePROCPIDSTAT:returngetstat(pid,page);casePROCPIDSTATM:returngetstatm(pid,pa
ge);#ifdefSMPcasePROCPIDCPU:returngetpidcpu(pid,page);#endif}return-EBADF;}staticinlineintfillarray(char*page,intpid,inttype,char**start,offtoffset,intlength){if
(pid)returngetprocessarray(page,pid,type);returngetrootarray(page,type,start,offset,length);}#definePROCBLOCKSIZE(3*1024)/*4Kpagesizebutouroutputroutinesusesomes
lackforoverruns*/staticssizetarrayread(structfile*file,char*buf,sizetcount,lofft*ppos){structinode*inode=file->fdentry->dinode;unsignedlongpage;char*start;ssizet
length;ssizetend;unsignedinttype,pid;structprocdirentry*dp;if(count>PROCBLOCKSIZE)count=PROCBLOCKSIZE;if(!(page=getfreepage(GFPKERNEL)))return-ENOMEM;type=inode-
>iino;pid=type>>16;type&=0x0000ffff;start=NULL;dp=(structprocdirentry*)inode->u.genericip;if(pid&&processunauthorized(type,pid)){freepage(page);return-EIO;}if(dp
->getinfo)length=dp->getinfo((char*)page,&start,*ppos,count,0);elselength=fillarray((char*)page,pid,type,&start,*ppos,count);if(length<0){freepage(page);returnle
ngth;}if(start!=NULL){/*Wehavehadblock-adjustingprocessing!*/copytouser(buf,start,length);*ppos+=length;count=length;}else{/*Static4kB(orwhatever)blockcapacity*/
if(*ppos>=length){freepage(page);return0;}if(count+*ppos>length)count=length-*ppos;end=count+*ppos;copytouser(buf,(char*)page+*ppos,count);*ppos=end;}freepage(pa
ge);returncount;}staticstructfileoperationsprocarrayoperations={NULL,/*arraylseek*/arrayread,NULL,/*arraywrite*/NULL,/*arrayreaddir*/NULL,/*arraypoll*/NULL,/*arr
ayioctl*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};structinodeoperationsprocarrayinodeoperations={&pr
ocarrayoperations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mk
nod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*followlink*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};staticssizetarraylon
gread(structfile*file,char*buf,sizetcount,lofft*ppos){structinode*inode=file->fdentry->dinode;unsignedintpid=inode->iino>>16;unsignedinttype=inode->iino&0x0000ff
ff;switch(type){casePROCPIDMAPS:returnreadmaps(pid,file,buf,count,ppos);}return-EINVAL;}staticstructfileoperationsprocarraylongoperations={NULL,/*arraylseek*/arr
aylongread,NULL,/*arraywrite*/NULL,/*arrayreaddir*/NULL,/*arraypoll*/NULL,/*arrayioctl*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialrele
asecode*/NULL/*can'tfsync*/};structinodeoperationsprocarraylonginodeoperations={&procarraylongoperations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/NULL,/*lo
okup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*followlink*/NULL,/*readpage*/N
ULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};/**linux/fs/proc/base.c**Copyright(C)1991,1992LinusTorvalds**procbasedirectoryhandlingfunction
s*/#include<asm/uaccess.h>#include<linux/config.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/procfs.h>#include<linux/stat.h>#include<linux/init
.h>staticstructfileoperationsprocbaseoperations={NULL,/*lseek-default*/NULL,/*read-bad*/NULL,/*write-bad*/procreaddir,/*readdir*/NULL,/*poll-default*/NULL,/*ioct
l-default*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};/**procdirectoriescandoalmostnothing..*/staticst
ructinodeoperationsprocbaseinodeoperations={&procbaseoperations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/proclookup,/*lookup*/NULL,/*link*/NULL,/*unlink*/N
ULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*followlink*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,
/*truncate*/NULL/*permission*/};/**Thefillargumentisnon-zerowhentheinodeisbeingfilled...*wedon'tneedtodoanythingwhenit'sbeingdeleted.*/staticvoidprocpidfillinode
(structinode*inode,intfill){structtaskstruct*p;intpid=inode->iino>>16;intino=inode->iino&0xffff;readlock(&tasklistlock);if(fill&&(p=findtaskbypid(pid))!=NULL){ui
dtuid=0;gidtgid=0;if(p->dumpable||ino==PROCPIDINO){uid=p->euid;gid=p->egid;}inode->iuid=uid;inode->igid=gid;}readunlock(&tasklistlock);}/**Thisisreallyapseudo-en
try,andonlylinks*backwardstotheparentwithnolinkfromthe*rootdirectorytothis.Thiswaywecanhavejust*oneentryforevery/proc/<pid>/directory.*/structprocdirentryprocpid
={PROCPIDINO,5,"<pid>",SIFDIR|SIRUGO|SIXUGO,2,0,0,0,&procbaseinodeoperations,NULL,procpidfillinode,NULL,&procroot,NULL};staticstructprocdirentryprocpidstatus={PR
OCPIDSTATUS,6,"status",SIFREG|SIRUGO,1,0,0,0,&procarrayinodeoperations,NULL,procpidfillinode,};staticstructprocdirentryprocpidmem={PROCPIDMEM,3,"mem",SIFREG|SIRU

Hosted by uCoz