C语言编制程序中pid, tid以至实际pid的涉及(转卡塔 尔(阿拉伯语:قطر‎

Linux的长河和线程

Linux的经过和线程有无数异同点,能够谷歌(Google卡塔尔国下。但假使能知道地领悟一下几点,则丰硕通晓Linux中各样ID的意思。

  • 进度是财富分配的主导单位,线程是调解的主干单位
  • 经过是财富的聚众,那个资源满含内部存款和储蓄器地址空间,文件描述符等等,三个进程中的多个线程分享这么些财富。
  • CPU对职分张开调整时,可调治的核心单位 (dispatchable entity)是线程。要是一个历程中没有其它线程,能够了然成这些历程中独有一个主线程,这一个主进度独享进度中的全部能源。
  • 经过的私有间是一丝一毫独立的,而线程间是并行依存,并且分享能源。多进度遭逢中,任何一个进度的为止,不会潜濡默化到别的非子进程。而八线程意况中,父线程终止,全体子线程被迫结束(未有了能源)。

上述第一点说明是最基本功的,也是最重要的。

 

始于领悟各个ID。基本上遵照重视程度从高到低,在分水岭下方的IDs不太重大。

  • pid: 进程ID。
  • lwp: 线程ID。在客商态的授命(比如ps)中常用的展现格局。
  • tid: 线程ID,等于lwp。tid在系统提供的接口函数中更常用,举个例子syscall(SYS_gettid)和syscall(__NR_gettid)。
  • tgid: 线程组ID,也正是线程组leader的历程ID,等于pid。
  • ------分割线------
  • pgid: 进度组ID,也等于进度组leader的进度ID。
  • pthread id: pthread库提供的ID,生效范围不在系统等级,能够忽略。
  • sid: session ID for the session leader。
  • tpgid: tty process group ID for the process group leader。

 从上面的列表看出,各类ID最终都总结到pid和lwp(tid)上。所以精晓各个ID,最终归纳为精通pid和lwp(tid)的关系和分裂。

 

上面包车型大巴图是一张呈报父亲和儿子进度,线程之间涉及的图。

图片 1

上航海用教室很好地陈说了顾客意见(user view)和根本视角(kernel view)见到线程的异样:

  • 从客商意见出发,在pid 4第22中学发生的tid 44线程,归于tgid(线程组leader的长河ID) 42。以致用ps和top的暗中认可参数,你都无法儿见到tid 44线程。
  • 从水源视角出发,tid 42和tid 44是独自的调解单元,能够把她们身为"pid 42"和"pid 44"。

急需建议的是,不常候在Linux中经过和线程的不一样也是否可怜严刻的。尽管线程和进程混用,pid和tid混用,依据上下文,如故得以知晓地区分对方想要表明的意思。上海教室中,从根本视角出发见到了pid 44,是从调治单元的角度出发,不过在top或ps命令中,你是相对找不到一个pid为44的进度的,只能见到二个lwp(tid)为44的线程。

 

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

Linux客商态命令查看线程

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=%dn",pthread_self(),syscall(SYS_gettid));
    printf("the arg.i is %d, arg.j is %dn",str->i,str->j);
    printf("child, getpid()=%dn",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=%dn",pthread_self(),syscall(SYS_gettid));
    printf("parent, getpid()=%dn",getpid());
    pthread_join(thread_id,NULL);
    return 0;
}

图片 2

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=%ldn",getpid(),pthread_self(),syscall(SYS_gettid));
}

void *thread_two()
{
    printf("thread two:int %d main process, the tid=%lu,pid=%ldn",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;
}

图片 3

参考

Linux进度与线程的不同

 

top

私下认可top展现的是task数量,即经过。

图片 4

能够采取敲"H",来切换来线程。如下,能够观望实际有九十多个线程。也足以一向动用top -H命令来间接打字与印刷线程情状。

图片 5

 

2、pid与tid的用途

Linux中,每一个进程有二个pid,类型pid_t,由getpid()拿到。Linux下的POSIX线程也会有三个id,类型pthread_t,由pthread_self()获得,该id由线程维护,其id空间是各类进度独立的(即不相同进度中的线程只怕有雷同的id卡塔 尔(英语:State of Qatar)。你只怕驾驭,Linux中的POSIX线程库实现的线程其实也是三个经过(LWP卡塔尔国,只是该进度与主进度(运行线程的长河卡塔尔国分享一些财富而已,譬如代码段,数据段等。
  不经常候我们恐怕须求精通线程的真实pid。比方进程P1要向其余贰个历程P2中的有个别线程发送实信号时,既不能够使用P2的pid,更不可能使用线程的pthread id,而必须要采取该线程的实际pid,称为tid。
  有二个函数gettid()能够博得tid,但glibc并未兑现该函数,只可以通过Linux的系统调用syscall来拿到。使用syscall获得tid只需黄金时代行代码,但为了深化各位看官的纪念,轻松提供下边场景。
  有风流倜傥簇进度,当中三个经过中其余启了三个线程。各进度分享贰个数据结构,由shared_ptr指明,个中保存有线程的tid。在各个进度的推行进度中,需求判断线程是还是不是存在,若不设有则(重新卡塔尔国创造。
  首先,在线程函数的初步,需求将团结的tid保存至分享内部存款和储蓄器,

点击(此处)折叠或展开

  1. #include <sys/syscall.h>
  2. #include <sys/types.h>
  3. void*
  4. thread_func(void *args)
  5. {
  6.     //~ lock shared memory
  7.     shared_ptr->tid = syscall(SYS_gettid); //~ gettid()
  8.     //~ unlock shared memory
  9.     //~ other stuff
  10. }

  在各进度中推断进度是还是不是留存,

点击(此处)折叠或展开

  1. //~ lock shared memory
  2. pthread_t id;
  3. if (shared_ptr->tid == 0) { //~ tid is initialized to 0
  4.     pthread_create(&id, NULL, thread_func, NULL);
  5. } else if (shared_ptr->tid > 0) {
  6.     int ret = kill(shared_ptr->tid, 0); //~ send signal 0 to thread
  7.     if (ret != 0) { //~ thread already died
  8.         pthread_create(&id, NULL, thread_func, NULL);
  9.     }
  10. }
  11. //~ unlock shared memory

pidstat

pidstat -t [-p pid号] 能够打字与印刷出线程之间的涉及。

 

再有一个概念ppid,作者没在此个结构体中找到,但操作系统肯定是会记录的,在Python中,通过os.get_ppid()就可以取伏贴前行程的父进程。tgid与ppid,

知道pid和lwp(tid)的示范程序

上面接收叁个演示程序来更为领悟pid和lwp(tid),以至采纳格式化的ps命令打字与印刷出各类ID。上面包车型大巴主次在main函数中创立了2个子线程,加上main函数那一个主线程,生龙活虎共有3个线程。在3个线程中分别打印pthread id, pid和lwp(tid),来验证pid和lwp(tid)的关系。

 1 #include <unistd.h>
 2 #include <sys/syscall.h>
 3 #include <stdio.h>
 4 #include <pthread.h>
 5 
 6 #define gettidv1() syscall(__NR_gettid) // new form
 7 #define gettidv2() syscall(SYS_gettid)  // traditional form
 8 
 9 void *ThreadFunc1()
10 {
11         printf("the pthread_1 id is %ldn", pthread_self());
12         printf("the thread_1's Pid is %dn", getpid());
13         printf("The LWPID/tid of thread_1 is: %ldn", (long int)gettidv1());
14         pause();
15 
16         return 0;
17 }
18 
19 void *ThreadFunc2()
20 {
21         printf("the pthread_2 id is %ldn", pthread_self());
22         printf("the thread_2's Pid is %dn", getpid());
23         printf("The LWPID/tid of thread_2 is: %ldn", (long int)gettidv1());
24         pause();
25 
26         return 0;
27 }
28 
29 int main(int argc, char *argv[])
30 {
31         pid_t tid;
32         pthread_t pthread_id;
33 
34         printf("the master thread's pthread id is %ldn", pthread_self());
35         printf("the master thread's Pid is %dn", getpid());
36         printf("The LWPID of master thread is: %ldn", (long int)gettidv1());
37 
38         // 创建2个线程
39         pthread_create(&pthread_id, NULL, ThreadFunc2, NULL);
40         pthread_create(&pthread_id, NULL, ThreadFunc1, NULL);
41         pause();
42 
43         return 0;
44 }

在意编译的时候要使用-l钦命library参数。

# gcc threadTest.c -o threadTest -l pthread

 

施行顺序,结果如下:

# ./threadTest
the master thread's pthread id is 140154481125184
the master thread's Pid is 20992
The LWPID of master thread is: 20992
the pthread_1 id is 140154464352000
the thread_1's Pid is 20992
The LWPID/tid of thread_1 is: 20994
the pthread_2 id is 140154472744704
the thread_2's Pid is 20992
The LWPID/tid of thread_2 is: 20993

上述结果证实pthread id是pthread库提供的ID,在系统等第未有意义。pid都是线程组leader的过程ID,即20992。而lwp(tid)则是线程ID,分别是20993和20994。

 

还要接纳ps来查看结果,注意ps暗许只打字与印刷进度品级音讯,供给用-L选项来查看线程基本音信。

# ps -eo pid,tid,lwp,tgid,pgrp,sid,tpgid,args -L | awk '{if(NR==1) print $0; if($8~/threadTest/) print $0}'
  PID   TID   LWP  TGID  PGRP   SID TPGID COMMAND
20992 20992 20992 20992 20992 30481 20992 ./threadTest
20992 20993 20993 20992 20992 30481 20992 ./threadTest
20992 20994 20994 20992 20992 30481 20992 ./threadTest

从上述结果中能够看来:

  • PID=TGID: 20992
  • TID=LWP: 20993 or 20994
  • 至于SID,30481是bash shell的进程ID。

 

能够看见,里面定义了八个字段,pid和tgid,个中pid正是以此轻量级进程lwp的id,而tgid是轻量级进度组的id,当成立进度时,大家得以为投机钦赐

ps

ps的-L选项能够看到线程,平时能打字与印刷出LWP和NLWP相关音信。如下命令就能够查看线程消息:

ps -eLf

 

3、linux 系统中查阅pid,tid的方法

线程进度都会有投机的ID,从操作系统来说,那几个ID就叫做PID

图片 6

 

 图片 7

 

本文由2020欧洲杯官方投注-2020欧洲杯官方投注网址发布于win7,转载请注明出处:C语言编制程序中pid, tid以至实际pid的涉及(转卡塔 尔(阿拉伯语:قطر‎

相关阅读