通过/proc目录可以获取所有的进程信息。
需要注意的是 readlink系统调用不会追加0到字符串结尾,并且字符串的最大长度需要时读取长度+1,便于添加0结束字符串。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
typedef struct {
int Pid;
int Ppid;
char Name[128];
char Username[32];
int Effecitveuid;
char Exe[128];
char Cmdline[1024];
char Fd[1024];
}proc ;
proc g_proc;
static inline char* next_line( char *str ) {
int i = 0;
while( str[i] != '\n' ) {
if( str[i] == 0 ) {
return str+i;
}
i++;
}
i++; //skip the char '\n'
return str+i;
}
proc* get_proc( int pid )
{
char filename[128];
char buff[1024];
char key[16];
char val0[16], val1[16], val2[16], val3[16];
int str_len;
FILE *fp;
int i, count;
int ret;
proc* p = &g_proc;
struct passwd *pws;
sprintf(filename, "/proc/%d/status", pid);
fp = fopen(filename, "r");
if( fp != NULL ){
str_len = fread(buff, 1, 1024, fp);
if( str_len > 0) {
char *next, *curr;
curr = buff;
next = next_line(curr);
count = 0;
while(next != curr) {
*(next-1) = 0;
ret = sscanf(curr, " %s %s %s %s %s ", key, val0, val1, val2, val3);
if( strcmp(key, "Pid:") == 0 ) {
p->Pid = atoi(val0);
count++;
}else if( strcmp(key, "Name:") == 0 ) {
strcpy(p->Name, val0);
count++;
}else if( strcmp(key, "PPid:") == 0 ) {
p->Ppid = atoi(val0);
count++;
}else if( strcmp(key, "Uid:") == 0 ) {
p->Effecitveuid= atoi(val1);
int uid = atoi(val0);
pws = getpwuid(uid);
strcpy(p->Username, pws->pw_name);
count++;
}else if( count >= 3) {
break;
}
curr = next;
next = next_line(curr);
}
fclose(fp);
}
}else{
return NULL;
}
p->Cmdline[0] = 0;
sprintf(filename, "/proc/%d/cmdline", pid);
fp = fopen(filename, "r");
if( fp != NULL ) {
str_len = fread(p->Cmdline, 1, 1024, fp);
i = 0;
while(i < str_len-1) {
if(p->Cmdline[i] == 0) {
p->Cmdline[i] = ' ';
}
i++;
}
fclose(fp);
}
p->Exe[0] = 0;
sprintf(filename, "/proc/%d/exe", pid);
str_len = readlink(filename, p->Exe, 128);
if( str_len > 0 ) {
i = 0;
while(i < str_len) {
if(p->Exe[i] == 0) {
p->Exe[i] = ' ';
}
i++;
}
p->Exe[str_len] = 0;
}
p->Fd[0] = 0;
strcpy(p->Fd, "[");
str_len = 1;
i = 0;
while( i < 3 ) {
sprintf(filename, "/proc/%d/fd/%d", pid, i);
ret = readlink(filename, buff, 128);
if( ret > 0 ) {
buff[ret] = 0;
str_len += sprintf(p->Fd+str_len, "\"%s\",", buff);
}
i++;
}
if( p->Fd[str_len-1] == ',') {
p->Fd[str_len-1] = ']';
}else {
strcat(p->Fd, "]");
}
return p;
}
int proc2json(proc *p, char *buff)
{
int len = 0;
len += sprintf(buff, "{");
len += sprintf(buff+len, "\"%s\":%d,", "Pid", p->Pid);
len += sprintf(buff+len, "\"%s\":\"%s\",", "Name", p->Name);
len += sprintf(buff+len, "\"%s\":%d,", "Ppid", p->Ppid);
len += sprintf(buff+len, "\"%s\":\"%s\",", "Username", p->Username);
len += sprintf(buff+len, "\"%s\":%d,", "Effecitveuid", p->Effecitveuid);
len += sprintf(buff+len, "\"%s\":\"%s\",", "Exe", p->Exe);
len += sprintf(buff+len, "\"%s\":\"%s\",", "Cmdline", p->Cmdline);
len += sprintf(buff+len, "\"%s\":%s", "Fd", p->Fd);
len += sprintf(buff+len, "}");
return len;
}
void main()
{
int i = 0;
int ret;
proc *p;
char buff[2048];
while(i++ < 60000) {
p = get_proc(i);
if(p) {
ret = proc2json(&g_proc, buff);
printf("%s\n", buff);
}
}
}