使用C++获取Linux进程列表及状态的最优方案问询
Hey there! Let's tackle this process enumeration problem for your Linux antivirus project—super cool that you've already nailed the math models and heuristic methods, by the way. Recursively scanning /proc is a common first approach, but as you've noticed, it misses short-lived processes that start and exit between directory scans. Here are two modern, clean C++ solutions to fix this:
1. Use libproc2 for Fast, Reliable One-Shot Scans
libproc2 is the updated, maintained successor to the old libproc library, built for modern Linux kernels. It's efficient and avoids many pitfalls of manual /proc parsing.
Step-by-Step Implementation
First, install the library (package names vary by distro: libproc2-dev on Debian/Ubuntu, procps-ng-devel on RHEL/CentOS).
Here's a concise C++ example that enumerates all processes, grabs their state, and writes to a file:
#include <iostream> #include <fstream> #include <cstring> #include <proc/readproc.h> int main() { // Open output file with RAII-style management std::ofstream out_file("process_snapshot.txt"); if (!out_file.is_open()) { std::cerr << "Failed to open output file\n"; return 1; } // Configure proc reader to fetch core process details + state proc_t proc_info{}; PROCTAB* proc_tab = openproc(PROC_FILLSTAT | PROC_FILLSTATUS); if (!proc_tab) { std::cerr << "Failed to initialize proc table reader\n"; return 1; } // Iterate through all process entries while (readproc(proc_tab, &proc_info) != nullptr) { out_file << "PID: " << proc_info.tgid << " | Name: " << proc_info.cmd << " | State: " << proc_info.state << "\n"; } // Cleanup resources closeproc(proc_tab); out_file.close(); return 0; }
Compile with:
g++ -o proc_snapshot proc_snapshot.cpp -lps
This method is faster than manual /proc traversal and handles edge cases like zombie processes or kernel threads more reliably.
2. Combine with Netlink PROC_EVENT for Real-Time Process Tracking
To catch short-lived processes that might escape a one-shot scan, use the Linux kernel's netlink PROC_EVENT interface. This lets your program receive real-time notifications when processes are created, exited, or modified.
C++ Example for Netlink Process Monitoring
This code sets up a netlink socket to listen for process events and appends them to your output file:
#include <iostream> #include <fstream> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/connector.h> #include <linux/cn_proc.h> #define BUFFER_SIZE 1024 void handle_proc_event(const struct proc_event* event, std::ofstream& out_file) { switch (event->what) { case PROC_EVENT_FORK: out_file << "[NEW PROCESS] Child PID: " << event->event_data.fork.child_tgid << " | Parent PID: " << event->event_data.fork.parent_tgid << "\n"; break; case PROC_EVENT_EXIT: out_file << "[PROCESS EXIT] PID: " << event->event_data.exit.process_tgid << " | Exit Code: " << (event->event_data.exit.exit_code >> 8) << "\n"; break; default: break; } } int main() { std::ofstream out_file("process_events.txt", std::ios::app); if (!out_file.is_open()) { std::cerr << "Failed to open events log file\n"; return 1; } int sock_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (sock_fd < 0) { std::cerr << "Failed to create netlink socket\n"; return 1; } struct sockaddr_nl sa_nl{}; sa_nl.nl_family = AF_NETLINK; sa_nl.nl_groups = CN_IDX_PROC; sa_nl.nl_pid = getpid(); if (bind(sock_fd, (struct sockaddr*)&sa_nl, sizeof(sa_nl)) < 0) { std::cerr << "Failed to bind netlink socket\n"; close(sock_fd); return 1; } // Send subscription request for process events struct cn_msg msg{}; struct proc_event_mc mc{}; msg.id.idx = CN_IDX_PROC; msg.id.val = CN_VAL_PROC; msg.len = sizeof(mc); mc.cmd = PROC_MC_LISTEN; if (send(sock_fd, &msg, sizeof(msg) + sizeof(mc), 0) < 0) { std::cerr << "Failed to subscribe to process events\n"; close(sock_fd); return 1; } // Listen for incoming events char buffer[BUFFER_SIZE]; while (true) { ssize_t recv_len = recv(sock_fd, buffer, BUFFER_SIZE, 0); if (recv_len < 0) { std::cerr << "Failed to receive netlink message\n"; break; } struct nlmsghdr* nl_hdr = (struct nlmsghdr*)buffer; while (NLMSG_OK(nl_hdr, recv_len)) { struct cn_msg* cn_msg = (struct cn_msg*)NLMSG_DATA(nl_hdr); struct proc_event* event = (struct proc_event*)cn_msg->data; handle_proc_event(event, out_file); nl_hdr = NLMSG_NEXT(nl_hdr, recv_len); } } close(sock_fd); out_file.close(); return 0; }
Compile with:
g++ -o proc_monitor proc_monitor.cpp
Optimal Workflow for Your Antivirus
For complete host fingerprinting:
- Run the
libproc2snapshot first to capture all currently running processes. - Start the netlink monitor immediately after to track any new/exited processes, appending them to your file. This combination ensures you won't miss short-lived processes that start after your initial scan.
Both solutions use modern Linux APIs and clean C++ practices, avoiding outdated code patterns.
内容的提问来源于stack exchange,提问作者Mihai




