📄 array.c
字号:
int count = 0;
stack_page = p->kernel_stack_page;
if (!stack_page)
return 0;
ebp = p->tss.ebp;
do {
if (ebp < stack_page || ebp >= 4092+stack_page)
return 0;
eip = *(unsigned long *) (ebp+4);
if (eip < (unsigned long) interruptible_sleep_on
|| eip >= (unsigned long) add_timer)
return eip;
ebp = *(unsigned long *) ebp;
} while (count++ < 16);
}
#elif defined(__alpha__)
/*
* This one depends on the frame size of schedule(). Do a
* "disass schedule" in gdb to find the frame size. Also, the
* code assumes that sleep_on() follows immediately after
* interruptible_sleep_on() and that add_timer() follows
* immediately after interruptible_sleep(). Ugly, isn't it?
* Maybe adding a wchan field to task_struct would be better,
* after all...
*/
{
unsigned long schedule_frame;
unsigned long pc;
pc = thread_saved_pc(&p->tss);
if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
schedule_frame = ((unsigned long *)p->tss.ksp)[6];
return ((unsigned long *)schedule_frame)[12];
}
return pc;
}
#endif
return 0;
}
#if defined(__i386__)
# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
#elif defined(__alpha__)
/*
* See arch/alpha/kernel/ptrace.c for details.
*/
# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
+ (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
#elif defined(__sparc__)
# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
+ (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(u_regs[UREG_FP])))
#endif
/* Gcc optimizes away "strlen(x)" for constant x */
#define ADDBUF(buffer, string) \
do { memcpy(buffer, string, strlen(string)); \
buffer += strlen(string); } while (0)
static inline char * task_name(struct task_struct *p, char * buf)
{
int i;
char * name;
ADDBUF(buf, "Name:\t");
name = p->comm;
i = sizeof(p->comm);
do {
unsigned char c = *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';
return buf+1;
}
static inline char * task_state(struct task_struct *p, char *buffer)
{
#define NR_STATES (sizeof(states)/sizeof(const char *))
unsigned int n = p->state;
static const char * states[] = {
"R (running)",
"S (sleeping)",
"D (disk sleep)",
"Z (zombie)",
"T (stopped)",
"W (paging)",
". Huh?"
};
if (n >= NR_STATES)
n = NR_STATES-1;
buffer += 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",
states[n],
p->pid, p->p_pptr->pid,
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid);
return buffer;
}
static inline char * task_mem(struct task_struct *p, char *buffer)
{
#ifndef NO_MM
struct mm_struct * mm = p->mm;
if (mm && mm != &init_mm) {
struct vm_area_struct * vma = mm->mmap;
unsigned long data = 0, stack = 0;
unsigned long exec = 0, lib = 0;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
if (!vma->vm_inode) {
data += len;
if (vma->vm_flags & VM_GROWSDOWN)
stack += len;
continue;
}
if (vma->vm_flags & VM_WRITE)
continue;
if (vma->vm_flags & VM_EXEC) {
exec += len;
if (vma->vm_flags & VM_EXECUTABLE)
continue;
lib += len;
}
}
buffer += sprintf(buffer,
"VmSize:\t%8lu kB\n"
"VmLck:\t%8lu kB\n"
"VmRSS:\t%8lu kB\n"
"VmData:\t%8lu kB\n"
"VmStk:\t%8lu kB\n"
"VmExe:\t%8lu kB\n"
"VmLib:\t%8lu kB\n",
mm->total_vm << (PAGE_SHIFT-10),
mm->locked_vm << (PAGE_SHIFT-10),
mm->rss << (PAGE_SHIFT-10),
data - stack, stack,
exec - lib, lib);
}
#else /* NO_MM */
unsigned long bytes = 0, sbytes = 0;
struct mm_tblock_struct * tblock;
/* Logic: we've got two memory sums for each process, "shared", and
* "non-shared". Shared memory may get counted more then once, for
* each process that owns it. Non-shared memory is counted
* accurately.
*
* -- Kenneth Albanowski
*/
for(tblock = &p->mm->tblock;tblock;tblock=tblock->next) {
if (tblock->rblock) {
bytes += ksize(tblock);
if ((p->mm->count > 1) || (tblock->rblock->refcount > 1)) {
sbytes += ksize(tblock->rblock->kblock);
sbytes += ksize(tblock->rblock) ;
} else {
bytes += ksize(tblock->rblock->kblock);
bytes += ksize(tblock->rblock) ;
}
}
}
((p->mm->count > 1) ? sbytes : bytes) += ksize(p->mm);
((p->fs->count > 1) ? sbytes : bytes) += ksize(p->fs);
((p->files->count > 1) ? sbytes : bytes) += ksize(p->files);
((p->sig->count > 1) ? sbytes : bytes) += ksize(p->sig);
bytes += ksize(p);
bytes += PAGE_SIZE; /* Kernel stack */
buffer += sprintf(buffer,
"Mem:\t%8lu bytes\n"
"Shared:\t%8lu bytes\n",
bytes,
sbytes);
#endif /* NO_MM */
return buffer;
}
static inline char * task_sig(struct task_struct *p, char *buffer)
{
buffer += sprintf(buffer,
"SigPnd:\t%08lx\n"
"SigBlk:\t%08lx\n",
p->signal, p->blocked);
if (p->sig) {
struct sigaction * action = p->sig->action;
unsigned long sig_ign = 0, sig_caught = 0;
unsigned long bit = 1;
int i;
for (i = 0; i < 32; i++) {
switch((unsigned long) action->sa_handler) {
case 0:
break;
case 1:
sig_ign |= bit;
break;
default:
sig_caught |= bit;
}
bit <<= 1;
action++;
}
buffer += sprintf(buffer,
"SigIgn:\t%08lx\n"
"SigCgt:\t%08lx\n",
sig_ign, sig_caught);
}
return buffer;
}
static int get_status(int pid, char * buffer)
{
char * orig = buffer;
struct task_struct ** p = get_task(pid), *tsk;
if (!p || (tsk = *p) == NULL)
return 0;
buffer = task_name(tsk, buffer);
buffer = task_state(tsk, buffer);
buffer = task_mem(tsk, buffer);
buffer = task_sig(tsk, buffer);
return buffer - orig;
}
static int get_stat(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid), *tsk;
unsigned long sigignore=0, sigcatch=0, wchan;
unsigned long vsize, eip, esp;
long priority, nice;
int i,tty_pgrp;
char state;
if (!p || (tsk = *p) == NULL)
return 0;
if (tsk->state < 0 || tsk->state > 5)
state = '.';
else
state = "RSDZTW"[tsk->state];
vsize = eip = esp = 0;
if (tsk->mm && tsk->mm != &init_mm) {
#ifndef NO_MM
struct vm_area_struct *vma = tsk->mm->mmap;
while (vma) {
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
if (tsk->kernel_stack_page) {
eip = KSTK_EIP(tsk);
esp = KSTK_ESP(tsk);
}
#endif /* !NO_MM */
}
wchan = get_wchan(tsk);
if (tsk->sig) {
unsigned long bit = 1;
for(i=0; i<32; ++i) {
switch((unsigned long) tsk->sig->action[i].sa_handler) {
case 0:
break;
case 1:
sigignore |= bit;
break;
default:
sigcatch |= bit;
}
bit <<= 1;
}
}
if (tsk->tty)
tty_pgrp = tsk->tty->pgrp;
else
tty_pgrp = -1;
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" unix priority/nice value */
priority = tsk->counter;
priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
nice = tsk->priority;
nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
return sprintf(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\n",
pid,
tsk->comm,
state,
tsk->p_pptr->pid,
tsk->pgrp,
tsk->session,
tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
tty_pgrp,
tsk->flags,
tsk->min_flt,
tsk->cmin_flt,
tsk->maj_flt,
tsk->cmaj_flt,
tsk->utime,
tsk->stime,
tsk->cutime,
tsk->cstime,
priority,
nice,
tsk->timeout,
tsk->it_real_value,
tsk->start_time,
vsize,
tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left 3 */
tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
tsk->mm ? tsk->mm->start_code : 0,
tsk->mm ? tsk->mm->end_code : 0,
tsk->mm ? tsk->mm->start_stack : 0,
esp,
eip,
tsk->signal,
tsk->blocked,
sigignore,
sigcatch,
wchan,
tsk->nswap,
tsk->cnswap);
}
#ifndef NO_MM
static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
int * pages, int * shared, int * dirty, int * total)
{
pte_t * pte;
unsigned long end;
if (pmd_none(*pmd))
return;
if (pmd_bad(*pmd)) {
printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
pmd_clear(pmd);
return;
}
pte = pte_offset(pmd, address);
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
pte_t page = *pte;
address += PAGE_SIZE;
pte++;
if (pte_none(page))
continue;
++*total;
if (!pte_present(page))
continue;
++*pages;
if (pte_dirty(page))
++*dirty;
if (pte_page(page) >= high_memory)
continue;
if (mem_map[MAP_NR(pte_page(page))].count > 1)
++*shared;
} while (address < end);
}
static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
int * pages, int * shared, int * dirty, int * total)
{
pmd_t * pmd;
unsigned long end;
if (pgd_none(*pgd))
return;
if (pgd_bad(*pgd)) {
printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
pgd_clear(pgd);
return;
}
pmd = pmd_offset(pgd, address);
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
do {
statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
}
static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
int * pages, int * shared, int * dirty, int * total)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -