Browsed by
分类:Threads and Process

setcap wine 遇到的问题解决

setcap wine 遇到的问题解决

之后为了让普通用户也能通过wine访问到网络接口,需要给wine的相关程序(wine-preloader 和 wineserver wine) 一些特权

 

参考  man capabilities 和 setcap

  •  首先需要给CAP_NET_RAW 权限 这个要给到 wine-preloader 上,不过在设置完这个权限之后,执行 wine XXX.exe 会报错

wine: error while loading shared libraries: libwine.so.1: cannot open shared object file: No such file or directory

这是因为特权模式的程序运行的时候是不会检测到相对路径的lib库的, 具体参考文章如下:http://stackoverflow.com/q/6493846/296473  解决方法在文中已有了 就不赘述了

  •  上述问题解决后,运行wine 会提示  Internal errors- Invalid parameters  , 而且winedbg不可以attach到进程, 这个问题的解决方法是给wineserver(不是wine-preloader)CAP_SYS_PTRACE权限

 

 

Windows 下同步(多线程协调)的实现 的简单解释

Windows 下同步(多线程协调)的实现 的简单解释

Windows下的多个线程之间的通信,是通过各种Object进行的, 目前我只了解到EventObject, 下面简单介绍一下什么是EventObject .

我们可以把各个线程想象成一些不同的流水线,比如制作面包的流水线, 一个线程(流水线)负责制作面包,另一个流水线负责将面包包装好,那么这两个流水线就存在逻辑上的顺序, 即使他们同时工作,包装的如果不等制作面包的制作好,是无法进行的. 在系统里也是这样 两个(或者多个)线程之间有依赖关系, 比如B要在A完成后才可以处理,C要等D E完成之后才能处理. 那么,多个线程之间如何协调好这个关系呢. 这时候Windows就使用EventObject来给各个线程发送信号,EventObject可以有名字也可以没有名字, 带名字的在多线程同步时很常用(这里说明一下 ,多个线程之间协调工作就叫同步), 在多线程同步处理事件的时候 , 首先建立好一系列的EventObject(和其他Object) ,然后 线程A执行开始的时候 将EventObjectA设置为FALSE(没被触发状态) 这时 线程B在等待EventObjectA的信号(就是保持挂起状态,一旦有信号激活就会开始执行) , 然后线程A执行完毕之后 , 就会将EventObjectA设置为TRUE (触发状态) 这时, 由于EventObjectA被触发, 线程B也就同时启动了,然后开始执行线程B,这样就实现了线程之间的同步

有关NtCreateEvent和 EventObject的说明 参见msdn文档

https://msdn.microsoft.com/en-us/library/windows/hardware/ff566423(v=vs.85).aspx NtCreateEvent 的介绍

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682655(v=vs.85).aspx EventObject的介绍

gdb 下调试多线程

gdb 下调试多线程

最近接触的工作需要多线程的一些知识才能完成,而以前没有多线程相关知识,现在进行一些简单的学习和研究.本文内容偏向实践,对于想要了解原理的请去看计算机线程方面的资料和书籍.

1.gdb下调试多进程代码的注意事项

最近在调试这样一段代码的时候, 由于我不具备任何多线程的知识,导致我在找错误的时候出现了严重的问题,代码如下:

调试环境为在Linux下的Wine下运行的MSYS2(32bit) 在MSYS2内运行的gdb, 这段代码在运行到

这一行的时候 就出现了错误,导致我认为是fork出了问题,不过实际上不是这样的, 在我了解fork的具体操作后,才明白了为什么错误不发生在fork这一行但是却在fork上报错. 下面将会解释上面这个问题  首先要从fork的应用来说.

通过查看 man 2 fork我们可以了解到fork的使用方法和返回值的含义,  fork的作用是在某一个程序运行到fork()这里的时候 ,新开一个线程,这个线程与原来的线程独立,不过线程内的变量值等信息都与原来的线程一致, (他们不共用内存地址) , 这个线程就称为子进程, 原来的进程就叫做父进程. fork()的返回值为一个进程号, 返回的进程号为当前父进程的子进程的进程号,子进程的这个返回值为0(注意子进程是相对父进程而言) .

另外 在使用gdb调试的时候 ,如果出现了多线程的代码 ,那么不进行任何设置的情况下,gdb不会阻止(控制)子进程的执行,也就是说,就算你在用step in 或者next 对代码进行调试 ,但是遇到了 fork()之后 ,子进程会自动执行从 fork开始到代码末尾的所有语句,不会受gdb控制, 因而 ,如果是在fork之后的代码出了问题, 那么在用没有配置的gdb进行单步调试的时候,代码会在父进程fork之后报错,这样就不便于定位错误的位置. 下面用一段代码来验证一下我的这个说法:

上面这段代码做的事情很简单 ,我就不再多解释 ,将这段代码用 gdb -g -O0 编译之后  在gdb下调试

首先使用 start > tmpfile来启动调试进程, 这样所有的输出都会被重定向到一个文件 ,不会因为gdb的原因导致输出延迟, 然后 使用 next指令 执行完 fork这一行, 然后立即查看tmpfile的内容 你会发现 tmpfile的内容为:

我们明明还没有执行到下一个printf,但是却输出了forked PID is 0 , 通过上文我们知道了 PID为0 意味着打印这个信息的进程为子进程 这也就说明了 gdb没有阻拦子进程的执行 ,让子进程执行完毕了,但是父进程依旧在被gdb控制,因此,如果是fork之后的代码出现了问题,由于未经配置的gdb不能监视子进程,子进程自动执行到出错的地方然后扔出错误信息,但是我们在gdb上看到的现象却是执行fork的时候报错了,这样就导致了判断不出来错误的所在.

2.用gdb调试多线程

那么遇到多线程的代码的时候应该如何调试呢, 官方文档给出了三种方法 https://sourceware.org/gdb/onlinedocs/gdb/Forks.html

相关信息已经有很好的列出,在这里就不多解释了. 不过需要注意一点 ,就是在无法使用 follow-fork-mode 和 follow-exec-mode的时候 (比如kernel版本不对,平台不对之类的问题) 那么就要在代码里插入sleep来进行调试, 这个方法是通用的一个方法

 

3.依旧存在疑惑的地方

上面那段代码 ,如果直接执行(将信息输出到stdout上) 那么结果为:

 

这样三行内容    而如果重定向到文件或者管道的话 ,内容则变为:

四行, 具体一为什么会出现这一现象的原因有待深入学习fork和重定向的相关知识