c++ - 从 C++ 程序启动可执行文件并继续

标签 c++

我有一个用 C++ 编写的程序,打算在 Linux 操作系统上运行。忽略大部分程序,它归结为 - 它在一段时间后启动 X 数量的可执行文件(为简单起见,我们使用 5 秒)。

目前,我正在使用 system(path/to/executable/executable_name) 来执行可执行文件的实际启动,这对于让可执行文件到开始。

我还试图维护每个可执行文件的状态(再次为简单起见,我们只说状态是“UP”或“DOWN”(运行或未运行))。我已经能够完成这个......有点......

稍微备份一下,当我的程序被告知启动可执行文件时,逻辑看起来像这样:

pid = fork()
if (pid < 0) exit 0; //fork failed
if (pid == 0) {
   system(path/to/executable/executable_name)
   set executable's status to DOWN
} else {
   verify executable started
   set executable's status to UP
}

这就是我的问题。 fork() 导致生成一个子进程,这是我认为我需要的,以便原始进程继续启动其他可执行文件。 我不想等待一个可执行文件停止后再启动另一个。

但是,可执行文件在另一个子进程中启动...与父进程分开...如果我尝试在系统返回时在子进程中将可执行文件的状态设置为 DOWN,则父进程不知道关于它...

我对我可能需要做的事情有一些想法:

  • 使用线程而不是 fork:创建一个新线程来调用系统,但是父线程/主线程会知道新线程改变了可执行文件的状态吗?
  • 使用 fork 和 exec: 但我不确定这会比我已有的更好(我已经阅读了 fork 和 exec 的手册页,但我想我仍然对如何最好利用 exec)

有什么建议吗?

编辑 1 我想我最好为逻辑提供更多背景信息:

void startAll() {
    for each 'executable'
    call startExecutable(executable_name)
}

...

void startExecutable (executable_name) {
    pid = fork()
    if (pid < 0) exit 0; //fork failed
    if (pid == 0) {
        system(path/to/executable/executable_name)
        set executable's status to DOWN
        exit (1); <-- this is because once the child process's system returns, I don't want it to return to the above loop and start starting executables
    } else {
        verify executable started
        set executable's status to UP
    }
}

编辑 2 正如开头提到的,这是假设一个简化的设置(如果你愿意的话,第一次运行)。计划不仅要处理“UP”或“DOWN”状态,还要处理向我的程序已启动的可执行文件发送消息的第三种状态——“STANDBY”。我最初将这部分内容排除在外是为了避免使解释复杂化,但现在我发现必须包含它。

最佳答案

您需要了解当您fork 时到底发生了什么。您正在做的是创建一个子流程,它是 fork 流程的精确克隆。当前内存中的所有变量都被精确复制,子进程可以访问所有这些变量的所有拷贝。

但它们是拷贝,因此正如您所注意到的,fork 和 exec/system 本身并不处理进程间通信 (IPC)。在其中一个进程中设置内存值不会改变任何其他进程(包括其父进程)中的该变量,因为内存空间不同。

此外,systemexec 非常相似,但您对文件描述符和执行环境的控制要少得多。您实际上已经在进行 fork 和 exec,这是您应该做的。

当您正确地 fork 时(就像您在示例中所做的那样),您现在有两个进程,并且没有一个在等待另一个 - 它们只是在完全不同的代码路径中运行。您基本上想要的是让 parent 什么也不做,只是坐在那里等待新程序打开,偶尔检查 child 的状态,而 children 想跑就跑,想玩就玩。

有 IPC 解决方案,例如管道和消息 FIFO 队列,但在您的情况下这太过分了。就您而言,您只是在寻找流程管理。 parent 被赋予 child 的pid。保存并使用它。您可以调用 waitpid 来等待子进程结束,但您不希望这样。您只希望 parent 检查 child 的状态。一种方法是检查 if kill(childPid,0) == 0。如果不是,那么 pid 已经退出,即它不再运行。您还可以检查 /proc/childPid 以获取各种信息。

如果您的状态没有您的问题所暗示的那么简单,您将需要在 fork 和 execing 之后查看管道。否则,您所需要的只是过程监控。

根据您的EDIT 2,您仍然属于流程管理领域,而不是 IPC。 kill 命令向进程发送信号(如果命令为非 0)。您正在寻找的是让父级 kill(childPid, SIGTSTP)。在子端,您只需要使用 signal 命令创建一个信号处理程序。在许多其他引用资料中,请参阅 http://www.yolinux.com/TUTORIALS/C++Signals.html .基本上,您想要:

void sigTempStopHandler(int signum) { /* ... */ }
signal(SIGTSTP, sigTempStopHandler);

在子代码中执行。父级当然会知道此状态何时发送,因此可以更改状态。您可以在必要时使用其他信号进行恢复。

何时管道与信号:

管道是您可以使用的最强大的 IPC - 它允许您将任意数量的数据从一个进程发送到另一个进程,并且可以按您想要的方向发送。如果你想让你的 parent 把“你一直是个很坏的 child ”发给 child ,可以, child 也可以发给 parent “但总有一天我会选择你的养老院”。 (更简单地说,您可以将任何数据,无论是文本还是二进制数据从一个进程传递到另一个进程 - 包括您序列化的对象,或者如果它不依赖于内存,则只传递对象的原始数据,例如 int。)

到目前为止,您所描述的是将简单的命令结构从父级发送到子级,kill 非常适合此操作。 child 几乎可以很容易地发送信号——除了它需要知道 parent 的 pid 才能做到这一点。 (不难做到 - 在 fork 之前,保存 pid:int pid = getPid();,现在子知道父。)信号没有数据,它们只是非常原始的事件,但是到目前为止,这听起来就是您要查找的全部内容。

关于c++ - 从 C++ 程序启动可执行文件并继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17301181/

相关文章:

c++ - Win32 C++ 在第二个监视器中创建窗口

c++ - 车课(第一次上课)

C++:运算符重载错误:在 '&' token 之前应为非限定 ID

c++: 错误: 无法识别的命令行选项 ‘-std=gnu++14’

c++ - 为什么使用 std::sort() ) 给我垃圾值?

c++ - 为两个序列中第一个匹配项的距离之和提出一个最优算法

python - Eigen 矩阵乘法比 cblas 慢?

c++ - 对类型值的引用绑定(bind)删除限定符

c++ - 跳过整个循环而不运行 while

c++ - 一张一张打开图片