From 3202d72f85d885cada39e01f7cdcc424365b91dc Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 13 Jan 2012 20:54:08 +0400 Subject: [PATCH] crtools: Parse /proc/pid/stat in a more readable way We will later need other fields of this file, so let's parse it right now in a way, that allows to easily get new fields. Signed-off-by: Pavel Emelyanov Signed-off-by: Cyrill Gorcunov --- cr-dump.c | 102 +++++++------------------------------------ include/proc_parse.h | 54 +++++++++++++++++++++++ proc_parse.c | 64 +++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 86 deletions(-) diff --git a/cr-dump.c b/cr-dump.c index ee8063c95..01eeca59a 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -434,6 +434,8 @@ err: #define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e #define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e)) +static struct proc_pid_stat pps_buf; + static int get_task_stat(pid_t pid, int pid_dir, u8 *comm, u32 *flags, u64 *start_code, u64 *end_code, u64 *start_data, u64 *end_data, @@ -441,101 +443,29 @@ static int get_task_stat(pid_t pid, int pid_dir, u8 *comm, u32 *flags, u64 *task_sigset) { FILE *file = NULL; - char *tok1, *tok2; - int i, ret = -1; + int ret; - /* - * NOTE: Be careful, /proc/$pid/stat has a parasite - * '0' symbol at argument 20 in format string. - */ - - file = fopen_proc(pid_dir, "stat"); - if (!file) { - pr_perror("Can't open %d stat\n", pid); + ret = parse_pid_stat(pid, pid_dir, &pps_buf); + if (ret < 0) goto err; - } - if (!fgets(loc_buf, sizeof(loc_buf), file)) { - perror("Can't read task stat"); - goto err; - } + strcpy((char *)comm, pps_buf.comm); + *flags = pps_buf.flags; + *start_code = pps_buf.start_code; + *end_code = pps_buf.end_code; + *start_data = pps_buf.start_data; + *end_data = pps_buf.end_data; + *start_stack = pps_buf.start_stack; + *start_brk = pps_buf.start_brk; - tok1 = strtok(loc_buf, "("); - tok2 = strtok(NULL, ")"); - if ((long)tok1 & (long)tok2) { - strncpy((char *)comm, tok2, TASK_COMM_LEN); - ret = 0; - } else { - printf("Unable to parse task stat\n"); - ret = -1; - } - - if (!ret) { - ret = -1; - for (i = 0; i < 7; i++) { - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - } - *flags = atoi(tok1); - ret = 0; - } - - if (!ret) { - ret = -1; - for (i = 0; i < 16; i++) { - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - } - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *start_code = atol(tok1); - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *end_code = atol(tok1); - ret = 0; - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *start_stack = atol(tok1); - ret = 0; - } - - if (!ret) { - ret = -1; - for (i = 0; i < 16; i++) { - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - } - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *start_data = atol(tok1); - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *end_data = atol(tok1); - - tok1 = strtok(NULL, " \n\t"); - if (!tok1) - goto err_corrupted; - *start_brk = atol(tok1); - ret = 0; + if (*start_data == 0 || *end_data == 0 || *start_brk == 0) { + pr_err("%d's stat is corrupted/not complete\n", pid); + goto err_corrupted; } /* * Now signals. */ - fclose(file); file = fopen_proc(pid_dir, "status"); if (!file) { pr_perror("Can't open %d status\n", pid); diff --git a/include/proc_parse.h b/include/proc_parse.h index 95d22bf4f..87c165647 100644 --- a/include/proc_parse.h +++ b/include/proc_parse.h @@ -1,4 +1,58 @@ #ifndef __PROC_PARSE_H__ #define __PROC_PARSE_H__ int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files); + +#define TASK_COMM_LEN 16 + +struct proc_pid_stat { + int pid; + char comm[TASK_COMM_LEN]; + char state; + int ppid; + int pgid; + int sid; + int tty_nr; + int tty_pgrp; + unsigned int flags; + unsigned long min_flt; + unsigned long cmin_flt; + unsigned long maj_flt; + unsigned long cmaj_flt; + unsigned long utime; + unsigned long stime; + long cutime; + long cstime; + long priority; + long nice; + int num_threads; + int zero0; + unsigned long long start_time; + unsigned long vsize; + long mm_rss; + unsigned long rsslim; + unsigned long start_code; + unsigned long end_code; + unsigned long start_stack; + unsigned long esp; + unsigned long eip; + unsigned long sig_pending; + unsigned long sig_blocked; + unsigned long sig_ignored; + unsigned long sig_handled; + unsigned long wchan; + unsigned long zero1; + unsigned long zero2; + int exit_signal; + int task_cpu; + unsigned int rt_priority; + unsigned int policy; + unsigned long long delayacct_blkio_ticks; + unsigned long gtime; + long cgtime; + unsigned long start_data; + unsigned long end_data; + unsigned long start_brk; +}; + +int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s); #endif diff --git a/proc_parse.c b/proc_parse.c index e70c91f4d..19b448829 100644 --- a/proc_parse.c +++ b/proc_parse.c @@ -172,3 +172,67 @@ err_bogus_mapping: goto err; } +int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s) +{ + FILE *f; + + f = fopen_proc(pid_dir, "stat"); + if (f == NULL) { + pr_perror("Can't open %d's stat", pid); + return -1; + } + + memset(s, 0, sizeof(*s)); + fscanf(f, "%d (%s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %d %d %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu", + &s->pid, + s->comm, + &s->state, + &s->ppid, + &s->pgid, + &s->sid, + &s->tty_nr, + &s->tty_pgrp, + &s->flags, + &s->min_flt, + &s->cmin_flt, + &s->maj_flt, + &s->cmaj_flt, + &s->utime, + &s->stime, + &s->cutime, + &s->cstime, + &s->priority, + &s->nice, + &s->num_threads, + &s->zero0, + &s->start_time, + &s->vsize, + &s->mm_rss, + &s->rsslim, + &s->start_code, + &s->end_code, + &s->start_stack, + &s->esp, + &s->eip, + &s->sig_pending, + &s->sig_blocked, + &s->sig_ignored, + &s->sig_handled, + &s->wchan, + &s->zero1, + &s->zero2, + &s->exit_signal, + &s->task_cpu, + &s->rt_priority, + &s->policy, + &s->delayacct_blkio_ticks, + &s->gtime, + &s->cgtime, + &s->start_data, + &s->end_data, + &s->start_brk); + + s->comm[strlen(s->comm) - 1] = '\0'; /* trim the ending ) */ + fclose(f); + return 0; +}