Linux线程ID和进程ID

1. Linux线程的线程ID和进程ID

Linux内核并不支持真正意义上的线程,Linux线程库是用与普通进程具有同样内核调度视图的轻量级进程来实现线程支持的。这些轻量级进程拥有独立的进程id,在进程调度、信号处理、IO等方面享有与普通进程一样的能力。
每个Linux线程都同时具有线程id和进程id,其中进程id就是内核所维护的进程号,而线程id则由线程库分配和维护。
1)每个进程都有自己的PID,这是唯一的。
2)除此之外,每个进程还有其它的ID标识,比如处于某个线程组中的所有进程都有一个统一的线程组ID(TGID),如果进程没有使用线程,PID和TGID是相同的,其实主线程的PID和TGID就是相同的。
3)独立进程可以合并成为进程组。
4)几个进程组可以合并成一个会话,会话中的所有进程都有同样的会话ID。

重点关注一下 task_struct 中与进程ID相关的两个成员:
struct task_struct{
   pid_t pid;
   pid_t tgid;
}
属于同一个进程的所有线程,tgid是相同的,都指向线程组第一个进程(主线程)的PID值。
可以分别通过getpid(), syscall(SYS_gettid)获取对应的值。结合下面第2部分的程序,能够更直观地看出getpid()获取tgid、syscall()获取PID。

因此,对于Linux而言,所谓线程组共享进程ID,其实是通过 tgid 表示的,而线程组中的每个线程本质上是有自己的进程ID号的。

2. 通过程序查看线程相关的ID

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <linux/unistd.h>

pid_t gettid()  
{  
  return syscall(__NR_gettid);  
} 

static void *phandle(void *arg)
{
  pid_t pid_chld, pid_chld1;
  pthread_t tid;
	
  pid_chld = getpid();
  pid_chld1 = gettid();
  tid = pthread_self();
	
  printf("<child pthread>@(pid=%d/ptid=%d/tid=%lu) Child pthread ready to sleep 5 \r\n", pid_chld, pid_chld1,tid);
  sleep(2);
  printf("<child pthread>@(pid=%d/ptid=%d/tid=%lu) Child pthread exit\r\n", pid_chld, pid_chld1,tid);

  return NULL;
}

int main(int argc, char *argv[])
{
  int cnt;
  pid_t pid;
  pthread_t g_tid,tid;

  pid = getpid();
  g_tid = pthread_self();
  printf("[[main pthread]] (pid=%lu/tid_mian=%lu) start! \r\n", pid, g_tid);
	
  for(cnt=0; cnt<2; cnt++)
  {
    pthread_create(&tid,NULL,phandle,NULL);
    printf("[[main pthread]] create a child pthread_%d(%lu)\r\n",cnt,tid);
  }
  
  sleep(5);
  printf("[[main pthread]] (pid=%lu/tid_mian=%lu) exit!\r\n", pid, g_tid);
  exit(0);
}

执行结果如下:
# gcc -o pid pthread_pid_tid.c -lpthread 
# ./pid 
[[main pthread]] (pid=3221/tid_mian=3076355776) start! 
[[main pthread]] create a child pthread_0(3076352832)
[[main pthread]] create a child pthread_1(3067960128)
<child pthread>@(pid=3221/ptid=3223/tid=3067960128) Child pthread ready to sleep 5 
<child pthread>@(pid=3221/ptid=3222/tid=3076352832) Child pthread ready to sleep 5 
<child pthread>@(pid=3221/ptid=3223/tid=3067960128) Child pthread exit
<child pthread>@(pid=3221/ptid=3222/tid=3076352832) Child pthread exit
[[main pthread]] (pid=3221/tid_mian=3076355776) exit!

3. 转载网上的一篇关于线程ID和进程ID的文章

原文:http://blog.chinaunix.net/uid-24567872-id-100482.html    点击打开链接
在linux中,线程与进程最大的区别就是是否共享同一块地址空间,而且共享同一块地址空间的那一组线程将显现相同的PID号。
       在实际编程应用中,我们会很容易发现并证明,一组同源线程的PID都是一样的,但它们的PID真的一样么?
       在linux中,线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:
  1. clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);
       上面的代码产生的结果和调用fork()差不多,只是父子俩共享地址空间、文件系统资源、文件描述符和信号处理程序。换个说法就是, 新建的进程和它的父进程就是流行的所谓线程 。  
       对比一下,一个普通的fork()的实现是:
  1. clone(SIGCHLD, 0);
      而vfork()的实现是:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中的进程线程有以下几个区别: 1. 数据结构:在Linux中,线程是通过进程模拟出来的,没有真正意义上的线程数据结构。而在Windows中,操作系统为线程创建了thread_struct数据结构,因此有真正意义上的线程。 2. 执行流:在Linux中,每个线程实体对应着操作系统下的一条执行流,通过PCB(task_struct)来模拟。而用户态下创建的线程是通过线程库(pthread_struct)来进行管理。 3. 标识作用:在Linux中,轻量级进程ID(tid)对不同的线程起标识作用,操作系统在进行调度时使用tid。而进程ID(pid)对不同的进程起标识作用。在只有一个线程的进程中,tid的值等于pid的值。 4. 线程私有部分:线程私有部分包括运行时栈、一组寄存器/硬件上下文/任务状态段等。 5. 多线程提高效率:多线程能够提高效率的原因是多核和单核环境下的不同。在多核环境下,多线程可以将庞大的任务分成若干份,并交给不同的线程进行处理,同时执行不同步骤的代码,从而提高效率。而在单核环境下,多线程并发执行,使用线程切换来提高整体代码的运行效率。 6. 进程线程的区别:进程是程序运行的实例,是系统分配资源的基本单位,拥有独立的地址空间;线程是进程中的一条执行流,是CPU调度的基本单位,共享同一地址空间。创建和撤销进程的开销大于线程,不同进程间不会互相影响,而一个线程挂掉可以将整个进程挂掉。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值