linux - 如何在 Linux 上实现 pthread_detach?
问题描述
pthread_detach
标记一个线程,以便当它终止时,它的资源会自动释放,而不需要父线程调用pthread_join
. 它怎么能做到这一点?特别是从 Linux 的角度来看,有两个资源我特别好奇:
- 作为一个实现细节,我希望如果
wait
没有在终止的线程上执行系统调用,那么该线程将成为僵尸。我假设 pthread 库对这个问题的解决方案不涉及,因为(我认为)它仍然可以工作,无论程序指定在收到SIGCHLD
时发生什么操作。SIGCHLD
- 线程是使用
clone
系统调用创建的。调用者在调用之前必须分配内存作为子线程的栈区clone
。在 Stack Overflow 的其他地方,建议调用者使用mmap
为孩子分配堆栈。线程退出后如何取消映射堆栈?
在我看来,pthread_detach
必须以某种方式为这两个问题提供解决方案,否则,产生和分离许多线程的程序最终将失去继续产生新线程的能力,即使分离的线程可能已经终止。
解决方案
pthreads 库(在 Linux 上,NPTL)提供了一个围绕较低级别原语的包装器,例如clone(2)
. 当使用创建线程时pthread_create
,传递给的函数clone
是包装函数。该函数分配堆栈并将该信息以及任何其他元数据存储到一个结构中,然后调用用户提供的启动函数。当用户提供的启动函数返回时,就会进行清理。最后,调用内部函数__exit_thread
进行系统调用以退出线程。
当这样一个线程被分离时,它仍然从用户提供的启动函数返回并像以前一样调用清理代码,除了堆栈和元数据作为其中的一部分被释放,因为没有人在等待这个线程完成。这通常由pthread_join
.
如果线程在没有运行的情况下被杀死或退出,则清理由下一个pthread_create
调用处理,该调用将调用任何尚未运行的清理处理程序。
aSIGCHLD
没有发送给父级也不是wait(2)
必需的原因是因为使用了CLONE_THREAD
标志 to clone(2)
。手册页对此标志进行了以下说明:
使用 CLONE_THREAD 创建的新线程与进行克隆调用的进程具有相同的父进程(即,如 CLONE_PARENT),因此对 getppid(2) 的调用为线程组中的所有线程返回相同的值。当 CLONE_THREAD 线程终止时,创建它的线程不会发送 SIGCHLD(或其他终止)信号;使用wait(2) 也无法获取此类线程的状态。(据说线程是分离的。)
正如您所指出的,这是发生预期 POSIX 语义所必需的。
推荐阅读
- reactjs - 如何在常规反应站点上添加反应 360?
- javascript - HOC 不是函数
- javascript - 如何使用 javascript qodesmith / datepicker
- r - 在R中的嵌套列表中查找最大值
- javascript - 在反应并关闭弹出窗口中从 eventListener 调度事件
- azure-active-directory - 尝试在 tomcat 服务器中部署 msal4jsample
- firebase - 有限的firebase查询功能是否有解决方法
- python - Pandas DataFrame 构造函数对行进行排序,即使使用 OrderedDict 作为输入
- .net - 您应该如何分配 azure 函数来接收不同的标注或 webhook?
- ios - 某些视图上的导航栏大标题问题