为什么线程有PID?

在linux下用 top -H -p <pid> 查询某个进程的线程
按理说,都是某个进程下的线程, 应该进程id PID同样啊,但实际却都不同


实际是被PID的名字给弄混了,线程进程都会有本身的ID,这个ID就叫作PID,PID是不特指进程ID,线程ID也能够叫作PID。java

pthread库里的每个线程都对应一个内核线程,都是有单独的pid。
linux


The four threads will have the same PID but only when viewed from above. What you (as a user) call a PID is not what the kernel (looking from below) calls a PID.app

In the kernel, each thread has it's own ID, called a PID (although it would possibly make more sense to call this a TID, or thread ID) and they also have a TGID (thread group ID) which is the PID of the thread that started the whole process.函数

Simplistically, when a new process is created, it appears as a thread where both the PID and TGID are the same (new) number.this

When a thread starts another thread, that started thread gets its own PID (so the scheduler can schedule it independently) but it inherits the TGID from the original thread.spa

That way, the kernel can happily schedule threads independent of what process they belong to, while processes (thread group IDs) are reported to you.线程


关于线程继承关系图以下:code

USER VIEW
 <-- PID 43 --> <----------------- PID 42 ----------------->
                     +---------+
                     | process |
                    _| pid=42  |_
                  _/ | tgid=42 | \_ (new thread) _
       _ (fork) _/   +---------+                  \
      /                                        +---------+
+---------+                                    | process |
| process |                                    | pid=44  |
| pid=43  |                                    | tgid=42 |
| tgid=43 |                                    +---------+
+---------+
 <-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
                     KERNEL VIEW

在这里你能够清晰的看到,建立一个新的进程会给一个新的PID和TGID,而且2个值相同,当建立一个新的线程的时候,会给你一个新的PID,而且TGID和以前开始的进程一致。xml

Linux经过进程查看线程的方法 1).htop按t(显示进程线程嵌套关系)和H(显示线程) ,而后F4过滤进程名。2).ps -eLf | grep java(快照,带线程命令,e是显示所有进程,L是显示线程,f全格式输出) 3).pstree -p <pid>(显示进程树,不加pid显示全部) 4).top -Hp <pid> (实时) 5).ps -T -p <pid>(快照) 推荐程度按数字从小到大。继承

打印线程的PID的方法以下:

getpid()方法能够打印进程的PID
gettid()方法能够打印线程的PID

void * thread_start(void *arg)  
{  
    printf("Process ID: %d, thread ID %d\n", getpid(), gettid());  
}  
因为gettid()在glibc中没有包含
Note: There is no glibc wrapper for this system call; see NOTES. 

因此用以下syscall函数在用户空间替代gettid()的功能
syscall(__NR_gettid))   或者  syscall(SYS_gettid)

在文件 /usr/include/bits/syscall.h里, 有一行:
#define SYS_gettid __NR_gettid  
可见两者是同样的。__NR_gettid是系统调用号

#include <pthread.h>   #include <stdio.h>   #include <sys/types.h>   #include <sys/syscall.h>   #include <unistd.h>   void * thread_start(void *arg)   {       printf("[1] Process ID: %d, thread ID %d\n", getpid(), syscall(__NR_gettid));       printf("[2] Process ID: %d, thread ID %d\n", getpid(), syscall(SYS_gettid));   }