c++ - 实现允许用户在后台运行多个进程(最多同时三个)的 C++ 程序
问题描述
我是 Linux 新手。以下是我的代码。做这个任务对我来说有点复杂,所以我希望有人能给我提示。我感谢您的帮助。
*注意:我自己也搞砸了我的代码。所以它很糟糕而且未完成,但如果没有任何方向,我真的无法继续。
我正在尝试实现一个名为 BP 的 C/C++ 程序,它允许用户在后台运行多个进程(同时最多三个)。当三个进程当前正在运行时,进一步的执行请求将被挂起(进程状态变为“停止”)并等待直到另一个进程停止或终止。当进程在后台运行时,用户可以输入命令来显示后台进程的信息,停止或杀死一个后台进程。
If users' input = bg [name of executable file] [a list of arguments] Action: BP 在后台运行带有参数列表的可执行文件并继续接受来自用户的输入。如果已经有 3 个正在运行的进程,则停止该进程。
bgkill --> 通过用户输入杀死 pid
我的问题是我不知道如何检查进程的状态以确保后台进程不能超过三个。 流程图在这里。
/.....skipped.../ //问题从bg和bgKill开始
void bg(string input) {
// Using waitpid() to check child already finished before
int notRunning = waitpid(bpid, NULL, WNOHANG);
if (notRunning) status = 0;
// Check status
if (status > 3) {
cout << "Stopped. " << endl;
return;
}
// Check name is null or not
if (input == "" || input.length() == 0) {
cout << "BP: > Error: Name is null. " << endl;
return;
}
// Fork a child process
bpid = fork();
if (bpid < 0) exit(EXIT_FAILURE);
else if (bpid > 0) {
// Parent Code
cout << "BP: > Background process started with pid " << bpid << endl;
status += 1;
} else if (bpid == 0) {
// Child Code
// Parse command into array
// Init Array
int size = countArg(input);
char *arg[size + 1];
// Put substring into array
string delimiter = " ";
for (int argCount = 0; argCount < size; argCount++) {
int pos = input.find(delimiter);
arg[argCount] = strdup(input.substr(0, pos).c_str());
input.erase(0, pos + delimiter.length());
}
arg[size] = NULL;
// Execute the command
if (execvp(arg[0], arg) == -1) {
// If execute failed
if (fileExist(arg[0])) {
cout << "execvp() is failed. Do you mean ./" << arg[0] << "?" << endl;
} else cout << "execvp() is failed." << endl;
}
}
}
void bgKill(string pidStr) {
// Check status
if (status == 0) {
cout << "BP: > No background process to kill." << endl;
return;
}
// Check the pid is the background pid
int pid = atoi(pidStr.c_str());
if (pid == 0 || pid != bpid) return invalidProcess(pid);
// Kill the process
kill(pid, SIGTERM);
cout << "BP: > Background process with pid " << pid << " was killed." << endl;
// Reset all flag
status = 0;
bpid = 0;
}
解决方案
有三个选项:
阻止
waitpid
。这不是直接的选项,因为您需要同时响应输入,但您可以执行以下操作之一:- 阻塞子进程并使用管道或 eventfd 将更改传回,
- 在单独的线程中阻塞并使用管道、eventfd 或共享内存将更改传回
然后,您还应该调整主输入循环以使用
select
,以便您可以响应 STDIN 或子进程/线程上的更改。waitpid
像现在一样进行投票。这类似于以前的方法:将主输入循环重写为select
STDIN 几百毫秒,然后轮询waitpid
是否有变化。- 最后,您可以为
SIGCHLD
. 每当子进程停止或终止时,都会调用此函数,因此您可以响应它(例如,通过启动其中一个挂起的进程或设置一个标志)并返回阻塞输入。
推荐阅读
- java - 如何在不使用任何“ButtonType”控件的情况下在 JavaFx 中创建自定义对话框?
- c++ - 如何在 C++ 中将文本文件的特定行读入 int 类型的数组?
- java - 如何在 Java 中捆绑 getter?
- php - 对 Laravel 查询构建器的 SQL 查询
- r - 将数据帧的每一列除以数据帧的一行
- vba - VBA 代码的结果在 Access 的文本框中不可见
- performance - Flutter:大画布的缩放会降低 FPS
- spring - Spring Data JPA:参数化@Query注解字符串,重构两个相似的@Query方法
- azure-cognitive-services - 如何以编程方式关闭沉浸式阅读器?
- .net - 正确处理 dbnull 值