add by zhj: 下面是我對pid,tgid,ppid的個人理解
對於ubuntu14.04操作系統,可以在/usr/src/linux-headers-4.4.0-31/include/linux/sched.h文件中看到進程控制塊的結構體,如下
struct task_struct { volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; atomic_t usage; unsigned int flags; /* per process flags, defined below */ unsigned int ptrace; #ifdef CONFIG_SMP struct llist_node wake_entry; int on_cpu; unsigned int wakee_flips; unsigned long wakee_flip_decay_ts; struct task_struct *last_wakee; int wake_cpu; #endif ...... ...... pid_t pid; pid_t tgid; ...... ...... }
可以看到,里面定義了兩個字段,pid和tgid,其中pid就是這個輕量級進程lwp的id,而tgid是輕量級進程組的id,當創建進程時,我們可以為自己指定
進程的tgid字段,貌似可以隨便指定,只要存在就行,另外在父進程中,可以為子進程設置進程組id,如果沒有指定,它會繼承父進程的進程組id。
還有一個概念ppid,我沒在這個結構體中找到,但操作系統肯定是會記錄的,在Python中,通過os.get_ppid()就可以獲取當前進程的父進程。tgid與ppid,
這兩者其實沒有任何關系,因為tgid是可以自己來指定的,平時基本不用,不用管它。
原文:http://blog.csdn.net/u012398613/article/details/52183708
1、pid,tid,真實pid的使用
進程pid: getpid() // 相當於os.getpid() 線程tid: pthread_self() //進程內唯一,但是在不同進程則不唯一。相當於thread.get_ident() 線程pid: syscall(SYS_gettid) //系統內是唯一的。python中沒有現成的方法,需要手動調用動態鏈接庫ctypes.CDLL('libc.so.6').syscall(xx) #include <stdio.h> #include <pthread.h> #include <sys/types.h> #include <sys/syscall.h> struct message { int i; int j; }; void *hello(struct message *str) { printf("child, the tid=%lu, pid=%d\n",pthread_self(),syscall(SYS_gettid)); printf("the arg.i is %d, arg.j is %d\n",str->i,str->j); printf("child, getpid()=%d\n",getpid()); while(1); } int main(int argc, char *argv[]) { struct message test; pthread_t thread_id; test.i=10; test.j=20; pthread_create(&thread_id,NULL,hello,&test); printf("parent, the tid=%lu, pid=%d\n",pthread_self(),syscall(SYS_gettid)); printf("parent, getpid()=%d\n",getpid()); pthread_join(thread_id,NULL); return 0; }
getpid()得到的是進程的pid,在內核中,每個線程都有自己的PID,要得到線程的PID,必須用syscall(SYS_gettid);
pthread_self函數獲取的是線程ID,線程ID在某進程中是唯一的,在不同的進程中創建的線程可能出現ID值相同的情況。
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> void *thread_one() { printf("thread_one:int %d main process, the tid=%lu,pid=%ld\n",getpid(),pthread_self(),syscall(SYS_gettid)); } void *thread_two() { printf("thread two:int %d main process, the tid=%lu,pid=%ld\n",getpid(),pthread_self(),syscall(SYS_gettid)); } int main(int argc, char *argv[]) { pid_t pid; pthread_t tid_one,tid_two; if((pid=fork())==-1) { perror("fork"); exit(EXIT_FAILURE); } else if(pid==0) { pthread_create(&tid_one,NULL,(void *)thread_one,NULL); pthread_join(tid_one,NULL); } else { pthread_create(&tid_two,NULL,(void *)thread_two,NULL); pthread_join(tid_two,NULL); } wait(NULL); return 0; }
2、pid與tid的用途
Linux中,每個進程有一個pid,類型pid_t,由getpid()取得。Linux下的POSIX線程也有一個id,類型pthread_t,由pthread_self()取得,該id由線程維護,其id空間是各個進程獨立的(即不同進程中的線程可能有相同的id)。你可能知道,Linux中的POSIX線程庫實現的線程其實也是一個進程(LWP),只是該進程與主進程(啟動線程的進程)共享一些資源而已,比如代碼段,數據段等。
有時候我們可能需要知道線程的真實pid。比如進程P1要向另外一個進程P2中的某個線程發送信號時,既不能使用P2的pid,更不能使用線程的pthread id,而只能使用該線程的真實pid,稱為tid。
有一個函數gettid()可以得到tid,但glibc並沒有實現該函數,只能通過Linux的系統調用syscall來獲取。使用syscall得到tid只需一行代碼,但為了加深各位看官的印象,簡單提供下面場景。
有一簇進程,其中一個進程中另外啟了一個線程。各進程共享一個數據結構,由shared_ptr指明,其中保存有線程的tid。在各個進程的執行過程中,需要判斷線程是否存在,若不存在則(重新)創建。
首先,在線程函數的開始,需要將自己的tid保存至共享內存,
點擊(此處)折疊或打開
- #include <sys/syscall.h>
- #include <sys/types.h>
- void*
- thread_func(void *args)
- {
- //~ lock shared memory
- shared_ptr->tid = syscall(SYS_gettid); //~ gettid()
- //~ unlock shared memory
- //~ other stuff
- }
點擊(此處)折疊或打開
- //~ lock shared memory
- pthread_t id;
- if (shared_ptr->tid == 0) { //~ tid is initialized to 0
- pthread_create(&id, NULL, thread_func, NULL);
- } else if (shared_ptr->tid > 0) {
- int ret = kill(shared_ptr->tid, 0); //~ send signal 0 to thread
- if (ret != 0) { //~ thread already died
- pthread_create(&id, NULL, thread_func, NULL);
- }
- }
- //~ unlock shared memory
3、linux 系統中查看pid,tid的方法
線程進程都會有自己的ID,從操作系統來講,這個ID就叫做PID