分类: LINUX
2012-10-07 16:06:09
1.从操作系统层面理解进程和线程
操作系统最大的作用就是为运行在其上的程序提供系统资源统一管理,操作系统经历了单任务操作系统到多任务操作系统的发展历程。在单任务操作系统的阶段,操作系统上的年程序只能顺序执行,同一时间只能运行一个任务。到了多任务操作系统阶段,操作系统上的程序可以并发执行。这里的并发执行是一个分时的概念,即便只有一个cpu内核,依然可以采用分时共享时间片的方法实现多个任务的并发执行。(当然如果是多核CPU,能够实现微观层次指令级别的真正并发执行)。
在多任务(multitask)操作系统上,很自然地要涉及到各个任务的调度。为什么要调度呢,因为系统资源就那么多。一个萝卜一个坑,萝卜很多坑得数量有限,对于萝卜如何栽的问题就要调度。上面这个例子,一个萝卜就是一个调度的单位。在多任务操作系统上,任务调度的基本单位就是单个的任务(task),对于task实体统一专业的称喟为进程。与之相对应,之前提到的程序,则是一个静态的概念,包含数据和计算机可以执行的指令来完成程序员赋予的使命,单独的程序根据需要可以设计为单进程,也可以多进程。
说到这里似乎只用进程已经万事大吉了,为什么还要拉一个线程来凑热闹。进程作为计算系统资源调度的基本单位时,每个进程占据独立的虚拟地址空间、文件描述符、信号处理等系统资源,创建、销毁、切换进程的系统开销都是比较大的。另一方面从编程的角度进行考虑,进程间通讯(IPC)通常比线程间通讯要复杂得多。例如当多进程程序里面有共享的全局数据时,需要引入共享内存(类unix操作系统叫共享内存,windows里类似的技术是文件映射)。共享内存之类的技术使用起来的一个难点就是,程序员拿到一个指向共享内存的指针后,对其指向的数据的结构化管理。线程从这两面对操作系统的调度机制都是一种补充完善,首先线程通常被实现为轻量级的调度单位,同一进程下的不同线程都可以共享同一个虚拟地址空间、文件描述符、信号处理等资源,线程创建、销毁、切换的系统开销要小得多,同时由于共享内存空间的优势,高级语言中的容器(如C++中的STL)可以方便地用作全局数据的结构化管理。
2.Linux 进程和线程实现
Linux中的线程(thread)通常被称之为light weight processes,这传达了两方面的信息给我们。1.在linux 中并没有严格的区分进程和线程,线程对于linux内核而言也是一种进程2.线程是一种特殊的进程,这种特殊就表现在它占用更少的资源。
对于进程的创建,我们知道有folk调用来创建,提到线程创建我们通常用过或者听说过pthread库的api来创建。通过对最底层系统调用的分析,我们得到了linux平台进程和线程的联系。进程和线程的创建都会调用clone系统调用来完成,只不过由于传递的参数不同,进程和线程的表现就有不同。
提到linux 线程的实现不得不提到内核态线程(kernel thread)和用户态线程(userspace thread)。Linux 很长一段时间内核对线程的支持并不好。
最广为大家认知的一个linux 线程库是pthread,pthread是满足posix thread标准的库,在不同平台上有不同版本。Linux 平台pthread库属于glibc库的一部分。通常链接的libpthread.so历史上实际上有过两个版本的这现,Linux 2.6 之前是linuxthreads 实现,Linux 2.6开始替换为NPTL实现。