1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
| #include <iostream>
#include <vector>
#include <string>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <map>
#define MAX_LINE 1000
struct tree_node
{
pid_t id;
pid_t ppid;
std::string cmd;
std::vector<tree_node*> children;
};
void printTree(tree_node*, int);
int main() {
DIR *dirp;
struct dirent *dp;
char path[PATH_MAX];
char line[MAX_LINE], cmd_str[MAX_LINE];
pid_t ppid;
FILE *fp;
char *p;
bool gotname, gotpid, gotppid;
dirp = opendir("/proc");
if (dirp == NULL)
return -1;
/* Scan entries under /proc directory */
std::map<pid_t, tree_node*> pmap; // id > process, 树结构查找麻烦,建立一个map辅助查找
gotname = false;
gotppid = false;
for (;;) {
errno = 0; /* To distinguish error from end-of-directory */
dp = readdir(dirp);
if (dp == NULL) {
if (errno != 0)
return -1;
else
break;
}
/* Since we are looking for /proc/PID directories, skip entries
that are not directories, or don't begin with a digit. */
if (dp->d_type != DT_DIR || !isdigit((unsigned char) dp->d_name[0]))
continue;
snprintf(path, PATH_MAX, "/proc/%s/status", dp->d_name);
fp = fopen(path, "r");
if (fp == NULL)
continue; /* Ignore errors: fopen() might fail if
process has just terminated */
while (!gotname || !gotppid) {
if (fgets(line, MAX_LINE, fp) == NULL)
break;
/* The "Name:" line contains the name of the command that
this process is running */
if (strncmp(line, "Name:", 5) == 0) {
for (p = line + 5; *p != '\0' && isspace((unsigned char) *p); )
p++;
// 去除最后的换行符
char *pt = p;
while(*pt != '\n' && *pt != '\0')
pt++;
*pt = '\0';
strncpy(cmd_str, p, MAX_LINE - 1);
cmd_str[MAX_LINE -1] = '\0'; /* Ensure null-terminated */
}
if (strncmp(line, "PPid:", 5) == 0) {
ppid = strtol(line + 6, NULL, 10); /* Ensure null-terminated */
}
}
tree_node *pinfo = new tree_node;
pinfo->id = strtol(dp->d_name, NULL, 10);
pinfo->cmd = std::string(cmd_str);
pinfo->ppid = ppid;
pmap[pinfo->id] = pinfo;
fclose(fp);
}
// 构建进程树
for (auto item : pmap) {
if (pmap.count(item.second->ppid) > 0) {
pmap[item.second->ppid]->children.push_back(item.second);
}
}
// 打印
printTree(pmap[1], 0);
}
// 递归的打印出进程的所有子进程
void printTree(tree_node* node, int level) {
for(int i = 0; i < level; i++)
{
printf("|");
printf(" ");
}
printf("|--- ");
printf("[%d]%s\n", node->id, node->cmd.c_str());
for(auto i : node->children) {
printTree(i, level + 1);
}
}
|