gettid 和 pthread_self 的区别

6 篇文章 0 订阅
  • gettid
    • gettid() is a system call. As for as I know there is no glibc wrapper for gettid. You need to invoke gettid() using syscall(). The following code works for me.

      #include <sys/syscall.h>
      pid_t gettid() { return syscall(__NR_gettid); }

      pid_t gettid2() { return syscall(SYS_gettid); }

  • pthread_self
pthread_self()是POSIX的实现,它的返回值是pthread_t,pthread_t在linux中实际是无符号长整型,即unsigned long。
gettid是系统调用,它的返回值是pid_t,在linux上是一个无符号整型。

pthread_self是为了区分同一进程种不同的线程, 是由thread的实现来决定的,而gettid获取的线程id和pid是有关系的,因为在linux中线程其实也是一个进程(clone),所以它的线程ID也是pid_t类型。在一个进程中,主线程的线程id和进程id是一样的,该进程中其他的线程id则在linux系统内是唯一的,因为linux中线程就是进程,而进程号是唯一的。gettid是不可移植的。

pthread_self返回的是同一个进程中各个线程之间的标识号,对于这个进程内是唯一的,而不同进程中,每个线程返回的pthread_self可能返回的是一样的。而gettid是用来系统内各个线程间的标识符,由于linux采用轻量级进程实现的,它其实返回的应该是pid号。

    They are not the same. Here are some bits I collected from TLPI (I couldn't find a large-enough block that completely describes this). If you're in a hurry you probably want just the last part.

    gettid

    Linux 2.4 introduced a new system call, gettid(), to allow a thread to obtain its own thread ID.

    Each thread within a thread group is distinguished by a unique thread identifier. A thread ID is represented using the same data type that is used for a process ID, pid_t. Thread IDs are unique system-wide, and the kernel guarantees that no thread ID will be the same as any process ID on the system, except when a thread is the thread group leader for a process.

    pthread_self

    Each thread within a process is uniquely identified by a thread ID. A thread can obtain its own ID using pthread_self().

    The pthread_equal() function is needed to compare thread ids because the pthread_t data type must be treated as opaque data.

    In the Linux threading implementations, thread IDs are unique across processes. However, this is not necessarily the case on other implementations, and SUSv3 explicitly notes that an application can’t portably use a thread ID to identify a thread in another process.

    gettid vs pthread_self

    POSIX thread IDs are not the same as the thread IDs returned by the Linux-specific gettid() system call. POSIX thread IDs are assigned and maintained by the threading implementation. The thread ID returned by gettid() is a number (similar to a process ID) that is assigned by the kernel.

    I would go with pthread_setaffinity_np but be aware that the manual says:

    These functions are implemented on top of the sched_setaffinity(2)

      如何获取进程的PID(process ID)?

      可以使用:

      #include <unistd.h>   
      pid_t getpid( void);  
      通过查看头文件说明,可以得到更详细的信息:
      find /usr/include -name unistd.h  
        
      /usr/include/asm/unistd.h  
      /usr/include/bits/unistd.h  
      /usr/include/linux/unistd.h  
      /usr/include/sys/unistd.h  
      /usr/include/unistd.h  
        
      cat /usr/include/unistd.h | grep getpid  
        
      /* Get the process ID of the calling process.  */   
      extern __pid_t getpid ( void) __THROW;  

      如何获取线程的TID(thread ID)?

      通过查看man得到如下描述:

      (1) The gettid() system call first appeared on Linux in kernel 2.4.11.

      (2) gettid() returns the thread ID of the current process. This is equal to the process ID (as returned by getpid(2)), unless the process is part of a thread group (created by specifying the CLONE_THREAD flag to the clone(2) system call). All processes in the same thread group have the same PID, but each one has a unique TID.

      (3) gettid() is Linux specific and should not be used in programs that are intended to be portable. (如果考虑移植性,不应该使用此接口)


      但是根据man的使用说明,测试后发现会报找不到此接口的错误“error: undefined reference to `gettid'”,通过下面链接可以找到更详细的说明:

      http://www.kernel.org/doc/man-pages/online/pages/man2/gettid.2.html

      (1) Glibc does not provide a wrapper for this system call; call it using syscall(2).(说明Glibc并没有提供此接口的声明,此接口实际使用的是系统调用,使用者可以自己创建包裹函数)

      (2) The thread ID returned by this call is not the same thing as a POSIX thread ID (i.e., the opaque value returned by pthread_self(3)).


      然后查看/usr/include/sys/syscall.h(实际在/usr/include/asm/unistd.h)可以找到我们需要的system call number:

      #define __NR_gettid     224


      因此,要获取某个线程的TID,最nasty的方式是:

      #include <sys/syscall.h>   
      printf( "The ID of this thread is: %ld\n", ( long  int)syscall(224));  
      或者比较elegant的方式是:
      #include <sys/syscall.h>   
      #define gettidv1() syscall(__NR_gettid)  
      #define gettidv2() syscall(SYS_gettid)   
      printf( "The ID of this thread is: %ld\n", ( long  int)gettidv1()); // 最新的方式  
      printf( "The ID of this thread is: %ld\n" , ( long   int )gettidv2()); // traditional form   
      PS: 在/usr/include/sys/syscall.h中可以看到关于__NR_<name>和SYS_<name>两个宏的区别,实际最后使用的都是__NR_<name>。
      // /usr/include/bits/syscall.h   
      #define SYS_gettid __NR_gettid  
        
      #ifndef _LIBC  
      /* The Linux kernel header file defines macros `__NR_<name>', but some       
         programs expect the traditional form `SYS_<name>'.  So in building libc 
         we scan the kernel's list and produce <bits/syscall.h> with macros for  
         all the `SYS_' names.  */  
      # include <bits/syscall.h>   
      #endif  


      验证TID是否正确的方法:

      查看进程pid

      (1) ps ux | grep prog_name

      (2) pgrep prog_name 

      查看线程tid

      (1) ps -efL | grep prog_name

      (2) ls /proc/pid/task

      • 4
        点赞
      • 9
        收藏
        觉得还不错? 一键收藏
      • 0
        评论

      “相关推荐”对你有帮助么?

      • 非常没帮助
      • 没帮助
      • 一般
      • 有帮助
      • 非常有帮助
      提交
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值