C语言__TID__用法,C語言編程中pid, tid以及真實pid的關系(轉)

add by zhj: 下面是我對pid,tgid,ppid的個人理解

對於ubuntu14.04操作系統,可以在/usr/src/linux-headers-4.4.0-31/include/linux/sched.h文件中看到進程控制塊的結構體,如下

structtask_struct {volatile long state; /*-1 unrunnable, 0 runnable, >0 stopped*/

void *stack;

atomic_t usage;

unsignedint flags; /*per process flags, defined below*/unsignedintptrace;

#ifdef CONFIG_SMPstructllist_node wake_entry;inton_cpu;

unsignedintwakee_flips;

unsignedlongwakee_flip_decay_ts;struct task_struct *last_wakee;intwake_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是可以自己來指定的,平時基本不用,不用管它。

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#include#include#include

structmessage

{inti;intj;

};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[])

{structmessage 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;

}

1e6ad283a7fe343055da61f6c072c18d.png

getpid()得到的是進程的pid,在內核中,每個線程都有自己的PID,要得到線程的PID,必須用syscall(SYS_gettid);

pthread_self函數獲取的是線程ID,線程ID在某進程中是唯一的,在不同的進程中創建的線程可能出現ID值相同的情況。

#include #include#include#include#include

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;

}

9c04cca8e3eb0f08d2dca0ffaa04ce2d.png

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 

#include 

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

4026894f1653a3fc2bad747c3426101c.png

02a751b91f5f2094aaa58f1ea59aa7ef.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值