syscall(SYS_gettid)/getpid() 获取当前线程/进程号
strace -tt -T -p tid/pid 获取当前线程/进程运行的系统调用
得到的结果可能为:
ioctl(237, xxx, xxx)
或
futex(0x11f4374, xxx, xxx)
通过系统调用中第一个参数,可以知道锁的地址或者ioctl的fd等
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
#if __WORDSIZE == 64
unsigned int __nusers;
#endif
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
#if __WORDSIZE == 64
int __spins;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
#else
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
#endif
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
当是线程锁时,若知道了锁的地址,即__lock的地址(如0x11f4374),往后+8,即偏移两个int(一个int四个字节),即可得到__owner的地址(如0x11f437c),然后关掉程序的软狗和硬狗,使用gdb调试主进程(如test_strace,首先使用ps得到test_strace的进程号,如1230):
./gdb -p 1230
使用
p *(int *)0x11f437c
得到__owner的线程/进程号(如1298),使用
cat /proc/1230/task/1298/status
可以看到当前线程/进程信息
继续使用
strace -tt -T -p tid/pid
看当前线程还在等待什么锁,一层层往下分析,找到源头
修改时,很可能是某个退出的地方未释放锁导致的,想清楚修改即可。
当是ioctl时,若知道了fd(如237)和并通过ps命令知道主进程test_strace的pid(如1230),则可使用
ls -l /proc/1230/fd/237
得到这个fd所对应的文件,如/dev/vo,便可定位出是大致哪里出的问题。