2024-01-19 22:23阅读: 231评论: 0推荐: 0

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

打印进程树

简介

这是 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);
}

本文作者:フランドール·スカーレット

本文链接:https://www.cnblogs.com/FlandreScarlet/p/17975765

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   フランドール·スカーレット  阅读(231)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Scarborough Fair 山田タマル
  2. 2 Faster Than Light Paradox Interactive,Andreas Waldetoft
  3. 3 世界は可愛く出来ている 上海アリス幻樂団
Scarborough Fair - 山田タマル
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : Pual Simon

作曲 : Pual Simon

作词 : イングランド民謡

作曲:加藤达也

Are you going to Scarborough Fair?

Parsley, sage, rosemary and thyme

Remember me to one who lives there

He once was a true love of mine

Tell him to make me a cambric shirt

Tell him to make me a cambric shirt

Parsley, sage, rosemary and thyme

Without no seams nor needlework

Then he'll be a true love of mine.

Tell him to find me an acre of land

Tell him to find me an acre of land

Parsley, sage, rosemary and thyme

Between the salt water and the sea strand

Then he'll be a true love of mine

Are you going to Scarborough Fair?