关于windows多线程对同一个HANDLE并发读写死锁问题
1.一般情况下不会对普通文件同时多线程读或者写。
2.典型场景就是windows有COM口.一个线程读,一个线程写。明显读写都挂住了。
3.如何分析死锁问题,在用户态和内核态思路是一致的,找到线程等待的对象,分析为啥会等待这个对象,比如linux如果是pthread mutex死锁,直接gdb aatach 上去,把所有线程栈显示出来。
如果是内核态,cat /proc/$pid/*/stack,这里可以查看内核态的栈非常简单哈。或者使用crash工具,当然请安装调试符号。
4.windows用户态使用windbg,方式跟linux用户态类似。内核态需要使用类似linux crash工具,livekd好像能完成这件事,但是我还是选择使用把windows内核调试
模式打开,使用windbg local kernel debug 功能,非常有用
5.上面都是讲方法学,具体如果多线程同时同步读写同一个文件为什么会挂死呢?我使用方法四,先把挂死进程的内核栈打印出来
6.上面是两个读写线程的内核栈,从栈上来看,写线程挂在了IopAcquireFileObjectLock,而读明显是等待有数据可读正常让出CPU,
因此关注点放在IopAcquireFileObjectLock,这时候有几种方法接下来分析:
1)直接IDA 分析为什么会调用IopAcquireFileObjectLock,当然这个比较复杂
2)直接上源码,源码有很多选择,可以选择官方WRK,可以选择泄露的NT4的内核源码和Windows NT 2000的,Windows xp,包括最进完整泄露的Windows Server 2003,
当然有ReactOS源码这个代码基本就是XP的逆向复刻,可参考性非常强。当然哈windows 内核源代码质量非常高,认真学习可以了解很多windows内部原理的一些东西。
7.我们这里直接通过函数名 IopAcquireFileObjectLock分析,这个好像在获取文件对象锁,也就是说Windows IO 子系统就是这么设计的,如果你想要使用同步IO,它系统外层限制
你并发读写,如果你想要并发读写,他推荐你使用它自代的重叠IO技术。非常有意思哈。