大家好,关于还记得工业控制电池检测系统的.NET 卡住分析吗很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
0:000:x86 !clrstackOS 线程ID:0x4a08 (0)子SP IP 呼叫站点012fe784 0000002b [HelperMethodFrame_1OBJ: 012fe784] System.Threading.WaitHandle.WaitOneNative(System.Runtime.InteropServices.SafeHan dle ,UInt32,布尔值,布尔值)012fe868 7115d952 System.Threading.WaitHandle。 InternalWaitOne (System.Runtime.InteropServices.SafeHandle, Int64, 布尔值, 布尔值) [f:\dd\ndp\clr\src\BCL\system\threading\waithandle.cs @ 243]012fe880 7115d919 System.Threading.WaitHandle.WaitOne(Int32 ,布尔) [f:\dd\ndp\clr\src\BCL\system\threading\waithandle.cs @ 194]012fe894 711e89bf System.Threading.WaitHandle.WaitOne(Int32) [f:\dd\ndp\clr\src\BCL \system\threading\waithandle.cs @ 220]012fe89c 6fb186b8 System.Threading.ReaderWriterLockSlim.WaitOnEvent(System.Threading.EventWaitHandle, UInt32 ByRef, TimeoutTracker, EnterLockType)012fe8e0 6fb17892 System.Threading.ReaderWriterLockSlim.TryEn terReadLockCore(TimeoutTrack呃)012fe920 6fb17562 系统.Threading .ReaderWriterLockSlim.TryEnterReadLock(TimeoutTracker)012fe94c 0325f49f xxx.QuyitpjK0dXKR6IyqH(System.Object)012fe964 0325ee8a xxx.RWAutoLock.ctor(System.Threading.ReaderWriterLockSlim, Boolean). 从六角形中的线程堆栈数据来看,看来是卡在读写锁TryEnterReadLock上,根据读写锁的规则,肯定有人执行了WriteLock,无法退出。下一步是找到持有该锁的线程。
2. 到底谁在持有
如果是lock的话,相信很多朋友都知道使用!syncblk命令。那么读写锁用什么命令呢?说实话,我想不通。我只能深入研究ReaderWriterLockSlim 类本身,看看是否有任何新内容。
0:000:x86 !DumpObj /d 03526f38Name: System.Threading.ReaderWriterLockSlimMethodTable: 6f947428EEClass: 6f9a92dcSize: 72(0x48) bytesFile: C:\Windows\Microsoft.Net\Assembly\GA C_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dllFields: MT 字段偏移类型VT Attr 值Name70da878c 40004aa 38 System.Boolean 1 实例0 _fIsReentrant6f92fa28 40004ab 3c .LockSlim+SpinLock 1 实例03526f74 _spinLock70dfba4c 40004ac 1c System.UInt32 1 实例20 _numWriteWait 70dfba4c 40004ad 20 System.UInt32 1 实例1 _numReadWaiters70dfba4c 40004ae 24 System.UInt32 1 个实例0 _numWriteUpgradeWaiters70dfba4c 40004af 28 System.UInt32 1 个实例0 _numUpgradeWaiters6f93d764 40004b0 39 System.Byte 1 个实例0 _waiterStates70da42a8 40004b1 2c System.Int32 1 个实例-1 _upgradeLockOwnerId 70da42a8 40004b2 30 System.Int32 1 实例11 _writeLockOwnerId70da6924 40004b3 c .g.EventWaitHandle 0 个实例034844d0 _writeEvent70da6924 40004b4 10 .g.EventWaitHandle 0 个实例042a69c8 _readEvent70da6924 40004b5 14 .g.EventWaitHandle 0 个实例00000000 _upgradeEvent70da6924 40004b6 18 .g .EventWaitHandle 0 实例00000000 _waitUpgradeEvent70da150c 40004b8 4 System.Int64 1 实例367 _lockID70da878c 40004ba 3a System .Boolean 1 实例0 _fUpgradeThreadHoldingRead70dfba4c 40004bc 34 System.UInt32 1 实例3221225472 _owners70da878c 40004c2 3b System.Boolean 1 实例0 _fDispose70da42a8 40004a9 4dc System.Int32 1 静态4 ProcessorCount70da150c 40004b7 4d4 System.Int64 1 静态1882 s_nextLockID6f942b7c 40004b9 0 .ReaderWriterCount 0 TLstatic t_rwc 结合源码分析,发现上面的_writeLockOwnerId=11就是持有锁的线程ID。很容易找到固定线。将这个managementid=11转换为dbgid,再次观察。
0:000:x86 !t 13 11 47bc 0a0702c0 1029220 抢占式00000000:00000000 01425ed0 0 MTA (线程池工作线程) 0:013:x86 !clrstackOS 线程ID3 33 600x47bc (13)子SP IP 呼叫站点07e4f1ac 0000002b [InlinedCallFrame: 07e4f1ac] 07e4f1a4 09e38597 DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr)07e4f1ac 09e38334 [InlinedCallFrame33 360 07e4f1ac] System.Data.SQLite.UnsafeNativeMethods.sqlite3_step(IntPtr)07e4f1dc 09e38334 System.Data.SQLite.SQLite3.Step(System.Data.SQLite.SQLiteStatement)07e4f228 09e36fe8 System.Data.SQLite.SQLiteDataReader.NextResult()07e4f250 09e36ce系统.Data .SQLite.SQLiteDataReader .ctor(System.Data.SQLite.SQLiteCommand, System.Data.CommandBehavior)07e4f270 09e367ce System.Data.SQLite.SQLiteCommand.ExecuteReader(System.Data.CommandBehavior)07e4f284 09e36732 System.Data.SQLite。 SQLite 命令。 ExecuteNonQuery(System.Data.CommandBehavior)07e4f2b0 09e366e6 System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()07e4f2bc 09e350dc SqlSugar.AdoProvider.ExecuteCommand(System.String, SqlSugar.SugarParameter[])07e4f388 1 3189518 `1[[系统。 __Canon, mscorlib]].ExecuteCommand()07e4f420 0181ac4a xxx.OperateLog+d__8.MoveNext().0:013:x86 kCvRegToMachine(x86)0x14fX86MachineInfo:SetVal: 请求未知寄存器0 # ChildEBP Ret地址00 07e4ede0 76c9ad10 ntdll_76ed0000!NtFlushBuffersFile+0xc01 07e4ede0 6b27af8c 内核库!FlushFileBuffers+0x30WARNING: 堆栈展开信息不可用。以下框架可能有误。02 07e4edf0 6b270256 SQLite_Interop!SI768767362ea03a94+0xf73c03 07e4ee1c 6b267938 SQLite_Interop!SI768767362ea03a9 4+0x4a0604 07e4ee38 6b2599e1 SQL ite_Interop!SI83d1cf4976f57337+0x84c805 07e4ee80 6b25902b SQLite_Interop!SIa3401e98cbad673e+0x320106 07e4ee98 6b25258c SQLite _Interop!SIa3401e98cbad673e +0x284b0 7 07e4f168 6b255a05 SQLite_Interop!SI327cfc7a6b1fd1fb+0x633c08 07e4f19c 09e38597 SQLite_Interop!SI9c6d7cd7b7d38055+0x255 大概知道写锁是用来写sqlite的,后者卡在缓冲区刷新函数NtFlushBuffersFile上,方法签名如下:
NTSTATUS NtFlushBuffersFile(HANDLE FileHandle, IO_STATUS_BLOCK *IoStatusBlock);有的朋友可能想看看怎么写,那么简单反编译一下代码:
至此,我们基本搞清楚了,因为13号线程持有写锁,导致主线程想要使用读锁操作sqlite时,等待了很长时间。
解决方案相对简单。主线程应该尽可能只做UI更新操作。不要让它触发各种锁,否则有等待锁的可能。
3. NtFlushBuffersFile 怎么了
有的朋友可能会问为什么NtFlushBuffersFile函数会卡住不返回。要找到这个答案,您需要查看反汇编。
0:013:x86 uf ntdll_76ed0000!NtFlushBuffersFilentdll_76ed0000!NtFlushBuffersFile:76f41ad0 b84b000000 mov eax,4Bh76f41ad5 ba7071f576 mov edx,偏移ntdll_7 6ed000 0!Wow64SystemServiceCall(76f57170)76f41ada ffd2调用edx76f41adc c20800 ret 80:013:x86 u 76F57170hntdll_76ed0000!Wow64SystemServiceCall:76f57170 ff252892ff 76 jmp双字指针[ntdll_76ed0000!Wow64Transition (76ff9228)]0:013:x86 u 76ec7000wow64cpu! KiFastSystemCall:76ec7000 ea0970ec763300 jmp 0033:76EC700976ec7007 0000 添加字节ptr [eax],al76ec7009 41 inc ecx76ec700a ffa7f8000000 jmp dword ptr [edi+0F8h] 从查看汇编代码中,NtFlushBuffersFile通过KiFastSystemCall进入内核态。用户态转储无法看到内核态,因此也无法进一步追查此案。
但是,您也可以查看该线程过去的GetLastError() 值。使用!gle 命令您可能会有所收获。
0:013:x86 !gleLastErrorValue: (Win32)0x26 (38) – 无法获取错误代码textLastStatusValue: (NTSTATUS)0xc0000008 – 无法获取错误代码文本根据上述状态代码,搜索msdn 了解具体信息。
从错误描述来看,可能是sqlite文件有问题。句柄无效,读取已结束。怀疑是操作sqlite时文件损坏。
现在回过头来看,如果你想对Sqlite进行并发读写,你应该可以开启Write-Ahead Logging模式。程序中不需要控制读写。
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/194212.html
用户评论
我没有爱人i
以前也遇到过卡死问题,好头疼啊!这篇文章写的真详细,把调试过程都捋清楚了,特别是那个内存泄漏点,我之前还真没注意到。以后碰到类似问题能借鉴一下你的思路!
有12位网友表示赞同!
巴黎盛开的樱花
工控系统真是让人捉急呀,一旦出bug就严重影响生产,还好作者分析的很透彻,查出来问题的根源是 .NET 的某个模块,这个知识点我也记下了,避免将来遇到类似情况了。
有14位网友表示赞同!
无寒
每次遇到卡死问题都是头疼,不知道从哪里下手调。幸好找到了这篇文章,详细的记录和步骤让我受益匪浅啊!建议作者后期可以整理成一本电子书,这样更方便大家查阅学习.
有13位网友表示赞同!
杰克
电池检测系统很关键啊,尤其是工控环境下,不能出现任何故障!这个 .NET 部分的分析还行,我觉得这种卡死问题其实也很常见,在工业应用中遇到比较多。文章可以加入一些预防措施和解决方案,更加实用!
有17位网友表示赞同!
娇眉恨
感觉作者经验丰富,把问题分析的很仔细,每个步骤都说得清楚明白,很容易理解。这篇文章确实是一篇优秀的工控系统故障分析案例。
有6位网友表示赞同!
あ浅浅の嘚僾
我刚开始接触 .NET 开发,遇到这类卡死调试问题还是比较头疼的。感谢作者分享经验,希望能借鉴你的思路来解决类似问题!
有16位网友表示赞同!
矜暮
工控系统的安全性很重要,一旦出现卡死问题,后果不堪设想。文章分析的方法很扎实,但我觉得应该强调一下安全措施的重要性,以便读者更好地理解相关风险。
有7位网友表示赞同!
眷恋
这篇文章对.NET 和工控系统都不太深入。作为一名资深工程师来说,我从中学到了很少东西。如果能提供一些更具体的解决方案或者代码示例会更好。
有11位网友表示赞同!
玻璃渣子
写的不错,把卡死问题的常见原因概括得非常清晰,特别是内存泄漏的分析很实用。但是希望作者可以结合一些案例进行讲解,更容易理解和记忆。
有5位网友表示赞同!
良人凉人
我觉得工控系统调试其实就是逻辑思维和代码能力,遇到这种情况需要不断分析和测试,才能找到问题所在!这篇博文确实提醒了我这方面知识的重要性的。
有12位网友表示赞同!
服从
说实话,我感觉这个标题有点夸大了。文章里面主要讲.NET 卡死问题,工控电池检测系统只是个例而已。而且缺乏一些具体的案例分析,让人感觉比较抽象。
有6位网友表示赞同!
有恃无恐
我很赞赏作者分享的经验,这种卡死分析方法确实很有帮助!我平时开发 .NET 程序也会遇到类似的问题,感谢这位博主提供思路和解决方案!
有7位网友表示赞同!
容纳我ii
工控系统和普通软件不太一样,需要更加考究可靠性,因此卡死问题格外让人头疼。 作者的分析思路很清晰,但对于具体解决方法,建议可以更详细地阐述,比如具体的代码修改或架构调整等。
有20位网友表示赞同!
寒山远黛
文章比较注重逻辑推理和调试步骤讲解,缺少一些技术细节的讨论,比如.NET平台特定性能问题的原因等。不过总体来说还是很有帮助的!
有20位网友表示赞同!
花海
这篇文章虽然没有具体案例分析,但对 .NET 卡死问题的常见原因做了很好的总结,非常适合作为新手入门了解这类问题的思路。 希望作者以后能结合实际项目分享更多的经验。
有9位网友表示赞同!
久爱不厌
工控系统开发的确需要考虑到很多安全性问题,卡死问题就是其中的一部分。这篇博文提醒了我们要注意代码质量和测试用例的完善度,才能避免类似问题的发生!
有14位网友表示赞同!
一笑抵千言
作为一名 .NET 开发者,遇到卡死问题的确很烦躁。这篇博客帮了我理解卡死的原因以及分析思路,受益匪浅!
有6位网友表示赞同!