首页 > 系统相关 >[操作系统] 打印进程树 pstree

[操作系统] 打印进程树 pstree

时间:2024-01-19 22:36:10浏览次数:36  
标签:std 操作系统 auto 打印 pid 进程 include pstree name

打印进程树

简介

这是 jyy 老师的操作系统课程的 M1 实验,为了弥补一些欠缺的操作系统相关的知识。在这里实现的的 pstree 并不是严格的按照实验要求而设计的(一个原因是按要求实现的代码不可以公开),这里会看到一些不一样的简单实现,比如直接运行,没有命令行可选参数,输出格式会有所不同,编程语言所使用的是 c++ 而不是 c

实验要求

实现一个简单的 pstree ,能够展示进程之间的树状关系。

实验环境

Arch Linux x86_64

实验设计

在我的环境中,因为使用的是 arch ,可以知道第一个进程的 pid=1 ,也就是 systemd

linux 中,一切皆文件,那么我们就需要找到一个对应的目录,找到进程文件,也就是 /proc 下,每个以数字为名的子目录就代表着当前系统下运行的进程,每个进程目录下包含着多个与该进程相关的进程文件。因此,这里使用 std::filesystem::directory_iterator 对目录进行遍历。

对于进程树,我们需要知道如何获取到该进程的父进程 pid 。这里可以通过 /proc/[pid]/stat 或者可读性更好的 /proc/[pid]/status 提供该进程的信息。我们需要其中的进程名,以及其父进程 pid ,对应 stat 中的第二个和第四个字符串。

只要我们将这些信息找出来,就不难发现,这些构成了一颗树,我们打印的时候只需递归打印即可。

总的代码量很少,很简单就可以在一个 main 中实现一个简单的 pstree 了。

代码实现

#include <cassert>
#include <chrono>
#include <cstdint>
#include <fstream>
#include <ranges>
#include <format>
#include <iostream>
#include <filesystem>
#include <string>
#include <unordered_map>
#include <vector>

auto main(int argc, char* argv[]) -> int {
    for (int i = 0; i < argc; i ++) {
        assert(argv[i] != nullptr);
        // std::cout << std::format("argv[{}] = {}\n", i, argv[i]);
    }
    assert(argv[argc] == nullptr);

    std::filesystem::path proc_dir_path = "/proc";
    assert(std::filesystem::exists(proc_dir_path));

    std::unordered_map<std::uint64_t, std::vector<std::uint64_t>> pid_adj{};
    std::unordered_map<std::uint64_t, std::string> pid_name{};

    auto string_to_pid = [](const std::string &file_name, std::uint64_t &pid_result) -> bool {
        pid_result = 0;
        for (auto ch : file_name) {
            if (ch >= '0' && ch <= '9') {
                pid_result = pid_result * 10 + (ch - '0');
            } else {
                return false;
            }
        }
        return true;
    };

    for (const auto &entry : std::filesystem::directory_iterator(proc_dir_path)
        | std::views::filter([](const auto &entry) {
                return entry.status().type() == std::filesystem::file_type::directory
                    && std::filesystem::exists(entry.path() / "stat");
            })
    ) {
        auto file_name = entry.path().filename().string();
        std::uint64_t pid;
        if (!string_to_pid(file_name, pid)) {
            continue;
        }

        auto stat_stream = std::ifstream(entry.path() / "stat");

        std::string _, parent_pid_str, pid_name_str;
        stat_stream >> _ >> pid_name_str >> _ >> parent_pid_str;

        std::uint64_t parent_pid;
        if (!string_to_pid(parent_pid_str, parent_pid)) {
            continue;
        }

        pid_name[pid] = pid_name_str;
        pid_adj[parent_pid].emplace_back(pid);
    }

    auto dump_print = [&](auto &self, std::uint64_t current_pid, std::string indent = "", bool is_last = true) -> void {
        const auto marker = is_last ? "└───" : "├───";
        std::cout << std::format("{}{}{}({})\n", indent, marker, pid_name[current_pid], current_pid);

        if (!pid_adj.contains(current_pid)) {
            return;
        }

        indent += is_last ? "    " : "│   ";
        const auto &next = pid_adj[current_pid];
        for (std::size_t i = 0; i < next.size(); i ++) {
            self(self, next[i], indent, i + 1 == next.size());
        }
    };

    constexpr std::uint64_t init_pid = 1;
    dump_print(dump_print, init_pid);
}

标签:std,操作系统,auto,打印,pid,进程,include,pstree,name
From: https://www.cnblogs.com/FlandreScarlet/p/17975765

相关文章

  • 云打印原理,云打印服务是什么意思?
    最近一段时间云打印的概念非常火热,很多App和个人用户都来到易绘创开放平台寻求对接云打印服务。那么云打印服务是什么意思?云打印的原理又是怎么样的?今天就来给大家介绍一下。 云打印原理,云打印服务是什么意思?其实云打印就是一种基于云计算技术的打印方式,云打印即通过App、小......
  • 云打印服务怎么启动?云打印服务怎么使用?
    最近一段时间,易绘创云打印服务开始在各个App和高校中火热了起来。很多没有打印机或者觉得线下打印店较贵的用户都想使用云打印服务。那么云打印服务怎么启动?云打印服务怎么使用呢?今天小易就带大家来了解一下。 云打印服务怎么启动?云打印服务怎么使用?目前打印市场上的云打印......
  • 嵌入式操作系统的一些基本概念
    1、前后台系统一些对实时性要求不那么严格的基于芯片的开发会采用前后台系统架构来进行开发,前后台系统前台由中断构成,后台由一个顺序处理任务的无限循环构成。//中断服务程序voidkeyHandle();voiduartHandle();//主函数intmain(intargc,char**argv){BSP......
  • 云打印自助服务系统有哪些?云打印自助服务系统怎么用?
    随着当下云打印服务的火热发展,越来越多的人开始选择云打印服务。那么云打印自助服务系统有哪些?云打印自助服务系统怎么用?接下来带大家来了解一下。云打印自助服务系统有哪些?云打印自助服务系统怎么用?当前市场上的云打印自助服务系统还是有一些的,不过大多是需要自备打印机才能完......
  • 云打印机介绍,云打印机是什么意思?
    随着当下云打印服务的火热发展,越来越多的人开始选择云打印服务。那么当下的云打印软件有哪些?云打印平台怎么选?接下来带大家来了解一下。 云打印软件有哪些?当前市场上的云打印软件还是有一些的,不过要找到合适靠谱的云打印平台的话,我们还是要根据自己的定位来寻找合适的云打印......
  • RaspberryPi(树莓派)安装操作系统
    访问网站:RaspberryPiOS–RaspberryPi 下载RaspberryPiImager管理器。  保存到本地后进行安装。运行程序选择你的树莓派类型,然后选择需要安装的操作系统。安装操作系统然后单击下一步安装操作系统。RaspberryPi(树莓派)安装操作系统安装完成当安装完成后把SD卡从卡槽中......
  • RaspberryPi(树莓派)安装操作系统时默认启用 SSH
    如果对RaspberryPi(树莓派)安装操作系统的时候不做任何修改的话默认是不用SSH的。单击编辑设置。配置SSH在当前的界面中,选择启用SSH。  那么在安装完成RaspberryPi(树莓派)后的SSH是自动启动服务的。 ......
  • SpringBoot项目从0到1配置logback日志打印
    转载自:SpringBoot项目从0到1配置logback日志打印,作者sum墨一、写文背景我们在写后端项目的时候,日志打印是必需的。支持SpringBoot项目的日志框架一般有log4j、logback,这二者各有优劣,这里就不展开对比了。我们项目中常用的是logback框架,该框架主要是一个logback-spring.xml配置......
  • MIT 6.S081入门 lab0 操作系统环境及其配置
    MIT6.S081入门lab0操作系统环境及其配置闲话由于不是正经计算机专业出身,但是又想做Linux内核/驱动开发,因此赶在暑假实习开始前把操作系统的课程补习一下。之前自学的linux的驱动系统入门的笔记在这个寒假也会整理并发布(包括U-boot移植和驱动/应用开发入门)。实验环境Ubuntu-......
  • 操作系统
    目录操作系统概述进程管理信号量与PV操作前趋图死锁进程资源图银行家算法存储管理段页式存储页面置换算法文件管理索引文件位示图操作系统概述进程管理存储管理文件管理作业管理设备管理进程管理进程的两个基本属性:可拥有资源的独立单位;可独立调度和分配资源的基本单位......