OS教科书对进程和线程的区别有这样简单的归纳:进程是资源分配的单位,线程是调度的单位。可是Linux内核是不区分进程和线程的,都用任务(task_struct)来表示,何时叫进程何时叫线程,须要视上下文而定。虽没有专门的线程实现,但内核用轻量级进程LWP(Light Weight Process)来代替线程。linux
内核比如服务器,用户任务比如客户端,内核的一切都是为用户态服务的。轻量级进程就是为了支持用户态线程库。服务器
Posix thread是符合posix标准线程库的统称,具体实现有多种,在此不赘述,只要知道线程库的实现按照用户态线程数和内核进程数的比例可分为三种模型:N:1, M:N和1:1。执行下面的命令能够查看你的系统上用的是什么线程库:.net
$ getconf GNU_LIBPTHREAD_VERSION NPTL 2.22
NPTL(Native Posix Thread Lib)是Linux的线程实现,用的是1:1模型。这里有篇文章将的很好,请参考NPTL分析之线程的建立。线程
轻量级进程就是linux所谓的“线程”,它只是共享了父进程不少资源如进程地址空间,文件描述符和信号量等,而独立的资源只有任务描述符task_struct,内核栈等与调度有关的,作到了:资源共享,调度独立。code
共享进程地址空间struct task_struct {struct mm_struct *mm;}
是经过让多个进程的mm
指向同一个虚拟内存struct mm_struct
实现的。经过pthread_create()建立线程时,会经过clone()系统调用传入各类flags组合来决定哪些资源须要与父进程共享。blog
struct mm_struct
表示了一个进程虚拟地址空间,虚拟地址空间的layout不少参考书都有,struct mm_struct {unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end;}
,代码,数据,堆,栈,参数,环境变量各段空间都有指向。而这些虚拟内存段与物理内存的映射关系是怎么创建的呢?答案是经过内存映射mmap。VMA(Virtual Memory Area)列表struct mm_struct {struct vm_area_struct *mmap; /* list of VMAs */}
, 有些vma如动态库,可执行程序是经过mmap, 有些vma如堆,栈是经过匿名映射完成的。进程
进程描述符里有个字段struct task_struct { struct list_head thread_group;}
,明显是想把一个线程组的线程放在一块儿。进程组struct task_struct { pid_t tgid }
, tgid就是线程组里领头进程struct task_struct {struct task_struct *group_leader;}
的pid。内存