#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
int
main (int ac, char *av[])
{
pid_t inipid = atoi(av[1] ? : "0");
if (kill(inipid, 0) && errno == ESRCH)
exit((puts("No such process"), 1));
// сортируем по ppid, таким образом все потомки одного pid окажутся рядом
FILE *in = popen("ps -e --no-headers -o ppid,pid | sort -n -k 1", "r");
if (!in)
exit((perror("ps ..."), 2));
int ppasize,
nppa = 0; // количество пар ppid,pid (всего процессов из ps -e)
struct pids {
pid_t ppid, pid;
} *ppa = (__typeof__(ppa))malloc(sizeof(*ppa) * (ppasize = 100));
if (!ppa)
exit((perror("malloc"), 2));
// прочтем отсортированный по ppid набор ppid,pid в ppa[]
while (fscanf(in, "%d %d", &ppa[nppa].ppid, &ppa[nppa].pid) == 2)
if (++nppa == ppasize)
if (!(ppa = (__typeof__(ppa))realloc(ppa, sizeof(*ppa) * (ppasize *= 2))))
exit((perror("realloc"), 2));
pclose(in);
/*
Пройдем по дереву потомков inipid и подсчитаем их число.
Для этого используем очередь.
Для pid из головы очереди ищем в ppa[] все процессы с таким ppid
(это непосредственные потомки) и помещаем их в хвост очереди.
Повторяем, пока в очереди что-то есть.
Количество элементов выбранных из очереди является ответом (-1 inipid)
*/
pid_t q[nppa + 1]; // очередь потомков inipid
int qh = 0, qt = 0, // индексы head и tail очереди
nchilds = -1; // наш result
q[qt++] = inipid; // инициируем процесс поиска, занеся в очередь inipid
// повторяем, пока очередь не станет пустой
do {
nchilds++;
pid_t pid = q[qh++]; // новый parent
int first = 0, last = nppa, mid;
// используем binsearch для поиска первого потомка (ppa[i].ppid == pid)
while (first < last) {
mid = first + (last - first) / 2;
// такое вычисления middle позволяет избегать overflow в общем случае
if (pid > ppa[mid].ppid)
first = mid + 1;
else
last = mid;
}
// переберем всех потомков pid и занесем их в очередь
// они расположены последовательно, поскольку мы сортировали ppa[] по ppid
while (first < nppa && pid == ppa[first].ppid)
q[qt++] = ppa[first++].pid;
} while (qh < qt);
free(ppa);
return printf("pid %d has %d childs (of %d total pids)\n",
inipid, nchilds, nppa) < 0;
}
PS通过/进行
类型转换,这样程序也可以由 C++ 编译器翻译。mallocrealloc__typeof__
键 ps:
-h
没有标头(无论它是进程的什么),--ppid
使用给定的 ppid 发布进程。ps 的输出是 servedwc
,它可以计算行数。要递归地获取所有孩子的数量,您可以使用 pstree 并做一些魔术:
pstree
从指定的开始绘制进程树。可惜树太美,不便寄托。密钥-p
在树上给出括号中进程的 pid。我们用 grep 选择这些括号。我们跳过第一行tail
,因为这是我们开始的过程本身。最后,我们算数。但是如果系统有一个进程只调用括号中的数字(原则上不太可能),则可能会出错由于标签是 C,它可能对某些人有用,该程序可以为给定进程的整个后代树解决此问题。
让我们以命令接收的 PPID 对列表、所有进程的 PID 为基础,
ps -e -o ppid,pid
并按 PPID 值对其进行排序。因此,每个进程的所有后代都将在附近。
让我们在这个列表中找到给定进程的所有直接后代(即列表中 PPID 等于给定 PID 的那些对)并依次对每个进程执行相同的搜索(我们将“遍历进程树” ”)。为了实现我们的搜索步骤,我们使用了一个 PID 队列,我们将找到的直接后代放在其中。
结果(给定进程的子进程数)将等于放置在队列中(从队列中移除)的元素数减去给定进程,它初始化队列以进行树遍历。
PS通过/进行
类型转换,这样程序也可以由 C++ 编译器翻译。
malloc
realloc
__typeof__
计算进程的所有子进程: