为何子进程临界区调用printf会导致父进程死锁?
跨进程互斥锁死锁问题分析与解决
问题现象
在C语言中测试跨进程互斥锁时发现:当且仅当子进程的临界区(pthread_mutex_lock/pthread_mutex_unlock调用之间)存在printf调用时,父进程最终会发生死锁。
程序核心逻辑:
- 分配256字节匿名共享内存
- 在共享内存中初始化
pthread_mutex_t互斥锁 - 创建子进程,父子进程分别读写共享内存的前
sizeof(int)字节并打印内容
复现代码
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/mman.h> #include <pthread.h> #include <sys/types.h> #include <sys/wait.h> int main(){ pthread_mutex_t *lock; int *shared_memory = mmap(NULL, 0x100, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, 0, 0); if (shared_memory == MAP_FAILED) { printf("Error in mapping memory!\n"); exit(1); } lock = (pthread_mutex_t *)shared_memory + sizeof(int); if ( pthread_mutex_init(lock, NULL) != 0) { printf("Error in initializing mutex\n"); exit(1); } int pid = fork(); if (pid == -1) { printf("Error in fork()!\n"); exit(1); } else if (pid == 0) { unsigned int val = 0xC0FFE, j = 0; while (j < 3) { pthread_mutex_lock(lock); printf("%p: %08x\n",shared_memory, *shared_memory); *shared_memory = val; pthread_mutex_unlock(lock); j++; val++; } } else { int i = 0; while (i < 30) { pthread_mutex_lock(lock); *shared_memory -= 1; pthread_mutex_unlock(lock); printf("%p: %08x\n",shared_memory, *shared_memory); i++; } while(wait(NULL) > 0); } }
调试确认
通过GDB调试,确认父进程卡在pthread_mutex_lock调用处:
gdb -p `pidof ./test` ... futex_wait (private=0, expected=2, futex_word=0x7f13ba8be0a0) at ../sysdeps/nptl/futex-internal.h:146 146 ../sysdeps/nptl/futex-internal.h: No such file or directory. (gdb) bt 10 #0 futex_wait (private=0, expected=2, futex_word=0x7f13ba8be0a0) at ../sysdeps/nptl/futex-internal.h:146 #1 __GI___lll_lock_wait (futex=futex@entry=0x7f13ba8be0a0, private=0) at ./nptl/lowlevellock.c:49 #2 0x00007f13ba6dd082 in lll_mutex_lock_optimized (mutex=0x7f13ba8be0a0) at ./nptl/pthread_mutex_lock.c:48 #3 ___pthread_mutex_lock (mutex=0x7f13ba8be0a0) at ./nptl/pthread_mutex_lock.c:93 #4 0x000055e3eca8d37e in main () at test.c:44
解决方案
为互斥锁添加PTHREAD_PROCESS_SHARED属性即可解决该问题,修改后的互斥锁初始化代码如下:
pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); if (pthread_mutex_init(lock, &attr) != 0) { printf("Error in initializing mutex\n"); exit(1); } pthread_mutexattr_destroy(&attr);
原因说明:默认情况下pthread互斥锁属性为PTHREAD_PROCESS_PRIVATE,仅允许同一进程内的线程访问。跨进程使用时必须显式设置PTHREAD_PROCESS_SHARED,才能让不同进程正确识别互斥锁状态。子进程临界区的printf调用会触发进程调度时机变化,将原本隐藏的私有属性问题暴露为死锁。
内容的提问来源于stack exchange,提问作者user2543740
相关产品推荐
相关产品推荐

