C NPTL中的线程如何退出?

C NPTL中的线程如何退出?,c,linux-kernel,pthreads,system-calls,glibc,C,Linux Kernel,Pthreads,System Calls,Glibc,我很好奇,从实现的角度来看,单个NPTL线程是如何存在的 我对glibc-2.30实施的理解是: NPTL线程构建在Linux上的轻量级进程之上,附加信息存储在用户堆栈上的pthread对象中,以跟踪NPTL特定的信息,如连接/分离状态和返回对象的指针 当一个NPTL线程完成时,它将永远消失,只有用户堆栈(因此)pthread对象将被收集(由其他线程连接),除非它是分离的,在这种情况下,空间将被直接释放 \u exit()syscall杀死线程组中的所有线程 接收的用户函数实际上被包装到另一个函

我很好奇,从实现的角度来看,单个NPTL线程是如何存在的

我对glibc-2.30实施的理解是:

  • NPTL线程构建在Linux上的轻量级进程之上,附加信息存储在用户堆栈上的pthread对象中,以跟踪NPTL特定的信息,如连接/分离状态和返回对象的指针
  • 当一个NPTL线程完成时,它将永远消失,只有用户堆栈(因此)pthread对象将被收集(由其他线程连接),除非它是分离的,在这种情况下,空间将被直接释放
  • \u exit()
    syscall杀死线程组中的所有线程
  • 接收的用户函数实际上被包装到另一个函数中,该函数在运行用户函数之前做一些准备,然后进行一些清理
  • 问题是:

  • 在包装器函数的末尾,有以下注释和代码:

    /* 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
    \u 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);
         }
     }
    
    所以我在这里感到困惑,因为它不应该真正执行syscall
    \u exit()
    ,因为它将终止所有线程

  • 应该终止一个线程,因此它应该做一些类似于包装器
    start\u thread()
    最后所做的事情,但是它调用了,我在跟踪该函数时迷失了方向。它似乎与上面的
    \uuu exit\u thread()
    无关,也不调用
    \u exit()
  • 我在这里感到困惑,因为它不应该真正执行syscall _exit()

    这里的混淆源于将
    exit
    系统调用与
    \u exit
    libc例程混合(Linux上没有
    \u exit
    系统调用)

    前者终止当前Linux线程(如预期的那样)

    后者(令人困惑地)不执行
    exit
    系统调用。相反,它执行
    exit_group
    系统调用,终止所有线程

    线程_exit()应终止单个线程

    这是间接的。它展开当前堆栈(类似于
    siglongjmp
    ),执行控制转移到设置
    cleanup_jmp_buf
    的点。那是在
    start\u-thread


    在控制转移之后,
    start\u-thread
    清理资源,并调用
    \u-exit\u-thread
    实际终止线程。

    这就解释了一切,谢谢!我重新访问了手册页
    man2\u exit
    ,注释部分说“在glibc版本2.3之前的版本中,
    \u exit()
    包装函数调用了同名的内核系统调用。自glibc2.3以来,包装器函数调用
    exit_group
    (2),以终止进程中的所有线程。(原始的
    \u exit()
    系统调用仅终止调用线程。)。这是一个过时的描述,还是在glibc 2.3之前有一个名为
    \u exit
    的系统调用?在
    man
    第2节中有一个
    \u exit
    页面这一事实似乎有点奇怪。@QnA我同意:我认为
    \u exit
    应该移到第3节,因为它描述了
    libc
    函数,而不是系统调用。请随意提交一个bug。