fork中的死锁问题

news/2024/10/16 7:22:01 标签: c++, fork, linux

背景

当我们通过fork去创建子进程时,当父/子进程都涉及到锁的操作,可能会产生死锁。

代码样例

#include <iostream>
#include <mutex>
#include <unistd.h>
std::mutex m;
int main() {
    std::cout << "main process begin" << std::endl;
    m.lock();
    int pid = fork();
    if (pid == -1) {
        std::cout << "fork failed" << std::endl;
        return -1;
    }
    if(pid == 0){ // 子进程
        m.lock();
        std::cout << "child process run" << std::endl;
    } else {
    }
	m.unlock();
    while (true) {

    }
    return 0;
}

代码示例中,父进程持有锁m,然后通过fork进行进程的创建,这个时候子进程里也进行锁操作,这个时候子进程就会死锁在这里

根因

当我们通过fork创建子进程时,进程会继承父进程的内存空间(写时复制技术,copy-on-write),包括代码段,堆栈,堆和数据段。
在子进程中锁定m时,这个时候从父进程里继承的m的锁状态处于锁定状态,这是再去m.lock,那就会死锁。

一些解决方法

如果子进程能够访问到锁,那锁定前先解锁

    if(pid == 0){ // 子进程
       m.unlock(); // 锁定前,先解锁
       m.lock();
       std::cout << "child process run" << std::endl;
   } else {
   }

fork_42">如果子进程不方便访问到锁,使用 pthread_atfork()

std::mutex m;
void child() {
 m.unlock();
}
int main() {
   pthread_atfork(nullptr, nullptr, child); //  三个参数分别时,prepare,parent,child
}
  • prepare 处理器在 fork() 调用之前执行,通常用于获取那些需要在 fork() 期间保持的锁。
  • parent 处理器在 fork() 调用之后,在父进程中执行,通常用于释放 prepare 处理器中获取的锁。
  • child 处理器在 fork() 调用之后,在子进程中执行,也通常用于释放 prepare 处理器中获取的锁。

总结

  1. 我们要尽量在多线程程序中使用fork()
  2. 使用fork()后立即调用exec()
  3. 避免在持有锁时调用fork()
    当然当我们编写多进程大型程序时,很难避免,特别是引用了一些三方库这些不受控的代码

http://www.niftyadmin.cn/n/5707551.html

相关文章

ROS2初级面试题汇总

大家好&#xff0c;我是小白小帅&#xff0c;在日常基于ros2开发移动机器人和学习过程中&#xff0c;个人总结和收集了一些关于ros2的问题&#xff08;共25道&#xff09;&#xff0c;这些问题也是面试中可能涉及到的一些知识点&#xff0c;对于我个人就是一个简单的记录&#…

VS如何修改生成的exe程序的名称

一、简述 在日常开发中&#xff0c;我们一般会将工程名称设置为生成的exe程序的名称&#xff0c;在VS编译器中&#xff0c;默认生成的exe名称取自工程名称&#xff0c;所以如果是已经建立好工程&#xff0c;想要修改生成的exe名称&#xff0c;可以通过工程属性修改&#xff1a…

学习vue20.17.0-列表渲染

列表渲染 官方中文网站:列表渲染 | Vue.js (vuejs.org) v-for 我们可以使用 v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名:演示代码: js 代码: const items = ref([{…

Python案例 | 测试网络的下载速度上传速度和 ping 延迟

使用了 speedtest 库来测试网络的下载速度上传速度和 ping 延迟 注意&#xff0c;这里需要先卸载speedtest&#xff0c;再安装speedtest-cli pip uninstall speedtest pip install speedtest-cli其次运行代码&#xff1a; # 使用了 speedtest 库来测试网络的下载速度上传速度…

PetaLinux工程的常用命令——petalinux-create

petalinux-create&#xff1a;此命令创建新的PetaLinux项目或组件。 注&#xff1a;有些命令我没用过&#xff0c;瞎翻译有可能会翻译错了&#xff0c;像是和fpgamanager相关的部分。 用法: petalinux-create [options] <-t|--type <TYPE> <-n|--name <COMPONEN…

深入解析CSS中的!important规则

深入解析CSS中的!important规则 一、引言 在CSS的世界里&#xff0c;样式的优先级通常由选择器的特异性、在样式表中的位置&#xff08;后来的规则覆盖先前的规则&#xff09;以及继承等因素决定。然而&#xff0c;!important规则就像一把双刃剑&#xff0c;它可以打破这些规…

TCP(Transmission Control Protocol,传输控制协议)整理

TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的传输协议&#xff0c;它是OSI&#xff08;Open System Interconnection&#xff0c;开放式系统互联&#xff09;模型中的第四层协议&#xff0c;通常使用于网络中的…

多态常见面试问题

1、什么是多态&#xff1f; 多态&#xff08;Polymorphism&#xff09;是面向对象编程中的一个重要概念&#xff0c;它允许同一个接口表现出不同的行为。在C中&#xff0c;多态性主要通过虚函数来实现&#xff0c;分为编译时多态&#xff08;静态多态&#xff09;和运行时多态…