简体   繁体   English

是否可以在现代 C++ 中使用 fork?

[英]Is it possible to use fork in modern C++?

Traditional C++ was very straightforward and only a library intended to create threads (like pthread) gave rise to other threads.传统的 C++ 非常简单,只有一个旨在创建线程的库(如 pthread)才会产生其他线程。

Modern C++ is much closer to Java with many functions being thread based, with thread pools ready to run asynchronous jobs, etc. It's much more likely that some library, including the standard library, uses threads to compute asynchronously some function, or sets up the infrastructure to do so even if it isn't used.现代 C++ 更接近 Java,许多函数是基于线程的,线程池准备好运行异步作业等。更可能是一些库,包括标准库,使用线程来异步计算某个函数,或者设置即使没有使用,基础设施也可以这样做。

In that context, is it ever safe to use functions with global impact like fork?在这种情况下,使用像 fork 这样具有全球影响力的函数是否安全?

The answer to this question, like almost everything else in C++, is "it depends".这个问题的答案,就像 C++ 中的几乎所有其他事情一样,是“视情况而定”。

If we assume there are other threads in the program, and those threads are synchronizing with each other, calling fork is dangerous.如果我们假设程序中还有其他线程,并且这些线程彼此同步,那么调用fork是危险的。 This is because, fork does not wait for all threads to be a synchronization point (ie mutex release) to fork the process.这是因为, fork不会等待所有线程成为同步点(即互斥锁释放)来 fork 进程。 In the forked process, only the thread that called fork will be present, and the others will have been terminated, possibly in the middle of a critical section.在 fork 进程中,只有调用fork的线程会存在,而其他线程将被终止,可能在临界区的中间。 This means any memory shared with other threads, that wasn't a std::atomic<int> or similar, is an undefined state.这意味着与其他线程共享的任何内存,不是std::atomic<int>或类似的,都是未定义的状态。

If your forked process reads from this memory, or indeed expects the other threads to be running, it is likely not going to work reliably.如果您的分叉进程从此内存读取,或者确实期望其他线程正在运行,则它可能无法可靠地工作。 However, most uses of fork actually have effectively no preconditions on program state .然而, fork大多数用途实际上对程序状态没有先决条件 That is because the most common thing to do is to immediately call execv or similar to spawn a subprocess.那是因为最常见的做法是立即调用execv或类似方法来生成子execv In this case your entire process is kinda "replaced" by some new process, and all memory from your old process is discarded.在这种情况下,您的整个进程有点被一些新进程“替换”,并且旧进程中的所有内存都被丢弃。

tl;dr - Calling fork may not be safe in multithreaded programs. tl;dr - 在多线程程序中调用fork可能不安全。 Sometimes it is safe;有时它是安全的; like if no threads have spawned yet, or evecv is called immediately.就像还没有产生线程一样,或者立即调用evecv If you are using fork for something else, consider using a thread instead.如果您将fork用于其他用途,请考虑改用线程。

See the fork man page and this helpful blog post for the nitty-gritty.有关详细信息,请参阅fork 手册页这篇有用的博客文章

To add to peteigel's answer, my advice is - if you want to fork, do it very early, before any other threads than the main thread are started.要补充 peteigel 的答案,我的建议是 - 如果您想分叉,请尽早进行,在主线程以外的任何其他线程启动之前。

In general, anything you can do in C, you can do in C++, since C++, especially on Linux with clang or gcc extensions, is pretty darn close to a perfect superset of C. Of course, when there are good portable APIs in std C++, use them.一般来说,你可以用 C 做的任何事情,你都可以用 C++ 做,因为 C++,特别是在带有 clang 或 gcc 扩展的 Linux 上,非常接近 C 的完美超集。当然,当 std 中有很好的可移植 API 时C++,使用它们。 The canonical example is preferring std::thread over pthreads C API.规范示例更喜欢 std::thread 而不是 pthreads C API。

One caveat is pthread_cancel, which must be avoided on C++ due to exceptions.一个警告是 pthread_cancel,由于异常,必须在 C++ 上避免使用。 See eg pthread cancel harmful on C++ .参见例如pthread 取消对 C++ 有害

Here is another link that explains the problem: pthread_cancel while in destructor这是另一个解释问题的链接: pthread_cancel while in destructor

In general, C++ cleanup handling is in general easier and more elegant than C, since RAII is part and parcel of C++ culture, and C does not have destructors.一般来说,C++ 清理处理通常比 C 更容易和更优雅,因为 RAII 是 C++ 文化的一部分,而 C 没有析构函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM