DllMain中不当操作导致死锁问题的分析--死锁介绍

DllMain()限入死锁问题分析 (一) 这个经典的同步问题,有很多文章讲过,写这篇博客,权当是疏理一下相关的技术概念和分析方法。 阅读详情

(转载于breaksoftware的csdn博客)

最近在网上看到一些关于在DllMain中不当操作导致死锁的问题,也没找到比较确切的解答,这极大吸引了我研究这个问题的兴趣。我花了一点时间研究了下,正好也趁机研究了下进程对DllMain的调用规律。因为整个研究篇幅比较长,我觉得还是分开写比较能突出重点。本文先说说死锁。

        介绍死锁之前,我说一个我小时候听过的一个故事:

        某国际实验机构将在全球各著名小学做个团队合作的实验。他们在中国选定了一个“被安排的”学校,然后“随机”选出一些学生,让这些学生作为实验的样本参与中国区的实验。实验是这样的:他们在N根细绳一头捆着一支短粉笔,将这些粉笔放到一个细口瓶中。该瓶口只能容一支粉笔自由出入。然后绳的另一头放在学生的手中,告知他们要迅速将自己手中绳子捆住的粉笔从瓶子中拽出来。中国学生经过讨论后,决定出他们的方案。于是123之后,“聪明谦让”的中国学生“一个个”并迅速的将各自的粉笔拽了出来。而同样的实验,在“苦大仇深”的外国学生中结果却不理想。因为他们同时一起往外拽绳子,导致所有的粉笔都卡在瓶口……

        这个故事影响了我很久,我一直在思考:外国人这么笨么?但是现在我回忆这个故事,却想到了这个实验中发生的一些现象和我们在编程中遇到的一些问题是如此的类似。想想,“中国学生”的思路就是“序列化执行”,而外国学生的现象就是因为“竞争”而导致了“死锁”。

        回到正题,我想熟悉计算机的同学应该对“死锁”这个概念并不陌生。我们看一下wiki对Deadlock这个词的解释:

[plain] view plain copy
  1. A deadlock is a situation in which two or more competing actionsare each waiting for the other to finish, and thus neither ever does。  

        也就是说:多个操作相互等待其他结束从而导致它们都无法结束的一种场景。为简单描述,我以两个相互影响因素来描述死锁。


        上图中红色的部分就是故事中“所有粉笔卡在瓶口”那个纠结的时期。于是左右两个例程都纠结于此,不再往下执行。

        以下我列出比较典型的死锁案例

  1. // A线程中 hEventA未激活  
  2. WaitforSingleObject(hEventA, <strong>INFINITE</strong>);  
  3. SetEvent(hEventB);  
  1. // B线程中 hEventB未激活  
  2. WaitforSingleObject(hEventB, <strong>INFINITE</strong>);  
  3. SetEvent(hEventA);  
        线程A、B都在等待对方释放一个事件再释放对方要获得的事件,否则它们都一直等下去。系统看不得它们不工作而傻等,于是就把它们都挂起了。它们就死锁了。想想这和古惑仔片中两个黑帮(线程A、B)相互扣押了对方的卧底(线程A扣押了hEventB,线程B扣押了hEventA),但是两方的老大都要求对方先放人(A线程WaitforSingleObject(hEventA, INFINITE(无线等待)); B线程WaitforSingleObject(hEventB, INFINITE(无线等待));),于是他们就这样僵持下去了(死锁)。如果某方老大富有智慧,会先要求对方一段时间先放人以不失身份,但是等一会儿后(A线程 WAIT_TIMEOUT == WaitforSingleObject(hEventA, 1000(小等一下));),自己先把对方的人先放了(SetEvent (hEventB);)。然后对方老大释怀了(线程B WAIT_OBJECT_0==WaitforSingleObject(hEventB, INFINITE);),再释放潜入的卧底(SetEvent (hEventA);),这样的问题就解决了。可是编程中,出于种种原因,我们很难在一开始就发现是哪儿我们没转过弯。就像我题目中描述的问题,很多人无法理解为什么就在DllMain中加了点代码就死锁了,甚至代码中不包括一点”等“性质的函数(其实是有,只是很隐蔽)。

        我们再看一个教科书式的死锁案例

  1. // A线程  
  2. EnterCriticalSection(&g_csA);  //要进入临界区g_csA  
  3. FunA1();                       //该函数不影响死锁这个必然的结果,只是如果这个函数执行的消耗的时间很完美,将导致死锁出现的概率大增  
  4. EnterCriticalSection(&g_csB);  //要进入临界区g_csB  
  5. FunA2();  
  6. LeaveCriticalSection(&g_csB);  //要退出临界区g_csB  
  7. LeaveCriticalSection(&g_csA);  //要退出临界区g_csA  
  1. // B线程  
  2. EnterCriticalSection(&g_csB);  //要进入临界区g_csB  
  3. FunB1();                       //该函数不影响死锁这个必然的结果,只是如果这个函数执行的消耗的时间很完美,将导致死锁出现的概率大增  
  4. EnterCriticalSection(&g_csA);  //要进入临界区g_csA  
  5. FunB2();  
  6. LeaveCriticalSection(&g_csA);  //要退出临界区g_csA  
  7. LeaveCriticalSection(&g_csB);  //要退出临界区g_csB  
        如果A线程进入g_csA临界区并运行到FunA1()时,B线程进入g_csB临界区,并运行了FunB1()。这个时候,当A线程从FunA1()中退出后,试图进入临界区g_csB时是进入不了的,因为此时B线程还在运行FunB1(),B还在g_csB临界区中,于是A线程等待B退出临界区g_csB。而B线程运行完FunB1()时,将试图进入临界区g_csA,它也进入不了,因为线程A的操作在这个临界区中。于是B就等待A线程退出g_csA。它们相互等待对方退出,而自己却不去主动退出,这样就是挤破了头也没法一起进行下去。最后说一下,此处的FunA1(),FunB1()并不影响死锁产生的结果,但是会影响死锁产生的概率。

        请大家记住这两个例子,我们会在之后分析的DllMain中不当操作导致死锁的案例中再次看到它们的身影。
DllMain和多线程死锁 问题 收集网络上关于 freelibrary 死锁 问题 立即下载

相关推荐

离散数学期末复习笔记【精华版】

文章目录前言一、????理逻辑1. 命题逻辑2. 等值演算3. 主合取范式、主析取范式4. 【题】推理证明5. 辖域、自由变元、约束变元二、????合1. 环和、环积,幂集,笛卡尔乘积三、 ????????关系1. 自反、对称、传递2&3. 合成运算,逆关系、闭包4. 哈斯图、上下界、偏序5. 等价关系、划分四、????1. 幺元(么元、单位元)、零元、逆元,半群、群、阿尔贝群、独异点、循环独异点2. 【题】由表判断3. 【题】证明五、????论1. 简单图、平凡图、多重图、子图、补图、出度、入度、

林大夕可的博客 17万+

DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子

        有了前面两节的基础,我们现在切入正题:研究下DllMain为什么会因为不当操作导致死锁的问题。首先我们看一段比较经典的“DllMain中死锁”代码。(转载请指明出于breaksoftware的csdn博客) //主线程中 HMODULE h = LoadLibraryA(strDllName.c_str());   // DLL中代码 static DWORD WINA...

方亮的专栏 7880

重访时间与覆盖分析的stk操作

1.打开stk 2.创建一个新的场景,命名为Test,选择地球为场景星球,若为金星,可在Central Body里选择Venus(金星自转周期慢,自转周期243天,卫星轨道变化不明显)(其中start stop时间可设置长一些) 3.插入一个AreaTarget或者place,以AreaTarget为例 选择Pattern,Add三个点(用法可见前面的博客,有时候编程的代码也可以帮助理解stk的操作) 4.插入Satellite,选择Orbit Wizard(若想设置卫星的六根数也可

weixin_42664107的博客 1万+

DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)

之前几篇文章主要介绍和分析了为什么会在DllMain做出一些不当操作导致死锁的原因。本文将总结以前文章的结论,并介绍些DllMain中还有哪些操作会导致死锁等问题。(转载请指明出于breaksoftware的csdn博客)DllMain的相关特性 首先列出《DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析》中论证的11个特性: Dll的加...

编程语言小筑 726

全网最全vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法)

markdown-it | markdown-it 中文文档上面的是 markdown-it 中文文档链接 ,供参考使用核心的东西就这些啦,如果有其他想问的,评论区留言即可~博客写作不易,希望大家多多支持,多多捧场~~~最后给大家分享一下 typed.js 网址,网上比较多,我觉得这个比较好理解一些Typed.js - Type your heart out (mattboldt.github.io)[这里是图片011]https://mattboldt.github.io/typed.js/

m0_74825108的博客 3056

喷雾破碎模型解析:从理论到CFD应用实践

本文深入解析喷雾破碎模型的理论基础与CFD应用实践,重点介绍KHRT、TAB和ETAB等主流模型的核心原理与工程调参技巧。通过OpenFOAM实例演示和参数优化建议,帮助工程师精准预测液滴破碎行为,提升燃烧效率与排放控制性能,适用于汽车发动机、燃气轮机等工业场景。

weixin_29281915的博客 498

关于dllMain死锁的问题

前几天遇到了一个死锁问题,查了很久没查出来,最后发现是在dllMain中结束线程导致死锁。 起因:是修改了某个模块,在init函数里启动线程,在uninit函数里结束线程,开始并不知道init和uninit是从dllMain调过来的,也不知道dllmain中结束线程会导致死锁。 具体原因:每次进入dllMain时都会持有一个loader-lock,而结束线程也会进入dllMain,结果就死锁了

mxc的专栏 635

用 MATLAB 实现鼻子和嘴的检测

为了方便起见,这里我们使用了 CascadeObjectDetector 中自带的 haarcascade_frontalface_alt2.xml 文件,该文件包含了多个包含鼻子和嘴的样本图像。其中 bbox 变量表示检测到的所有鼻子和嘴的边界框信息。在图像处理中,鼻子和嘴的检测是十分重要的一项任务。本文将介绍如何使用 MATLAB 实现鼻子和嘴的检测,并提供相应的源代码。然后,我们可以调用之前创建的 detector 对象来进行鼻子和嘴的检测。综上所述,我们可以使用以上代码实现鼻子和嘴的检测。

qq_39605374的博客 256

[转载]DllMain中不当操作导致死锁问题的分析--死锁介绍

(转载于breaksoftware的csdn博客) 最近在网上看到一些关于在DllMain中不当操作导致死锁的问题,也没找到比较确切的解答,这极大吸引了我研究这个问题的兴趣。我花了一点时间研究了下,正好也趁机研究了下进程对DllMain的调用规律。因为整个研究篇幅比较长,我觉得还是分开写比较能突出重点。本文先说说死锁。 介绍死锁之前,我说一个我小时候听过的一个故事: ...

angbagangzhe065140的博客 118

爆破shadow文件密码脚本(完成版)

由于添加了一个for循环,再稍作修改,让password not found!print(f"Trying password:")显示爆破的密码和过程。将代码中的password="123456"替换成下面代码。line.strip()函数首尾去空格。

m0_56578216的博客 771

SAP ABAP 接口管理服务(ZIF)开源项目介绍

接口管理服务(ZIF)开源项目基于 SAP ABAP系统,是一款对标SAP PI/PO 的轻量接口管理产品。他通过独立开发包部署在ABAP系统中,包含接口注册、接口管理、日志服务及其他配套功能,拥有丰富的技术沉淀并通过市场检验,目前已被多家企业应用在SAP ERP系统中。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 1740

DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2

本文介绍使用Windbg去验证《DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子》中的结论,调试对象是文中刚开始那个例子。(转载请指明出于breaksoftware的csdn博客)         1 g 让程序运行起来         2 ctrl+break 中断程序         3 ~ 查看线程数         其实该程序自己运行起来

ProgrammingRing的专栏 950

【第24例】华为 IPD 体系 | RMT 需求管理团队

RMT需求管理团队

产品线负责人 1764

DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析

不知道大家是否思考过一个过程:系统试图运行我们写的程序,它是怎么知道程序起始位置的?很多同学想到,我们在编写程序时有个函数,类似Main这样的名字。是的!这就是系统给我们提供的控制程序最开始的地方(注意这儿是提供给我们的,而实际有比这个还要靠前的main)。于是看到DllMain就可以想到它是干嘛的了:Dll的入口点函数。那何时调用这个函数的呢?以及各种调用场景都传给了它什么参数呢...

方亮的专栏 6672

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

DllMain中不当操作导致死锁问题的分析--DisableThreadLibraryCalls对DllMain中死锁的影响

(转载于breaksoftware的csdn博客) 《windows核心编程》作者在讨论DllMain执行序列化的时候,曾说过一个他的故事:他试图通过调用DisableThreadLibraryCalls以使得新线程不在调用DllMain从而解决死锁问题。但是该方案最后失败了。思考作者的思路,他可能一开始认为:因为线程要调用DllMain而加锁,于是windows在发现DllMain不用调用

ProgrammingRing的专栏 1783

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

DllMain中不当操作导致死锁问题的分析——线程中调用GetModuleFileName、GetModuleHandle等导致死锁

(转载于breaksoftware的csdn博客) 之前的几篇文章已经讲解了在DllMain中创建并等待线程导致的死锁的原因。是否还记得,我们分析了半天汇编才知道在线程中的死锁位置。如果对于缺乏调试经验的同学来说,可能发现这个位置有点麻烦。那么本文就介绍几个例子,它们会在线程明显的位置死锁掉。         DLL中的代码依旧简单。它获取叫EVENT的命名事件,然后等待这个事件被激活。激

ProgrammingRing的专栏 1150

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

[转载]DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2...

(转载于breaksoftware的csdn博客) 本文介绍使用Windbg去验证《DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子》中的结论,调试对象是文中刚开始那个例子。 1 g 让程序运行起来 2 ctrl+break 中断程序 3 ~ 查看线程数 其实该程序自己运行起...

angbagangzhe065140的博客 140

[转载]DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子...

(转载于breaksoftware的csdn博客) 有了前面两节的基础,我们现在切入正题:研究下DllMain为什么会因为不当操作导致死锁的问题。首先我们看一段比较经典的“DllMain中死锁”代码。 //主线程中 HMODULEh=LoadLibraryA(strDllName.c_str()); //DLL中代码...

angbagangzhe065140的博客 138

DllMain中不当操作导致死锁问题的分析--加载卸载DLL与DllMain死锁的关系

(转载于breaksoftware的csdn博客) 前几篇文章一直没有在源码级证明:DllMain在收到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH时会进入临界区。这个论证非常重要,因为它是使其他线程不能进入临界区从而导致死锁的关键。我构造了在DLL被映射到进程地址空间的场景,请看死锁时加载DLL的线程的堆栈         如果仔细看过《DllMai

ProgrammingRing的专栏 1047

[转载] DllMain中不当操作导致死锁问题的分析--加载卸载DLL与DllMain死锁的关系

(转载于breaksoftware的csdn博客) 前几篇文章一直没有在源码级证明:DllMain在收到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH时会进入临界区。这个论证非常重要,因为它是使其他线程不能进入临界区从而导致死锁的关键。我构造了在DLL被映射到进程地址空间的场景,请看死锁时加载DLL的线程的堆栈 如果仔细看过《DllMa...

angbagangzhe065140的博客 186
上一篇: 中断和异常的处理
下一篇: DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
ProgrammingRing
博客等级 码龄17年 76粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值