NPTL中的线程如何退出?

问题描述 投票:1回答:1

从实现的角度,我很好奇单个NPTL线程如何退出。

关于glibc-2.30的实现,我了解的是:

  1. NPTL线程是在Linux上的轻量级进程之上构建的,其他信息存储在用户堆栈的pthread对象中,以跟踪NPTL特定的信息,例如连接/分离状态和返回的对象的指针。
  2. 当NPTL线程完成后,它就一去不复返了,除非它是分离的,否则只剩下用户堆栈(因此)pthread对象被收集(由其他线程连接),在这种情况下,该空间直接被释放。
  3. [_exit() syscall杀死线程组中的所有线程。
  4. pthread_create()接受的用户功能实际上被包装到另一个功能pthread_create()中,该功能在运行用户功能之前进行了一些准备,之后进行了一些清理。

问题是:

  1. 包装函数start_thread()的末尾,有以下注释和代码:

    start_thread()

    但是start_thread()似乎还是要进行系统调用start_thread()

    /* We cannot call '_exit' here.  '_exit' will terminate the process.
    
     The 'exit' implementation in the kernel will signal when the
     process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
     flag.  The 'tid' field in the TCB will be set to zero.
    
     The exit code is zero since in case all threads exit by calling
     'pthread_exit' the exit status must be 0 (zero).  */
     __exit_thread ();
    

    所以我在这里很困惑,因为它实际上不应该执行syscall __exit_thread(),因为它将终止所有线程。

  2. __exit_thread()应该终止单个线程,因此它应该执行与包装器_exit()最后的操作类似的操作,但是它调用了 static inline void __attribute__ ((noreturn, always_inline, unused)) __exit_thread (void) { /* some comments here */ while (1) { INTERNAL_SYSCALL_DECL (err); INTERNAL_SYSCALL (exit, err, 1, 0); } } ,而TBH在跟踪该函数时迷失了方向。它似乎与上述_exit()无关,也没有调用pthread_exit()
c linux-kernel pthreads system-calls glibc
1个回答
1
投票

我在这里很困惑,因为它实际上不应该进行syscall _exit()

这里的混乱源于将pthread_exit()系统调用与start_thread() libc例程混合在一起(Linux上没有__do_cancel()系统调用)。

前者终止当前的Linux线程(按预期方式。)>

后者(令人困惑)不执行__do_cancel()系统调用。相反,它执行__exit_thread()系统调用,该系统调用终止all

线程。

thread_exit()应该终止单个线程

它确实是间接的。它展开当前堆栈(类似于_exit()),执行控制转移到设置exit的位置。那是在_exit中。

在控制权转移之后,_exit清理资源,并调用exit实际终止线程。

© www.soinside.com 2019 - 2024. All rights reserved.