操作系统 | 关于进程、线程、用户线程、内核线程
一、进程和线程
进程:操作系统分配资源的最小单位
线程:CPU调度的最小单位
- 每个线程共享进程的代码段
- 每个线程共享进程的数据段
- 每个线程共享进程的堆
- 每个线程都有自己的栈和一些私有的数据,所以相互之间可以不受影响
以上的意思就是进程是线程的”容器“,而线程是可以被CPU调度的最小单元。
执行流:逻辑上独立的指令区域,简单点就是能上CPU执行的,它具有:
- 内存资源
- 一套寄存器映像
- 独立体现在每个执行流都有自己的栈
线程就是一套机制,为一般的代码块创造上下文环境,从而让代码块独立,使这块代码块能被调度器认可,从而能被专门调度到处理器上执行。
比如一个进程上有多个函数,那么对函数A pthread_create,其实就是为函数A创建上下文,让它成为了能在CPU上执行的独立指令区域,即执行流。
线程本质上就是函数。[1]
代码块(函数) + 上下文 = 执行流(线程),可被OS调度。
进程 = 资源 + 线程
二、用户级线程和内核级线程
根据运行环境和调度者的身份,线程可分为内核线程和用户线程。人为分的,CPU无所谓你内核还是用户。
- 内核线程运行在内核空间,由内核来调度
- 用户线程运行在用户空间,线程库调度
这句话很有意思,比如POSIX线程标准,为了可移植性,其实内核根本不知道有用户线程,pthread_create创造了多个线程后,如何能够并发?由POSIX的调度器来操作,一般某个权威机构发布线程库后,开发人员在用户进程中调用此库中的方法创建、结束线程等。线程库中一定存在着线程调度器。[1]
那操作系统怎么给这些用户线程分配时间片运行呢?
答案是内核线程。操作系统只能“看到”内核线程,当进程的一个内核线程获得CPU的使用权后,它就加载并运行一个用户线程。可以说内核线程相当于用户线程运行的”容器“。[2]
三、Linux下调用pthread库创建的线程是用户级线程还是内核级线程的问题?
可以参考这个问题下[大河]的回答。
Linux下调用pthread库创建的线程是属于用户级线程还是内核级线程?
大致意思:
如果你 1:使用2.6的内核的系统平台,2:你的gcc支持NPTL (现在一般都支持),那么你编译出来的多线程程序,就是“内核级”线程了。
线程库为了移植性,只是在用户代码中实现了多线程。
例如在1:N模型中,一个内核线程对应多个用户线程,当操作系统调度至这个内核线程时,需要一个“线程库”(eg. POSIX pthread库) 中间层负责N个用户态线程的调度。
对于Linux而言,采用的是1: 1模型。
四、 参考资料
[1] 《操作系统真象还原》,作者郑钢,P406-P408
[2] 《Linux高性能服务器编程》,作者游双,P269