外观
Debian中编写cpp
1.Debian中编写并运行
安装环境
apt update
apt install build-essential #build-essential:基础开发工具包 包含了gcc g++ make libc6-dev dpkg-dev
#一般来说Linux 上需要编译任何软件,先安装 `build-essential`
g++ --version #验证是否安装成功编写程序
#创建工作目录
mkdir cpp_learning
cd cpp_learning
#编写代码
vi main.cpp#include
int main() {
std::cout << "==== 极简 linux进程监视器 ====" << std::endl;
}#编译为可执行的二进制文件
g++ -std=c++17 -o monitor main.cpp
#g++调用c++编译器
#-std=c++17 使用c++17的标准2.VS Insiders中编写linux与远程调试
- 配置目标机器的连接信息
- 在目标机器中安装gdb
apt install gdb -y- gdb是用来调试的,上面那个gcc是用来编译的;gcc造,gdb修
- 修改编译环境C++的版本
- 右键项目属性 -> C/C++ -> 语言 中将C++语言标注改为你想要的版本
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <filesystem>
#include <iomanip>
#include <algorithm> //std::all_of
namespace fs = std::filesystem;
// 1. 定义数据结构,存储进程信息
struct ProcessInfo {
int pid;
std::string name;
std::string state;
std::string vmRSS; // 物理内存占用
};
// 辅助函数:从文件中读取第一行内容
std::string readFirstLine(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
return "";
}
std::string line;
std::getline(file, line);
return line;
}
// 辅助函数:从 status 文件中提取特定字段的值 (例如 VmRSS:)
std::string extractValueFromStatus(const std::string& path, const std::string& key) {
std::ifstream file(path);
if (!file.is_open()) return "";
std::string line;
while (std::getline(file, line)) {
// 简单查找 key,例如 "VmRSS:"
if (line.find(key) == 0) {
// 找到冒号的位置
size_t pos = line.find(':');
if (pos != std::string::npos) {
// 截取冒号后面的部分,并去除前后空格
std::string value = line.substr(pos + 1);
// 简单去除前导空格
size_t start = value.find_first_not_of(" \t");
if (start != std::string::npos) {
return value.substr(start);
}
}
}
}
return "";
}
ProcessInfo getProcessInfo(int pid) {
ProcessInfo info;
info.pid = pid;
info.name = "unknown";
info.state = "?";
info.vmRSS = "0 kB";
std::string procPath = "/proc/" + std::to_string(pid) + "/";
// 1. 读取进程名 (/proc/[pid]/comm)
std::string commPath = procPath + "comm";
std::string name = readFirstLine(commPath);
if (!name.empty()) info.name = name;
// 2. 读取状态和内存 (/proc/[pid]/status)
std::string statusPath = procPath + "status";
// 读取 State (状态)
// status 文件里 State 通常是第二行,但我们用提取函数更通用
// 为了极简,我们直接解析 status 文件里的 State 字段
std::ifstream statusFile(statusPath);
if (statusFile.is_open()) {
std::string line;
while (std::getline(statusFile, line)) {
if (line.find("State:") == 0) {
info.state = line.substr(7); // "State:" 长度是 6,跳过它和后面的空格
// 清理一下前导空格
size_t start = info.state.find_first_not_of(" \t");
if (start != std::string::npos) info.state = info.state.substr(start);
// 只取第一个字符,例如 'S (sleeping)' -> 'S'
if (!info.state.empty()) info.state = info.state.substr(0, 1);
}
if (line.find("VmRSS:") == 0) {
info.vmRSS = extractValueFromStatus(statusPath, "VmRSS");
}
}
statusFile.close();
}
return info;
}
/*
关键目录和文件:
/proc: 根目录。
/proc/[pid]/: 每个数字命名的目录代表一个进程(例如 /proc/1234/)。
/proc/[pid]/comm: 包含进程的简短名称(例如 bash)。
/proc/[pid]/status: 包含详细状态信息(包括内存 VmRSS,状态 State)。
/proc/[pid]/stat: 包含更底层的统计信息(初学者先暂时不用,解析较复杂)。
*/
std::vector<ProcessInfo> getAllProcesses() {
std::vector<ProcessInfo> processes;
const std::string procPath = "/proc";
for (const auto& entry : fs::directory_iterator(procPath)) {
// 只关心目录名是数字的 entry (PID)
if (entry.is_directory()) {
std::string dirname = entry.path().filename().string();
// 检查是否全为数字
if (!dirname.empty() && std::all_of(dirname.begin(), dirname.end(), ::isdigit)) {
int pid = std::stoi(dirname);
//std::cout << pid << std::endl; // 输出 PID 以验证我们正确读取了进程目录
// 获取详细信息并加入列表
// 注意:这里可能会因为权限不足或进程结束而抛出异常/返回空数据,生产环境需更严谨
try {
processes.push_back(getProcessInfo(pid));
}
catch (...) {
// 忽略读取失败的进程 (可能刚退出)
continue;
}
}
}
}
return processes;
}
int main()
{
std::vector<ProcessInfo> procs = getAllProcesses();
std::cout << "\t===== 极简 Linux 进程监视器(" << procs.size() << ")===== " << std::endl;
// 获取所有进程
// 打印表头
// setw(n) 设置输出宽度,left 左对齐
std::cout << std::left
<< std::setw(10) << "PID"
<< std::setw(20) << "NAME"
<< std::setw(10) << "STATE"
<< std::setw(15) << "MEMORY (VmRSS)"
<< std::endl;
std::cout << std::string(55, '-') << std::endl;
// 打印每一行
for (const auto& p : procs) {
std::cout << std::left
<< std::setw(10) << p.pid
<< std::setw(20) << p.name
<< std::setw(10) << p.state
<< std::setw(15) << p.vmRSS
<< std::endl;
}
return 0;
}