foggia2004

线程的2个ID

我们知道进程ID是操作系统调度的最小单位,有时候根据业务的需要,我们会使用到多线程技术,当创建了多个线程时,也会有一个线程ID,那这个线程ID和进程ID有什么不一样吗?

其中,线程组的线程ID是属于NPTL(Native POSIX Thread Library)线程库的范畴,属该线程库调度的标识;而调度器的进程ID则属于操作系统的最小调度单位.两者具有在本质上截然不同的意义和使用范围,值得注意!我们来看一个实验代码:线程执行函数thread1和thread2都只做一件事情,输出自己的线程组中的线程ID和被调度器调度的进程ID,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <pthread.h>
#include <sys/syscall.h> /* syscall(SYS_gettid); */

void *thread1();
void *thread2();

int main(int argc, char *argv[])
{
	int flag;
	pthread_t th1,th2;
	flag=pthread_create(&th1,NULL,thread1,NULL);
	if(flag != 0)
	{
		fprintf(stderr,"创建线程1失败[%s]\n",strerror(errno));
		exit(0);
	}	
	
	flag=pthread_create(&th2,NULL,thread2,NULL);
	if(flag != 0)
	{
		fprintf(stderr,"创建线程2失败[%s]\n",strerror(errno));
		exit(0);
	}	
	
	printf("main进程ID是[%d]\n",getpid());
	
	pthread_join(th1,NULL);
	pthread_join(th2,NULL);
	
	return 0;
}

void *thread1()
{
	int tid = syscall(SYS_gettid); /* 被进程调度器调度的进程ID */
	printf("这是线程thread1,线程组的线程ID是[%u], 调度器的进程ID = %d\n",(unsigned int)pthread_self(), tid);
	/* 让线程不要退出,以便查看在proc下的线程信息 */
	pause();
}

void *thread2()
{
	int tid = syscall(SYS_gettid); /* 被进程调度器调度的进程ID */
	printf("这是线程thread2,线程组的线程ID是[%u], 调度器的进程ID = %d\n",(unsigned int)pthread_self(), tid);
	/* 让线程不要退出,以便查看在proc下的线程信息 */
	pause();
}

运行结果

发现属于NPTL的线程ID的数值非常大(3078654832,3068164976),而属于系统调度器的进程ID则紧跟主进程的进程ID(4180,4181)

在线程没有退出的情况下(使用pause进行模拟),可以使用ls -l /proc/[pid]/task命令查看该进程下的所属线程信息.因为procfs文件系统在task下会给进程的每一个线程都建立一个子目录,目录名称为该线程的被调度的ID.(PS: 使用命令ps -L -p 4179也可以查看)

发现该进程的目录下的确有4180和4181的线程目录.

从本质上来说,属于NPTL范畴的线程ID的类型是pthread_t,而它指向了一个类型为struct pthread的结构体,所以还是一个指针,理解成为一个地址也可以.

而被系统调度的进程ID的类型却是pid_t,它是能被列入到调度队列的.所以,两者还是有很大区别的.

命令ps -L -p 4179的执行结果

./threadid的状态是Sl+,S表示该进程是静止的,l表示是多线程或者克隆线程.

备注:进程或线程的状态列表

    D    不可中断     Uninterruptible sleep (usually IO)
    R    正在运行,或在队列中的进程
    S    处于休眠状态
    T    停止或被追踪
    Z    僵尸进程
    W    进入内存交换(从内核2.6开始无效)
    X    死掉的进程

    <    高优先级
    N    低优先级
    L    有些页被锁进内存
    s    包含子进程
    +    位于后台的进程组
    l    多线程,克隆线程

posted on 2017-01-06 10:01  foggia2004  阅读(202)  评论(0)    收藏  举报

导航