模仿pstree 打印进程树

article/2025/11/8 2:13:22

一个查看进程树的小栗子
可以打印进程数,并且可以加参数 -n 显示pid,加参数-p 显示线程信息 ( 和pstree 的参数并不一样)

准备工作

step 1 处理进程信息

想办法找到所有当前进程
在Linux下

proc 文件系统 (procfs) 是类 Unix 操作系统中的一种特殊文件系统,它以分层文件结构呈现有关进程的信息和其他系统信息,为动态访问内核中保存的进程数据提供了一种更方便和标准化的方法。传统的跟踪方法或直接访问内核内存。 (翻译自维基百科)

所以说,我们每一个进程其实存放在Linux下的/proc文件夹下,以进程号作为文件夹名称
接下来,我们要想办法读取这个文件夹下的所有文件夹
这里我们需要用到Linux下读取文件夹的一些操作 其包含的操作在dirent.h下。
其函数原型有:
在这里插入图片描述
struct dirent 结构
在这里插入图片描述
struct DIR 结构
在这里插入图片描述

在这里,我们利用opendir函数和readdir函数遍历目录

int listdir(const char *path) {DIR *dir;struct dirent *entry;dir = opendir(path);if (dir == NULL) {perror("fail opendir");return -1;}while ((entry = readdir(dir)))if (DT_DIR == entry -> d_type)puts(entry->d_name);closedir(dir);return 0;
}

接下来我们要去status里读取这个进程的信息,同时去task文件夹下面读取这个进程的线程
/proc/PID/status contains basic information about a process including its run state and memory usage.

	FILE* fp;char ch[size];strcpy(ch, "/proc/");strcat(ch, path);strcat(ch, "/status");fp = fopen(ch, "r");char pid[size], ppid[size], name[size];while((fscanf(fp, "%s", ch)) != EOF) {if (strcmp(ch, "Pid:") == 0) {fscanf(fp, "%s", pid);}if (strcmp(ch, "PPid:") == 0) {fscanf(fp, "%s", ppid);}if (strcmp(ch, "Name:") == 0) {fscanf(fp, "%s", name);}}

进入task目录下遍历目录我们可以使用listdir一样的代码

step 2 建树

我们需要一颗多叉树,来供我们保存父子节点信息方便打印,以及建树的几个函数

struct process {char *p_name;char *p_pid;struct process *bro;struct process *son;
};
typedef struct process process;
process* create_p(const char*, const char*);
int insert(process*, process*, const char*);
int print_tree(process*, int, int*, int);

这部分就是数据结构的问题,所有就不多叙述

step 3 打印树

我们需要控制一下打印格式 且需要使用一些Unicode特殊字符
如:\u2500, \u2502, \u252c, \u2514 等字符
然后递归打印这颗树即可

int print_tree(process* head, int len, int* buf, int flag) {if (head == NULL) return -1;while (head) {printf("%s", head->p_name);if (flag) printf("(%s)", head->p_pid);if (head->son) {if(!head->son->bro) printf("\u2500\u2500\u2500");else printf("\u2500\u252c\u2500");int size = strlen(head->p_name) + len + 3 + (flag * (strlen(head->p_pid) + 2));if (head->son->bro) buf[size - 2] = 1;print_tree(head->son, size, buf, flag);}head = head->bro;if (head) {printf("\n");if (!head->bro) buf[len - 2] = 0;for (int i = 0; i < len - 2; ++ i) if (buf[i]) printf("\u2502");else printf(" ");if (!head->bro) printf("\u2514\u2500");else printf("\u251c\u2500");}}return 0;
}

总体代码

/*************************************************************************> File Name: demo.c> Author: amjieker> Mail:  secrecy> Created Time: Sun Mar 14 20:58:37 2022************************************************************************/#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
struct process {char *p_name;char *p_pid;struct process *bro;struct process *son;
};
typedef struct process process;// toolsint listdir(const char*, const char*, process**, int, int);
int check_digital(const char*);
int build_tree(const char*, process*, int dep);
// struct process function 
process* create_p(const char*, const char*);
int insert(process*, process*, const char*);
int print_tree(process*, int, int*, int);int main(int argc, char* argv[]) {	
//	listdir("/proc");
//	process* head = create_p("init", "1");
//	insert(head, create_p("zsh", "2"), "1");	
//	insert(head, create_p("ass", "3"), "1");
//	insert(head, create_p("ssssssssssssssssb", "4"), "1");
//	insert(head, create_p("cdsds", "5"), "2");
//	insert(head, create_p("dwe2", "6"), "5");
//	insert(head, create_p("fdpsaa", "7"), "5");
//	insert(head, create_p("e3wq", "8"), "4");
//	insert(head, create_p("gxps", "9"), "4");
//	insert(head, create_p("wwewqm", "10"), "8");
//	insert(head, create_p("wwewqm", "11"), "8");
//	insert(head, create_p("wwewqm", "12"), "8");
//	insert(head, create_p("wwewqm", "13"), "8");
//	insert(head, create_p("wwewqm", "14"), "8");
//	insert(head, create_p("wwewqm", "15"), "10");
//	insert(head, create_p("wwewqm", "16"), "10");
//	insert(head, create_p("wwewqm", "17"), "10");
//	insert(head, create_p("wwewqm", "18"), "10");
//	insert(head, create_p("wwewqm", "19"), "14");
//	insert(head, create_p("wwewqm", "20"), "14");
//	insert(head, create_p("wwewqm", "21"), "14");
//	insert(head, create_p("wwewqm", "22"), "14");
//	insert(head, create_p("wwewqm", "23"), "14");
//	insert(head, create_p("wwewqm", "24"), "14");
//	insert(head, create_p("wwewqm", "25"), "20");
//	insert(head, create_p("wwewqm", "26"), "20");
//	insert(head, create_p("wwewqm", "27"), "20");
//	insert(head, create_p("wwewqm", "28"), "27");int buf[1024] = {0};int state_n = 0, state_p = 0;for (int i = 1; i < argc; ++ i) {if (strcmp(argv[i], "-n") == 0) state_n = 1;else if (strcmp(argv[i], "-p") == 0) state_p = 1;else {puts(argv[i]);puts("errof command");exit(0);}}process** head = (process**)malloc(sizeof(process*));listdir("/proc", " ", head, 0, state_p);printf("\n");print_tree((*head), 0, buf, state_n);printf("\n");return 0;
}int listdir(const char* path, const char* father, process** head, int dep, int flag) {struct dirent *entry;DIR *dir;dir = opendir(path);if (dir == NULL) {perror("fail opendir");return -1;}if (dep == 0) *head = create_p("", "0"); // init processwhile ((entry = readdir(dir))) if (DT_DIR == entry -> d_type)if (check_digital(entry->d_name) != -1) {if (dep == 1 && !strcmp(entry->d_name, father))continue;build_tree(entry->d_name, *head, dep);if (0 == dep && flag) {char buf[1024];strcpy(buf, "/proc/");strcat(buf, entry->d_name);strcat(buf, "/task");listdir(buf, entry->d_name, head, 1, flag);}}closedir(dir);return 0;
}int check_digital(const char* s) {int flag = 0;for (; *s; ++ s)if (*s < '0' || *s > '9')return -1;return 0;
}int build_tree(const char* path, process* head, int dep) {const int size = 1024;FILE* fp;char ch[size];strcpy(ch, "/proc/");strcat(ch, path);strcat(ch, "/status");fp = fopen(ch, "r");char pid[size], ppid[size], name[size];while((fscanf(fp, "%s", ch)) != EOF) {if (strcmp(ch, "Pid:") == 0) {fscanf(fp, "%s", pid);}if (strcmp(ch, "PPid:") == 0) {fscanf(fp, "%s", ppid);}if (strcmp(ch, "Name:") == 0) {fscanf(fp, "%s", name);}}ch[0] = 0;if (dep) strcpy(ch, "{");strcat(ch, name);if (dep) strcat(ch, "}");insert(head, create_p(ch, pid), ppid);fclose(fp);return 0;
}void check_memory(void* p) {if (p == NULL) {perror("malloc error");exit(0);}
}process* create_p(const char* p_name, const char* p_pid) {process* p = (process*)malloc(sizeof(process));check_memory(p);p->p_name = (char*)malloc(sizeof(char) * (strlen(p_name) + 1));p->p_pid  = (char*)malloc(sizeof(char) * (strlen(p_pid)  + 1));check_memory(p->p_name);check_memory(p->p_pid);strcpy(p->p_name, p_name);strcpy(p->p_pid,  p_pid);p->bro = NULL;p->son = NULL;return p;
}// tools
int cmp(const char* a, const char *b) {int tempa = atoi(a), tempb = atoi(b);if (a == b) return 0;if (a > b) return 1;return -1;
}
void insert_node(process* head, process* node) { /*help insert node function*/process* cur = head->bro;process* prv = head;while (cur) {int state = strcmp(head->p_name, node->p_name);if ( 1 == state || (0 == state && -1 == cmp(head->p_pid, node->p_name))) {prv->bro = node;node->bro = cur;return;}prv = cur;cur = cur->bro;}prv->bro = node;return;
}int insert(process* head, process* node, const char* fp_pid) {if (node == NULL) return -1;if (head == NULL) return -1;while (head) {if (0 == strcmp(head->p_pid, fp_pid)) {if (head->son)insert_node(head->son, node);else head->son = node;return 0;} else {if (0 == insert(head->son, node, fp_pid))return 0;}head = head->bro;}return -1;
}int print_tree(process* head, int len, int* buf, int flag) {if (head == NULL) return -1;while (head) {printf("%s", head->p_name);if (flag) printf("(%s)", head->p_pid);if (head->son) {if(!head->son->bro) printf("\u2500\u2500\u2500");else printf("\u2500\u252c\u2500");int size = strlen(head->p_name) + len + 3 + (flag * (strlen(head->p_pid) + 2));if (head->son->bro) buf[size - 2] = 1;print_tree(head->son, size, buf, flag);}head = head->bro;if (head) {printf("\n");if (!head->bro) buf[len - 2] = 0;for (int i = 0; i < len - 2; ++ i) if (buf[i]) printf("\u2502");else printf(" ");if (!head->bro) printf("\u2514\u2500");else printf("\u251c\u2500");}}return 0;
}

最后效果

在这里插入图片描述


http://chatgpt.dhexx.cn/article/Cminf7fm.shtml

相关文章

pstree 详解

pstree命令是用于查看进程树之间的关系&#xff0c;即哪个进程是父进程&#xff0c;哪个是子进程&#xff0c;可以清楚的看出来是谁创建了谁 #pstree 几个重要的参数&#xff1a; -A: 各进程树之间的连接以ASCII码字符来连接 -U:各进程树之间的连接以utf8字符来连接&#xff0c…

Centos安装pstree

说明 以树状图的方式展现进程之间的派生关系 补充说明 pstree命令 以树状图的方式展现进程之间的派生关系&#xff0c;显示效果比较直观。 语法 pstree(选项) 选项 -a&#xff1a;显示每个程序的完整指令&#xff0c;包含路径&#xff0c;参数或是常驻服务的标示&#x…

Linux命令之树状图显示所有进程pstree

概述 pstree 命令会将所有进程以树状图形式显示&#xff0c;方便查看进程之间的父子关系。pstree 是 display a tree of process 的缩写。 树状图将会以 pid (如果有指定) 或是以 init 这个基本进程为根 (root)&#xff0c;如果有指定使用者 id&#xff0c;则树状图会只显示该…

Linux基础命令-pstree树状显示进程信息

Linux基础命令-uname显示系统内核信息 Linux基础命令-lsof查看进程打开的文件 Linux基础命令-uptime查看系统负载 文章目录 前言 一 命令介绍 二 语法及参数 2.1 使用man查看命令语法 2.2 常用参数 三 参考实例 3.1 以树状图的形式显示所有进程 3.2 以树状图显示进程号…

学习一个 Linux 命令:pstree

linux在工作中用的越来越多&#xff0c;接下来为大家介绍一下比较常用的命令pstree的使用方法 命令简介 pstree 命令以树状图的方式展现进程之间的派生关系。 [rootcentos7 ~]# pstree -bash: pstree: command not found [rootcentos7 ~]# yum install psmisc -y 语法格式 …

android系统apk文件,如何安装apk文件 安卓手机apk文件安装方法

我们知道安卓手机软件程序均为APK格式文件&#xff0c;很多小白朋友对于安卓手机如何安装apk文件不是很了解&#xff0c;下面本文于大家简单介绍下。由于很多朋友使用一些手机应用软件里面下载安装程序&#xff0c;但那仅仅是针对Wifi用户很方便&#xff0c;而没有Wifi用户因流…

Android下载安装Apk

1.自定义监听类&#xff0c;用来返回下载结果 interface DownLoadListener {/*** 下载成功之后的文件*/fun onDownloadSuccess(file: File)/*** 下载进度*/fun onDownloading(progress: Int)/*** 下载异常信息*/fun onDownloadFailed(e:Exception) }进行文件下载 /*** param …

在Win 11上安装APK

听说在Win11上支持直接安装apk了&#xff0c;所以先把系统升级到了Win11。 1、 安装WSA 因为安装的不是开发版&#xff0c;所以需要下载完整的WSA&#xff08;安卓子系统)&#xff0c;下载操作如下&#xff1a; 首先进入网站 https://store.rg-adguard.net&#xff0c;分别选…

google Play安装APK软件

一、参考资料 此 Google 帐号尚未与设备关联。要安装应用&#xff0c;请先访问设备上的 Play 商店应用 二、相关介绍 利用现有网站平台生成新的Google Play下载APK链接&#xff0c;APK下载器允许APK文件从Google Play直接下载到电脑或移动设备。 三、准备工作 在 Google P…

android怎么安装apk文件,apk文件怎么安装?如何安装apk文件

可能很多已经入手或者将要入手的机友,对Android系统软件如何安装和卸载比较模糊,我们有必要对之有一个系统的了解和认知,这样我们才能更容易上手,熟悉了解这个系统的使用。 一、从手机直接安装 1、将APK 文件拷贝入手机的存储卡,在手机上运行安装好的APK 程序安装器,找到…

cmd 安装 apk

➥ 检查 adb, 如果不是下面 的页面说明&#xff1b;要么配置下 环境变量&#xff1b;要么在 adb.exe 文件夹中执行 adb &#xff1b;如果你没有 去你 Android SDK 地址拿一个也行 ➥ 直接跑命令 adb install D:\MineGit\flutter_spawn\sdk\demo_2201.apk 如果你电脑 有…

androidP: apk安装流程

一、Android应用安装有如下四种方式 1 系统应用安装――开机时完成&#xff0c;没有安装界面 2.网络下载应用安装――通过market应用完成&#xff0c;没有安装界面 3.ADB工具安装――没有安装界面。 4. 第三方应用安装――通过SD卡里的APK文件安装&#xff0c;有安装界面&#…

APK安装流程及详细步骤

往期推荐 APK打包流程 APK文件结构 Android开发之数据储存 1.1 安装方式 1.安装APK文件共有4种方式&#xff1a; &#xff08;1&#xff09;系统程序安装 &#xff08;2&#xff09;通过Android市场安装 &#xff08;3&#xff09;手机自带安装 &#xff08;4&#xff09…

2021年宏观经济十大趋势展望

新冠肺炎疫情无疑是一只黑天鹅&#xff0c;对2020年世界经济带来了巨大的冲击。临近年末&#xff0c;可以从很多角度回顾2020年中国宏观经济。如果从内外循环的角度概括一下&#xff0c;我们认为今年中国经济有两个“超预期”&#xff1a;外贸超预期&#xff0c;外资超预期。 …

2010-2020年农业农村重要经济指标

数据集名称&#xff1a;农业农村重要经济指标 时间范围&#xff1a;2010-2020年 数据来源&#xff1a;农业农村部 相关说明&#xff1a; 农业农村重要经济指标&#xff0c;覆盖6大类别&#xff0c;170多张统计表 全球及主要国家大豆产量(万吨)&#xff08;2015-2019&#…

金融数据分析(十)人均国内生产总值的增长率

案例&#xff08;四&#xff09;宏观金融数据分析 项目一&#xff1a;利用世界银行公开数据平台提供的宏观经济数据比较最近40年间A国与B国的人均国内生产总值的增长率&#xff08;图表输出&#xff09; 数据可通过此网页中的下载链接获取&#xff1a;https://data.worldbank…

【指数编制系列六】景气指数编制方法

景气是经济景气的简称&#xff0c;指经济总体的运行发展态势和活跃程度&#xff0c;是用来分析经济活跃程度的经济概念。经济活动发展具有周期性扩张的特征&#xff0c;因而常用景气波动、景气循环等术语来表达经济周期波动的特点。   经济景气周期波动理论是研究产业景气周期…

持续有效的风险指标:动荡指数

量化投资与机器学习微信公众号&#xff0c;是业内垂直于量化投资、对冲基金、Fintech、人工智能、大数据等领域的主流自媒体。公众号拥有来自公募、私募、券商、期货、银行、保险、高校等行业30W关注者&#xff0c;荣获2021年度AMMA优秀品牌力、优秀洞察力大奖&#xff0c;连续…

消费与储蓄的决定-中国视角下的宏观经济

消费与储蓄的决定 – 潘登同学的宏观经济学笔记 文章目录 消费与储蓄的决定 -- 潘登同学的宏观经济学笔记 中国消费不足、储蓄过剩的事实有关中国经济需求面的关键问题 拉姆齐模型单期单个消费者的优化问题单期多个消费者的优化问题仅居民积累资本仅企业积累资本企业和居民同时…

关于指标的理解

文章目录 1.**纵向分析和横向分析**2.**电商行业**3.**广告投放**4.**基本指标**5. **经销商资金利用效果高低的指标是库销比**6. **业务分析模型**7.**可视化图表**8.**业务分析报告**9.父子级关系10.使用数据 1.纵向分析和横向分析 纵向比较同一事物在不同时期的形式&#xf…