让我解释一下:我已经在Linux上开发了一个应用程序,它Forking 并执行一个外部二进制文件,然后等待它完成.结果通过shm文件传达,这些文件是fork+流程独有的.整个代码封装在一个类中.

现在我正在考虑通过线程来加快进程.拥有许多不同的类函数实例(使用不同的参数)可以并发地Forking 和执行二进制文件,并将结果与它们自己独特的shm文件进行通信.

这个线安全吗?如果我在一根线内Forking ,除了安全之外,还有什么我必须注意的吗?非常感谢您的任何建议或帮助!

推荐答案

问题是fork()只复制调用线程,子线程中的任何互斥锁都将永远锁定在fork子线程中.pthread解决方案是pthread_atfork()个处理程序.我们的 idea 是可以注册3个处理程序:一个预工作处理程序、一个父处理程序和一个子处理程序.当fork()发生时,在fork之前调用prefork,并期望获得所有应用程序互斥体.父进程和子进程都必须分别释放父进程和子进程中的所有互斥体.

但这并不是故事的结尾!库调用pthread_atfork为特定于库的互斥体注册处理程序,例如Libc就是这样做的.这是一件好事:应用程序不可能知道由第三方库持有的互斥体,因此每个库必须调用pthread_atfork,以确保在发生fork()的情况下清除自己的互斥体.

问题是,为不相关的库调用pthread_atfork个处理程序的顺序是未定义的(这取决于程序加载库的顺序).因此,这意味着,从技术上讲,由于竞争条件,在预工作处理程序内部可能会发生死锁.

例如,考虑这个序列:

  1. 线程T1调用fork()
  2. libc预处理程序在T1中被调用(例如,T1现在持有所有libc锁)
  3. 接下来,在线程T2中,第三方库a获取自己的互斥AM,然后进行需要互斥的libc调用.这会阻塞,因为libc互斥锁由T1持有.
  4. 线程T1运行库A的预工作处理程序,它阻止等待获取由T2持有的AM.

这就是你的死锁,它与你自己的互斥或代码无关.

这实际上发生在我曾经参与的一个项目上.我当时的建议是 Select fork 或线,但不能两者兼而有之.但对于某些应用程序来说,这可能并不实用.

Linux相关问答推荐

grep条件仅抓取某些文本

如何删除字符串中的`{{i:`and `}}`

当页面对齐关闭时,x86—64上的对象中的成员初始化器的Clang代码生成错误?

是否可以在Bash正则表达式中排除?

在Linux中随机化txt文件但保证不重复行

使用 ansible 验证 firewalld 配置

为什么 perf stat 不计算 cycles:u 在 BIOS 中禁用超线程的 Broadwell CPU 上?

使用 awk 从文件中检索一组特定的字符串

在 SLURM 作业(job)脚本中设置和传递字符串变量

使用 bash 在包含模式的 java 文件中查找行,然后替换该行的另一部分

在 64 位 Linux 操作系统上编译 32 位程序导致致命错误

你如何在 C 中的 Linux 上进行非阻塞控制台 I/O?

bashrc 在运行 bash 命令之前不会加载

'&&' 与 '&' 与 Bash 中的 'test' 命令

Linux 中的直接内存访问

有什么方法可以在linux中保留但不提交内存?

将所有文件扩展名转换为小写

如何使用终端打开-虚线文件名?

在类 Unix 系统中上次运行的 cron 作业(job)的详细信息?

在linux中根据内容拆分文件