Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
process.h
Go to the documentation of this file.
1
10
11/*
12Copyright (c) 2026 MrXie1109
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30SOFTWARE.
31*/
32
33#pragma once
34
35#ifndef __linux__
36#error "Unsupported platform - this library is for Linux only"
37#endif
38
39#include <cstdio>
40#include <cstdlib>
41#include <fcntl.h>
42#include <signal.h>
43#include <sys/types.h>
44#include <sys/wait.h>
45#include <unistd.h>
46
47namespace console {
52 enum class Signal : int {
53 Interrupt = SIGINT,
54 Terminate = SIGTERM,
55 Kill = SIGKILL,
56 Stop = SIGSTOP,
57 Continue = SIGCONT,
58 Hangup = SIGHUP,
59 User1 = SIGUSR1,
60 User2 = SIGUSR2
61 };
62
67 struct ExitStatus {
68 int code;
69 bool signaled;
70 int signal;
72
77 code(0), signaled(false), signal(0), core_dumped(false) {}
78
83 bool normal() const { return !signaled; }
84
89 int exit_code() const { return code; }
90
95 int term_signal() const { return signal; }
96 };
97
102 struct ProcessInfo {
103 pid_t pid;
104 pid_t ppid;
105 long rss_kb;
106 double cpu_time;
107 bool running;
108
113 pid(0), ppid(0), rss_kb(0), cpu_time(0), running(false) {}
114 };
115
120 class Process {
121 private:
122 pid_t pid_;
123
128 explicit Process(pid_t pid) : pid_(pid) {}
129
136 static int sys_kill(pid_t pid, int sig) { return ::kill(pid, sig); }
137
138 public:
142 static Process invalid() { return Process(-1); }
143
147 Process() : pid_(-1) {}
148
152 ~Process() = default;
153
157 Process(const Process &) = delete;
158
162 Process &operator=(const Process &) = delete;
163
168 Process(Process &&other) noexcept : pid_(other.pid_) {
169 other.pid_ = -1;
170 }
171
177 Process &operator=(Process &&other) noexcept {
178 if (this != &other) {
179 pid_ = other.pid_;
180 other.pid_ = -1;
181 }
182 return *this;
183 }
184
189 pid_t pid() const { return pid_; }
190
195 bool valid() const { return pid_ > 0; }
196
201 static Process fork() {
202 pid_t pid = ::fork();
203 if (pid == 0) return Process(0);
204 if (pid > 0) return Process(pid);
205 return Process(-1);
206 }
207
214 static Process spawn(int (*fn)(void *), void *arg) {
215 pid_t pid = ::fork();
216 if (pid == -1) return Process(-1);
217 if (pid == 0) {
218 int ret = fn(arg);
219 std::exit(ret);
220 }
221 return Process(pid);
222 }
223
231 static Process spawn_detach(int (*fn)(void *), void *arg) {
232 pid_t pid = ::fork();
233 if (pid == -1) return Process(-1);
234 if (pid == 0) {
235 int ret = fn(arg);
236 std::exit(ret);
237 }
238 return Process(pid);
239 }
240
245 static Process self() { return Process(getpid()); }
246
251 static Process parent() { return Process(getppid()); }
252
257 ExitStatus wait() const {
258 ExitStatus status;
259 int raw;
260 if (waitpid(pid_, &raw, 0) == -1) return status;
261 if (WIFEXITED(raw)) {
262 status.code = WEXITSTATUS(raw);
263 status.signaled = false;
264 } else if (WIFSIGNALED(raw)) {
265 status.signaled = true;
266 status.signal = WTERMSIG(raw);
267 status.core_dumped = WCOREDUMP(raw);
268 }
269 return status;
270 }
271
277 bool poll(ExitStatus *status) const {
278 int raw;
279 pid_t ret = waitpid(pid_, &raw, WNOHANG);
280 if (ret == pid_) {
281 if (WIFEXITED(raw)) {
282 status->code = WEXITSTATUS(raw);
283 status->signaled = false;
284 } else if (WIFSIGNALED(raw)) {
285 status->signaled = true;
286 status->signal = WTERMSIG(raw);
287 status->core_dumped = WCOREDUMP(raw);
288 }
289 return true;
290 }
291 return false;
292 }
293
299 static Process wait_any(ExitStatus *status) {
300 int raw;
301 pid_t pid = ::wait(&raw);
302 if (pid == -1) return Process(-1);
303 if (WIFEXITED(raw)) {
304 status->code = WEXITSTATUS(raw);
305 status->signaled = false;
306 } else if (WIFSIGNALED(raw)) {
307 status->signaled = true;
308 status->signal = WTERMSIG(raw);
309 status->core_dumped = WCOREDUMP(raw);
310 }
311 return Process(pid);
312 }
313
318 bool is_alive() const {
319 if (pid_ <= 0) return false;
320 return sys_kill(pid_, 0) == 0;
321 }
322
328 bool send_signal(Signal sig) const {
329 return sys_kill(pid_, static_cast<int>(sig)) == 0;
330 }
331
336 bool terminate() const { return sys_kill(pid_, SIGTERM) == 0; }
337
342 bool kill() const { return sys_kill(pid_, SIGKILL) == 0; }
343
348 bool stop() const { return sys_kill(pid_, SIGSTOP) == 0; }
349
354 bool resume() const { return sys_kill(pid_, SIGCONT) == 0; }
355
361 ProcessInfo info;
362 info.pid = pid_;
363 info.running = is_alive();
364 char path[64];
365 snprintf(path, sizeof(path), "/proc/%d/stat", pid_);
366 FILE *fp = fopen(path, "r");
367 if (fp) {
368 unsigned long utime, stime;
369 int ppid;
370 fscanf(fp,
371 "%d %*s %*c %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %lu %lu",
372 &info.pid,
373 &ppid,
374 &utime,
375 &stime);
376 info.ppid = ppid;
377 info.cpu_time = (utime + stime) / (double)sysconf(_SC_CLK_TCK);
378 fclose(fp);
379 }
380 snprintf(path, sizeof(path), "/proc/%d/statm", pid_);
381 fp = fopen(path, "r");
382 if (fp) {
383 long resident;
384 if (fscanf(fp, "%*d %ld", &resident) == 1)
385 info.rss_kb = resident * 4;
386 fclose(fp);
387 }
388 return info;
389 }
390
395 pid_t ppid() const {
396 char path[64];
397 snprintf(path, sizeof(path), "/proc/%d/stat", pid_);
398 FILE *fp = fopen(path, "r");
399 if (!fp) return -1;
400 pid_t ppid;
401 fscanf(fp, "%*d %*s %*c %d", &ppid);
402 fclose(fp);
403 return ppid;
404 }
405
411 static bool daemonize() {
412 pid_t pid = ::fork();
413 if (pid < 0) return false;
414 if (pid > 0) std::exit(0);
415 if (setsid() < 0) return false;
416 pid = ::fork();
417 if (pid < 0) return false;
418 if (pid > 0) std::exit(0);
419 chdir("/");
420 close(STDIN_FILENO);
421 close(STDOUT_FILENO);
422 close(STDERR_FILENO);
423 open("/dev/null", O_RDONLY);
424 open("/dev/null", O_WRONLY);
425 open("/dev/null", O_WRONLY);
426 return true;
427 }
428 };
429}
bool kill() const
向进程发送 SIGKILL 信号强制杀死。
Definition process.h:342
static Process fork()
经典 fork - 复制当前进程。
Definition process.h:201
pid_t pid_
被管理的进程 ID
Definition process.h:122
static Process self()
获取当前进程对象。
Definition process.h:245
Process()
默认构造函数,创建无效进程对象。
Definition process.h:147
bool terminate() const
向进程发送 SIGTERM 信号请求终止。
Definition process.h:336
bool poll(ExitStatus *status) const
非阻塞查询子进程退出状态。
Definition process.h:277
pid_t ppid() const
获取进程的父进程 ID。
Definition process.h:395
static Process invalid()
无效进程对象常量。
Definition process.h:142
bool stop() const
向进程发送 SIGSTOP 信号暂停执行。
Definition process.h:348
ExitStatus wait() const
等待子进程退出(阻塞)。
Definition process.h:257
static int sys_kill(pid_t pid, int sig)
向指定进程发送信号。
Definition process.h:136
static Process spawn_detach(int(*fn)(void *), void *arg)
发射后不管模式创建子进程。
Definition process.h:231
bool is_alive() const
检查进程是否存活。
Definition process.h:318
Process(Process &&other) noexcept
移动构造函数。
Definition process.h:168
static Process parent()
获取父进程对象。
Definition process.h:251
Process(const Process &)=delete
拷贝构造函数(删除)。
Process & operator=(Process &&other) noexcept
移动赋值运算符。
Definition process.h:177
bool resume() const
向进程发送 SIGCONT 信号恢复执行。
Definition process.h:354
Process & operator=(const Process &)=delete
拷贝赋值运算符(删除)。
static Process wait_any(ExitStatus *status)
等待任意子进程退出(阻塞)。
Definition process.h:299
Process(pid_t pid)
私有构造函数,通过 pid 创建 Process 对象。
Definition process.h:128
bool valid() const
检查进程对象是否有效。
Definition process.h:195
~Process()=default
析构函数。
ProcessInfo get_info() const
获取进程详细信息。
Definition process.h:360
static bool daemonize()
将当前进程守护化为后台服务进程。
Definition process.h:411
static Process spawn(int(*fn)(void *), void *arg)
创建子进程执行指定函数。
Definition process.h:214
pid_t pid() const
获取进程 ID。
Definition process.h:189
bool send_signal(Signal sig) const
向进程发送信号。
Definition process.h:328
本库所有组件所在的顶层命名空间。
Signal
常用信号枚举。
Definition process.h:52
@ Terminate
终止信号
Definition process.h:54
@ Stop
停止进程信号
Definition process.h:56
@ Interrupt
中断信号 (Ctrl+C)
Definition process.h:53
@ Kill
强制杀死信号
Definition process.h:55
@ User1
用户自定义信号1
Definition process.h:59
@ Hangup
挂起信号
Definition process.h:58
@ User2
用户自定义信号2
Definition process.h:60
@ Continue
继续运行信号
Definition process.h:57
进程退出状态,包含完整退出信息。
Definition process.h:67
int term_signal() const
获取终止信号。
Definition process.h:95
bool core_dumped
是否产生 core dump
Definition process.h:71
int exit_code() const
获取退出码。
Definition process.h:89
int code
退出码(正常退出时有效)
Definition process.h:68
ExitStatus()
构造函数,初始化所有成员为默认值。
Definition process.h:76
bool signaled
是否由信号终止
Definition process.h:69
int signal
终止信号的编号
Definition process.h:70
bool normal() const
检查进程是否正常退出。
Definition process.h:83
进程详细信息。
Definition process.h:102
bool running
进程是否在运行
Definition process.h:107
pid_t pid
进程 ID
Definition process.h:103
pid_t ppid
父进程 ID
Definition process.h:104
double cpu_time
CPU 使用时间 (秒).
Definition process.h:106
ProcessInfo()
构造函数,初始化所有成员为默认值。
Definition process.h:112
long rss_kb
常驻内存大小 (KB)
Definition process.h:105