检查 C++ 中子进程的状态

发布于 2024-10-21 05:55:34 字数 225 浏览 5 评论 0原文

我有一个使用 fork() 创建子进程的程序。我见过各种使用 wait() 在关闭之前等待子进程结束的示例,但我想知道我可以做什么来简单地检查文件进程是否仍在运行。

我基本上有一个无限循环,我想做一些类似的事情:

if(child process has goneed) break;

我怎样才能做到这一点?

I have a program that uses fork() to create a child process. I have seen various examples that use wait() to wait for the child process to end before closing, but I am wondering what I can do to simply check if the file process is still running.

I basically have an infinite loop and I want to do something like:

if(child process has ended) break;

How could I go about doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

执手闯天涯 2024-10-28 05:55:34

waitpid()WNOHANG 选项结合使用。

int status;
pid_t result = waitpid(ChildPID, &status, WNOHANG);
if (result == 0) {
  // Child still alive
} else if (result == -1) {
  // Error 
} else {
  // Child exited
}

Use waitpid() with the WNOHANG option.

int status;
pid_t result = waitpid(ChildPID, &status, WNOHANG);
if (result == 0) {
  // Child still alive
} else if (result == -1) {
  // Error 
} else {
  // Child exited
}
究竟谁懂我的在乎 2024-10-28 05:55:34

您无需等待子进程直到收到 SIGCHLD 信号。如果您收到该信号,则可以调用 wait 并查看它是否是您正在寻找的子进程。如果你没有收到信号,孩子还在跑。

显然,如果您在子进程完成之前不需要执行任何操作,只需调用 wait 即可。

You don't need to wait for a child until you get the SIGCHLD signal. If you've gotten that signal, you can call wait and see if it's the child process you're looking for. If you haven't gotten the signal, the child is still running.

Obviously, if you need to do nothing unitl the child finishes, just call wait.

┼── 2024-10-28 05:55:34

编辑:如果您只想知道子进程是否停止运行,那么其他答案可能更好。我的更多的是与同步有关,当一个进程可以执行多次计算而不必终止时。

如果您有一些代表子计算的对象,请添加一个方法,例如 bool isFinished() ,如果子计算已完成,该方法将返回 true。对象中有一个私有 bool 成员,表示操作是否已完成。最后,在子进程完成计算时调用的同一个对象上有另一个方法 private setFinished(bool)

现在最重要的是互斥锁。确保每次尝试访问任何成员时都锁定每个对象的互斥锁,包括在 bool isFinished()setFinished(bool) 方法内。

编辑2:(一些面向对象的说明)

由于我被要求解释如何使用面向对象来完成此操作,我将给出一些建议,尽管它很大程度上取决于总体问题,所以把它和一堆盐一起服用。大部分程序都是用 C 风格编写的,而一个对象四处浮动是不一致的。

创建一个名为 ChildComputation 的类

class ChildComputation {

    public:
    //constructor
    ChildComputation(/*some params to differentiate each child's computation*/) : 
        // populate internal members here {
    }
    ~ChildComputation();

    public:
    bool isFinished() {
        m_isFinished; // no need to lock mutex here, since we are not modifying data
    }

    void doComputation() {
        // put code here for your child to execute
        this->setFinished(true);
    }

    private:
    void setFinished(bool finished) {
        m_mutex.lock();
        m_isFinished = finished;
        m_mutex.unlock();
    }

    private:
    // class members
    mutex m_mutexLock; // replace mutex with whatever mutex you are working with
    bool m_isFinished;
    // other stuff needed for computation
}

作为一个简单的例子,您可以在主程序中

ChildComputation* myChild = new ChildComputation(/*params*/);
ChildPID= fork();
if (ChildPID == 0) {
   // will do the computation and automatically set its finish flag.
   myChild->doComputation();
}
else {
   while (1) { // your infinite loop in the parent
       // ...

       // check if child completed its computation
       if (myChild->isFinished()) {
           break;
       }
   }

   // at the end, make sure the child is no runnning, and dispose of the object
   // when you don't need it.
   wait(ChildPID);
   delete myChild;
}

,您可以在其中进行分叉:希望这是有道理的。

重申,我上面写的内容是丑陋的 C 和 C++ 合并(不是在语法方面,而是在风格/设计方面),并且只是为了给您提供帮助在您的上下文中了解与 OO 的同步。

EDIT: If you just want to know if the child process stopped running, then the other answers are probably better. Mine is more to do with synchronizing when a process could do several computations, without necessarily terminating.

If you have some object representing the child computation, add a method such as bool isFinished() which would return true if the child has finished. Have a private bool member in the object that represents whether the operation has finished. Finally, have another method private setFinished(bool) on the same object that your child process calls when it finishes its computation.

Now the most important thing is mutex locks. Make sure you have a per-object mutex that you lock every time you try to access any members, including inside the bool isFinished() and setFinished(bool) methods.

EDIT2: (some OO clarifications)

Since I was asked to explain how this could be done with OO, I'll give a few suggestions, although it heavily depends on the overall problem, so take this with a mound of salt. Having most of the program written in C style, with one object floating around is inconsistent.

As a simple example you could have a class called ChildComputation

class ChildComputation {

    public:
    //constructor
    ChildComputation(/*some params to differentiate each child's computation*/) : 
        // populate internal members here {
    }
    ~ChildComputation();

    public:
    bool isFinished() {
        m_isFinished; // no need to lock mutex here, since we are not modifying data
    }

    void doComputation() {
        // put code here for your child to execute
        this->setFinished(true);
    }

    private:
    void setFinished(bool finished) {
        m_mutex.lock();
        m_isFinished = finished;
        m_mutex.unlock();
    }

    private:
    // class members
    mutex m_mutexLock; // replace mutex with whatever mutex you are working with
    bool m_isFinished;
    // other stuff needed for computation
}

Now in your main program, where you fork:

ChildComputation* myChild = new ChildComputation(/*params*/);
ChildPID= fork();
if (ChildPID == 0) {
   // will do the computation and automatically set its finish flag.
   myChild->doComputation();
}
else {
   while (1) { // your infinite loop in the parent
       // ...

       // check if child completed its computation
       if (myChild->isFinished()) {
           break;
       }
   }

   // at the end, make sure the child is no runnning, and dispose of the object
   // when you don't need it.
   wait(ChildPID);
   delete myChild;
}

Hope that makes sense.

To reiterate, what I have written above is an ugly amalgamation of C and C++ (not in terms of syntax, but style/design), and is just there to give you a glimpse of synchronization with OO, in your context.

苦笑流年记忆 2024-10-28 05:55:34

我在这里发布了与这个问题相同的答案 如何检查进程是否正在 C++ 中运行? 因为这基本上是重复的。唯一的区别是函数的用例。

使用 kill(pid, sig) 但检查 errno 状态。如果您以其他用户身份运行并且无权访问该进程,它将失败并显示 EPERM,但该进程仍然处于活动状态。您应该检查ESRCH,这意味着没有这样的过程

如果您正在运行子进程,则终止将成功,直到调用 waitpid 为止,这也会强制清理所有已失效的进程。

这是一个函数,它返回 true 进程是否仍在运行,并处理清理失效的进程。

bool IsProcessAlive(int ProcessId)
{
    // Wait for child process, this should clean up defunct processes
    waitpid(ProcessId, nullptr, WNOHANG);
    // kill failed let's see why..
    if (kill(ProcessId, 0) == -1)
    {
        // First of all kill may fail with EPERM if we run as a different user and we have no access, so let's make sure the errno is ESRCH (Process not found!)
        if (errno != ESRCH)
        {
            return true;
        }
        return false;
    }
    // If kill didn't fail the process is still running
    return true;
}

I'm posting the same answer here i posted at as this question How to check if a process is running in C++? as this is basically a duplicate. Only difference is the use case of the function.

Use kill(pid, sig) but check for the errno status. If you're running as a different user and you have no access to the process it will fail with EPERM but the process is still alive. You should be checking for ESRCH which means No such process.

If you're running a child process kill will succeed until waitpid is called that forces the clean up of any defunct processes as well.

Here's a function that returns true whether the process is still running and handles cleans up defunct processes as well.

bool IsProcessAlive(int ProcessId)
{
    // Wait for child process, this should clean up defunct processes
    waitpid(ProcessId, nullptr, WNOHANG);
    // kill failed let's see why..
    if (kill(ProcessId, 0) == -1)
    {
        // First of all kill may fail with EPERM if we run as a different user and we have no access, so let's make sure the errno is ESRCH (Process not found!)
        if (errno != ESRCH)
        {
            return true;
        }
        return false;
    }
    // If kill didn't fail the process is still running
    return true;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文