Linux clone()是否为子进程创建新线程及核心亲和性设置相关问题
问题解答
前置问题澄清
你当前遇到的子进程阻塞父进程的问题和fork本身无关,是你在父进程逻辑中调用了wait(&status),这个API会主动挂起父进程,直到子进程退出才会继续执行后续逻辑。你只要去掉wait调用,父进程就会正常运行,子进程会在后台独立执行,完全不需要改用clone。
疑问1:clone()创建的子进程是否会运行在独立线程上?
这个完全由你传递给clone的标志位决定:
- 若传入
CLONE_THREAD标志,子进程会和父进程属于同一个线程组,内核会将其识别为同一进程下的独立线程,共享地址空间、文件描述符、信号处理规则等资源,和pthread_create创建的线程完全等价 - 若未传入
CLONE_THREAD标志,子进程属于独立的进程,和fork创建的子进程逻辑一致,仅可通过其他标志位控制共享资源的粒度
疑问2:pthread_setaffinity对clone()创建的子进程是否生效?
分两种场景:
- 如果你用
clone创建的是同进程下的线程(带CLONE_THREAD标志),pthread_setaffinity对这个子线程完全生效,和普通pthread线程没有区别 - 如果你创建的是独立进程(不带
CLONE_THREAD标志),pthread系列API无效,需要用sched_setaffinity系统调用来设置子进程的CPU亲和性
你要实现父子进程/线程运行在同一个核心的需求非常容易实现:如果是同进程线程,创建后直接调用pthread_setaffinity绑定到和父线程相同的核心即可;如果是独立子进程,在fork/clone之后,子进程侧调用sched_setaffinity绑定到指定核心即可。
疑问3:「fork不会创建新线程因此子进程会阻塞父进程,clone会创建新线程」的认知是否正确?
这个认知完全错误:
fork创建的是独立的子进程,和父进程天然并行运行,本身不会阻塞父进程,你代码中的阻塞完全是wait调用导致的clone只是更底层的系统调用,可以灵活控制父子侧共享的资源,既可以用来创建独立进程,也可以用来创建同进程线程,不是只要调用clone就会创建线程
场景优化建议
你要实现子Python进程长期存活、和父进程通过IPC通信的需求,完全不需要使用clone,直接修改原有fork代码即可:
- 去掉父进程中的
wait(&status)调用,父进程fork之后即可继续执行自身逻辑 - 父子进程提前创建FIFO或者Unix域套接字,将对应的文件描述符通过execv参数传递给Python侧,即可实现双向通信
- 如果需要后续回收子进程资源避免僵尸进程,可以注册
SIGCHLD信号处理函数,在信号回调中调用wait回收即可。
内容的提问来源于stack exchange,提问作者RTC222
相关产品推荐
相关产品推荐

