You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何子进程临界区调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:55:28