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;#
......
pid_t pid;
pid_t tgid;
python转java代码......
......
}
可以看到,⾥⾯定义了两个字段,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()//进程内唯⼀,但是在不同进程则不唯⼀。相当于_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",pthread_self(),syscall(SYS_gettid));
printf("the arg.i is %d, arg.j is %d",str->i,str->j);
printf("child, getpid()=%d",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",pthread_self(),syscall(SYS_gettid));
printf("parent, getpid()=%d",getpid());
pthread_join(thread_id,NULL);return 0;
}
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",getpid(),pthread_self(),syscall(SYS_gettid));
}void *thread_two()
{
printf("thread two:int %d main process, the tid=%lu,pid=%ld",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
#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
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论