java如何根据pid转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;

}

ae70968bc07eeeae19728c817f6aae09.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;

}

1153ee29b0ad02cf149ec45de9146dee.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

9457a2eb5cea110daf1140f6688abc21.png

b294a335b32ad47a50d322feae06f61d.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值