操作系统 - 线程
之前已经讨论过进程了,现在讨论线程。我在想如何用现实中的具体事物来比较进程和线程的关系。
举个我认为较恰当的例子。把进程比作一个工厂中的车间,车间中有若干个生产线,但是每条生产线都需要不同的零件,原料和员工。零件,原料和员工,是所有生产线都可以共同使用的资源。这里就把生产线当做线程吧。这样,每条生产线就只用管自己的生产过程。
就如讨论进程一样,这里还是列举一下线程所包含的实体。
Program counter
Register
Statck
State
不难发现,线程关心的只是下一刻CPU执行所需的必要实体,只需要知道PC等寄存器的信息,当前栈指针,不用关心我有没有子进程啊,我的地址空间在哪里,我打开了什么文件等等的信息。因为这些信息CPU已经知道了。
为什么要使用线程
在《现代操作系统》中已经说明了使用线程的种种优势,很容易就能看明白。其实根据上文,也能猜到答案。这里就不用说明了。
线程实现的方式
线程可以在内核中实现,也可以在用户空间实现。我自己的理解是这样的:在内核中实现就是操作系统提供线程支持;在用户空间中实现就是用户自己实现。本来以为JVM的线程就是在用户空间上实现的,但是搜了一下,貌似Linux平台下是调用Pthred库实现的。这里还是深入学习一下这两种线程的实现方式,为以后的工作和学习打下基础,说不定什么时候就用上了。看了几遍《现代操作系统》中的相关章节,可是自己还是云里雾里的,不是很清楚,这一次就好好的搞明白(不一定搞的明白,目前还没有接触过用户空间实现的线程,也许是我孤陋寡闻)。
用户空间实现线程
在这种情况下,内核不知道线程的存在。当一个进程中的线程执行完毕,不需要进行系统调用(Trap),不需要进行上下文交换,所以线程的切换非常快。
但是在发生I/O中断的时候,必须要内核去处理了。那么问题来了,内核会锁住当前线程所在的进程,因为内核不知道线程的存在,只知道进程。解决这个办法有点麻烦。《现代操作系统》中提出了一个解法,在某些UNIX版本中有一个select系统调用,它可以判断I/O操作是否会阻塞。如果阻塞就不执行I/O操作。这样run-time system(用的英文版教材,很多术语不会翻译或者乱翻译,囧)就知道是执行I/O,还是执行该进程的其它进程。
内核实现线程
内核实现线程和进程区别不大。但是在线程被销毁时,内核并不会销毁线程的数据结构,只是会标记该线程是不可执行的。这样,当新线程被创建时,覆盖不可执行的线程的数据,效率大大的提高了。
还有一个问题,当一个多线程的进程执行fork时,子进程是否需要复制父进程的所有线程还是个别线程,如何操作。这个,因为很少接触Linux下的C编程,所以暂时放在这里吧。
进程和线程的区别
面试的时候,这个问题可能是问的最多的,可以考察归纳能力和是否理解进程和线程。这里给出自己的理解。
首先,进程是操作系统资源分配和调度的基本单元,它包含了程序能够执行的必要资源。而线程也叫做轻权进程,只拥有CPU执行所需的必要资源。没有进程,线程无法单独执行。
其次,进程的执行一般是线程的,一条道走到黑。线程只是进程执行的不同路径,并发的执行。
就写这么多吧。
欢迎大家一起交流和学习啊。
-end-