在大多数UNIX系统上,可以通过fork()轻松地为子进程/父进程在进程之间传递打开的文件; 但是我需要分享一个fd"之后"孩子已经分叉了.
我发现一些网页告诉我sendmsg()可能适用于仲裁过程; 但这似乎非常依赖操作系统和复杂.该portlisten好像我能找到的最好的例子,但我更喜欢一个良好的包装库的libevent一样,隐藏的kqueue的所有魔法,游泳池,...
有谁知道是否有一些库(和便携式方式)这样做?
我听说在程序中混合分叉和线程可能非常有问题,通常会产生神秘的行为,特别是在处理共享资源时,例如锁,管道,文件描述符.但我从未完全明白危险是什么以及何时会发生.如果具有该领域专业知识的人能够更详细地解释在这样的环境中编程时存在哪些陷阱以及需要注意什么,那将是很棒的.
例如,如果我想编写一个从各种不同资源收集数据的服务器,我认为一个解决方案是让服务器生成一组线程,每个popen调用另一个程序来完成实际工作,打开管道从孩子那里获取数据.这些线程中的每一个都响应它自己的工作,没有数据交换它们,并且当收集数据时,主线程有一个队列,这些工作线程只将结果放入队列.这个解决方案可能出现什么问题?
请不要通过"回答"我的示例场景来缩小您的答案范围.任何与示例无关但有助于提供简洁设计的建议,替代解决方案或体验都会非常棒!谢谢!
我正在讨论fork()Vs thread()相对于任务并行化的相对成本.
我们了解进程Vs Thread之间的基本区别
线:
流程:
但我们不同意流程Vs线程的启动成本.
因此,为了测试理论,我编写了以下代码.我的问题:这是衡量启动成本的有效测试,还是我遗漏了一些东西.此外,我对每个测试在不同平台上的表现感兴趣.
#include <boost/lexical_cast.hpp>
#include <vector>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
extern "C" int threadStart(void* threadData)
{
return 0;
}
int main(int argc,char* argv[])
{
int threadCount = boost::lexical_cast<int>(argv[1]);
std::vector<pid_t> data(threadCount);
clock_t start = clock();
for(int loop=0;loop < threadCount;++loop)
{
data[loop] = fork();
if (data[looo] == -1)
{
std::cout << "Abort\n";
exit(1);
}
if (data[loop] == 0)
{
exit(threadStart(NULL));
}
}
clock_t middle = clock(); …Run Code Online (Sandbox Code Playgroud) 我有一些Python代码偶尔需要跨越一个新进程来以"一劳永逸"的方式运行shell脚本,即没有阻塞.shell脚本不会与原始Python代码通信,实际上可能会终止调用Python进程,因此启动的shell脚本不能是调用Python进程的子进程.我需要它作为一个独立的过程启动.
换句话说,假设我有mycode.py并启动script.sh.然后mycode.py将继续处理而不会阻塞.脚本script.sh将独立完成一些操作,然后实际停止并重新启动mycode.py.因此运行script.py的进程必须完全独立于mycode.py.我怎么能这样做?我认为subprocess.Popen不会阻塞,但仍然会创建一个子进程,一旦mycode.py停止就会终止,这不是我想要的.
有一个有点著名的 Unix 脑筋急转弯:写一个if表达式,使下面的程序打印Hello, world!在屏幕上。该expr中if必须是合法的C表达式,不应包含其他的程序结构。
if (expr)
printf("Hello, ");
else
printf("world!\n");
Run Code Online (Sandbox Code Playgroud)
答案是fork()。
当我年轻的时候,我只是笑了笑,忘记了。但是重新思考它,我发现我无法理解为什么这个程序比它应该的可靠得惊人。之后的执行顺序fork()无法保证并且存在竞争条件,但在实践中,您几乎总是看到Hello, world!\n,从不world!\nHello,。
为了证明这一点,我运行了 100,000 轮程序。
for i in {0..100000}; do
./fork >> log
done
Run Code Online (Sandbox Code Playgroud)
在 Linux 5.9 (Fedora 32, gcc 10.2.1, -O2) 上,执行 100001 次后,子只赢了 146 次,父赢率为 99.9985%。
$ uname -a
Linux openwork 5.9.14-1.qubes.x86_64 #1 SMP Tue Dec 15 17:29:47 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ wc -l log
100001 log …Run Code Online (Sandbox Code Playgroud) 我如何实现一些逻辑,允许我fork()使用Python 在Windows上使用系统调用在Linux上重现我的功能?
我特意尝试在SAPI Com组件上执行一个方法,同时继续主线程中的其他逻辑而不阻塞或等待.
我有一个漫长的运行过程,我需要它来启动另一个进程(这将运行一段时间).我只需要启动它,然后完全忘记它.
我设法通过从编程Ruby书中搜索一些代码来做我需要的东西,但我想找到最佳/正确的方法,并了解正在发生的事情.这是我最初得到的:
exec("whatever --take-very-long") if fork.nil?
Process.detach($$)
Run Code Online (Sandbox Code Playgroud)
那么,这是方式,还是我应该怎么做呢?
检查下面的答案后,我最终得到了这段代码,这似乎更有意义:
(pid = fork) ? Process.detach(pid) : exec("foo")
Run Code Online (Sandbox Code Playgroud)
我很欣赏有关如何fork运作的一些解释.[已经得到了]
分离$$对吗?我不知道为什么会这样,我真的很想更好地掌握这种情况.
我想分叉多个进程,然后在它们上使用信号量.这是我尝试过的:
sem_init(&sem, 1, 1); /* semaphore*, pshared, value */
.
.
.
if(pid != 0){ /* parent process */
wait(NULL); /* wait all child processes */
printf("\nParent: All children have exited.\n");
.
.
/* cleanup semaphores */
sem_destroy(&sem);
exit(0);
}
else{ /* child process */
sem_wait(&sem); /* P operation */
printf(" Child(%d) is in critical section.\n",i);
sleep(1);
*p += i%3; /* increment *p by 0, 1 or 2 based on i */
printf(" Child(%d) new value of *p=%d.\n",i,*p);
sem_post(&sem); /* …Run Code Online (Sandbox Code Playgroud) 我真的不确定POSIX对fork存在线程和信号的安全性的要求.fork被列为异步信号安全功能之一,但如果库代码有可能注册了pthread_atfork非异步信号安全的处理程序,这是否会否定安全性fork?答案取决于运行信号处理程序的线程是否可以使用atfork处理程序所需的资源?或者换句话说,如果atfork处理程序使用同步资源(互斥体等)但是fork从一个从不访问这些资源的线程中执行的信号处理程序调用,程序是否符合要求?
在这个问题的基础上,如果"线程安全"分叉在系统库内部使用建议的惯用语实现pthread_atfork(获取prefork处理程序中的所有锁并释放父和子postfork处理程序中的所有锁),那么就是fork安全的在线程程序中使用信号处理程序?处理信号的线程是否可能处于调用malloc或fopen/ fclose和持有全局锁的过程中,从而导致死锁fork?
最后,即使fork在信号处理程序中是安全的,在信号处理程序中是否安全fork然后从信号处理程序返回,或者fork在信号处理程序中进行调用总是需要后续调用函数_exit或其中一个exec函数.信号处理程序返回
我知道它可以是其中之一.但我总是看到孩子在我的UNIX终端上首先执行.此外,为什么父和子并行执行.他们似乎在连续执行.这是因为他们共用同一个终端吗?