存档在 ‘POSIX线程技术’ 分类

线程那些事儿(2)-实践

2011年9月5日

在多线程程序中,一个新的线程通常由一个进程调用phtread_create()函数而诞生的。新线程创建后,通常将这个进程称为主线程。你也许会有所迷惑:一个进程怎么会编程线程?此刻有几个线程,几个进程?

其实通过上文对线程、轻量级进程以及线程组之间关系的理解后,这个问题似乎也不难回答。我们可以将所有的进程都看作一个线程组,只不过普通进程的线程组只包含它自己一个线程,它不能与其他线程共享资源,只能独享自己的资源(而成为进程)。

对于多线程程序来说,一旦在进程内创建了一个线程,那么该进程也就摇身变成了一个线程。主线程和子线程共享“以前”那个进程所独享的资源。主线程和子线程之间是并列关系,不存在类似fork()函数那样的父子进程关系,这也就是不将创建线程的进程称为父线程的原因。

如果你还对上述的描述有所疑惑,那么通过下面的实验结果可以理解的更加深刻。下述的程序就是一个普通的线程创建,只不过主线程和子线程增加了延时以方便我们查看实验结果。

int *thread(void* arg)
{
	pthread_t newthid;
	newthid = pthread_self();//get the current thread's id
	printf("this a new thread and thread ID is=%lu\n", newthid);
	sleep(500);
	return NULL;
}

int main()
{
	pthread_t thid;

	printf("main thread,ID is %lu\n", pthread_self());//get the main thread's id
	if (pthread_create(&thid, NULL, (void *)thread, NULL) != 0) {
		printf("thread creation failed\n");
		exit(1);
	}

	printf("my Id is %lu, new thread ID is %lu\n", pthread_self(), thid);
	sleep(1000);
	return 0;
}

我们带开一个终端(称为终端1)运行上述程序,再另一个终端(称为终端2)里使用ps -eLf命令查看系统当前的线程信息。

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
edsionte  2210  2208  2210  0    1 09:10 pts/0    00:00:00 bash
edsionte  2429  2210  2429  0    2 09:52 pts/0    00:00:00 ./createthread
edsionte  2429  2210  2430  0    2 09:52 pts/0    00:00:00 ./createthread
edsionte  2431  2208  2431  5    1 09:52 pts/1    00:00:00 bash
edsionte  2449  2431  2449  0    1 09:52 pts/1    00:00:00 ps -eLf

请注意上述信息中三类ID信息:PID,PPID和LWP。LWP是轻量级进程的pid,NLWP为线程组中线程的个数。下面对上述的实验结果作以解释。

1.运行实验程序的终端对应的pid为2210;

2.我们的实验程序产生了两个线程,其pid都是2429。这说明这两个线程是并列关系,它们属于同一个线程组,该线程组的pid为2429。

3.实验程序产生的两个线程的PPID均为2210,再次说明这两个线程之间没有父子关系,他们的父亲均为终端1对应的进程。

4.每个线程都与一个轻量级进程关联,因此两个线程的LWP不同,分别为2429和2430。

5.这两个线程形成一个线程组,因此他们对应的NLWP为2。

6.通过pid,ppid和LWP的分配情况可以看到,内核对于进程和轻量级进程的id分配是统一管理的,这源于他们使用相同的数据结构task_struct。

上述分析基本上用实验结果诠释了进程、线程和轻量级进程之间的关系。

线程的那些事儿

2011年8月28日

1.线程

通过操作系统原理课,我们知道进程是系统资源分配的基本单位,线程是程序独立运行的基本单位。线程有时候也被称作小型进程,首先,这是因为多个线程之间是可以共享资源的;其次,多个线程之间的切换所花费的代价远远比进程低。

在用户态下,使用最广泛的线程操作接口即为POSIX线程接口,即pthread。通过这组接口可以进行线程的创建以及多线程之间的并发控制等。

2.轻量级进程

如果内核要对线程进行调度,那么线程必须像进程那样在内核中对应一个数据结构。进程在内核中有相应的进程描述符,即task_struct结构。事实上,从Linux内核的角度而言,并不存在线程这个概念。内核对线程并没有设立特别的数据结构,而是与进程一样使用task_struct结构进行描述。也就是说线程在内核中也是以一个进程而存在的,只不过它比较特殊,它和同类的进程共享某些资源,比如进程地址空间,进程的信号,打开的文件等。我们将这类特殊的进程称之为轻量级进程(Light Weight Process)。

按照这种线程机制的理解,每个用户态的线程都和内核中的一个轻量级进程相对应。多个轻量级进程之间共享资源,从而体现了多线程之间资源共享的特性。同时这些轻量级进程跟普通进程一样由内核进行独立调度,从而实现了多个进程之间的并发执行。

3.POSIX线程库的实现

用户线程和内核中轻量级进程的关联通常实在符合POSIX线程标准的线程库中完成的。支持轻量级进程的线程库有三个:LinuxThreads、NGPT(Next-Generation POSIX Threads)和NPTL(Native POSIX Thread Library)。由于LinuxThreads并不能完全兼容POSIX标准以及NGPT的放弃,目前Linux中所采用的线程库即为NPTL。

4.线程组

POSIX标准规定在一个多线程的应用程序中,所有线程都必须具有相同的PID。从线程在内核中的实现可得知,每个线程其实都有自己的pid。为此,Linux引入了线程组的概念。在一个多线程的程序中,所有线程形成一个线程组。每一个线程通常是由主线程创建的,主线程即为调用pthread_create()的线程。因此该线程组中所有线程的pid即为主线程的pid。

对于线程组中的线程来说,其task_struct结构中的tpid字段保存该线程组中主线程的pid,而pid字段则保存每个轻量级进程的本身的pid。对于普通的进程而言,tgid和pid是相同的。事实上,getpid()系统调用中返回的是进程的tgid而不是pid。

5.内核线程

上面所描述的都是用户态下的线程,而在内核中还有一种特殊的线程,称之为内核线程(Kernel Thread)。由于在内核中进程和线程不做区分,因此也可以将其称为内核进程。毫无疑问,内核线程在内核中也是通过task_struct结构来表示的。

内核线程和普通进程一样也是内核调度的实体,只不过他们有以下不同:

1).内核线程永远都运行在内核态,而不同进程既可以运行在用户态也可以运行在内核态。从另一个角度讲,内核线程只能之用大于PAGE_OFFSET(即3GB)的地址空间,而普通进程则可以使用整个4GB的地址空间。

2).内核线程只能调用内核函数,而普通进程必须通过系统调用才能使用内核函数。

 参考:

1. 深入理解Linux内核 第三版

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key