我正在学习系统编程并遵循这本书"Linux编程接口";。
在第29.9和29.10节中,提交人称
在多线程应用程序中,所有线程必须运行同一程序(尽管可能在不同的函数中)。在多进程应用程序中,不同的进程可以运行不同的程序。
和
在多线程进程中,多个线程同时执行相同的程序。
那么,在这种情况下说the same program
是什么意思呢?看完这句话后,我觉得所有线程都在同一时间执行相同的任务!?
那么,在这种情况下说同一个程序意味着什么?
它意味着在同一地址空间中运行的相同可执行代码。进程中的所有线程共享进程地址空间。这意味着他们共享:
- 可执行代码
- 全局变量
- 堆
- 与文件系统或其他进程共享的任何内存段
这基本上就是正在执行的程序。
(线程甚至共享所有线程堆栈;即一个线程不会被OS阻止查看另一个线程的堆栈。然而,我想不出有什么好的理由让一个线程查看另一个线程的堆栈。)
看完这句话后,我觉得所有线程都在同一时间执行相同的任务!?
嗯。。。嗯。。。是和否
他们可能真的在做同样的事情,但他们可能不是。他们可能正在对一个大问题的不同部分进行类似的计算。或者处理不同的请求。但如果它们具有不相关的";使命";对他们来说,成为同一程序和/或过程的一部分可能是没有意义的。
我认为线程和进程都是一次做多件事的方式。
-
进程不能共享对象、变量等。(除非你使用共享内存段。)它们通常不相互信任或合作。
-
线程可以(通常也可以)共享对象、变量等。他们需要相互信任,相互合作。
在操作系统中:
- 线程 是执行的单位
- 过程 是隔离的单位
此处的程序表示加载到内存并映射到进程虚拟地址空间的所有可执行代码。每个线程都可以执行该程序的不同部分,并维护自己的一组CPU寄存器值,并有自己的堆栈——尽管从技术上讲,即使是它的堆栈也存储在同一进程中的所有线程都可以访问的内存中。但是,线程无法访问加载到不同进程中的代码,也无法从另一个进程访问内存,也无法使用任何文件或内核对象的句柄(如果不首先通过向操作系统发出共享它们的特殊请求来明确共享这些东西)。因此,作者声称一个进程中的所有线程都在执行同一个程序,但它们不一定都在该程序的完全相同的指令上。每个线程都有自己的指令指针,它只是存储下一个要执行的机器代码字节的内存位置的虚拟地址。一个线程当前可能在程序的指令#3,另一个线程可能在同一程序的指令#103,这可能是完全不同功能的代码。
请允许我用一个扩展的比喻
每个线程就像一个面包师,按照特定的食谱一步一步地准备一些食物。过程类似于厨房。由于所有面包师都在同一个厨房,他们必须共享烤箱、碗、餐具等。实际上,他们可以很容易地进入整个厨房,包括其他面包师正在使用的东西。一个行为不端的面包师可能会把一种配料放入另一个面包师正在使用的碗中。或者修改普通烤箱的温度设置。同一厨房的面包师必须协调使用共享资源,并注意不要意外干扰另一位面包师的工作。
不同厨房的面包师彼此隔离。如果他们在一个厨房里做海鲜,但有人对海鲜过敏,危及生命,那么最好在一个完全不同的厨房里准备食物,那里的冰箱里没有海鲜原料。如果你不能信任其他面包师,这真的很重要。这就是我们用不同的厨房(不同的工艺)将面包师彼此隔离的方式。一个厨房发生火灾(就像程序崩溃一样)不会影响其他厨房正在进行的任何烘焙。
想想程序,就像厨房里任何印有说明的东西。这是所有食谱的集合,所有电器的手册,甚至是写在厨房墙上标志上的应急程序。面包师只能按照厨房里的说明书操作。尽管他们可以按照厨房里任何书籍或手册的任何一页上的说明进行操作。
不同的面包师可以遵循同一本书的不同页面上的说明,也可以完全不同的书,甚至可以目前遵循同一食谱的完全相同的说明。但他们不能突然开始遵循一本不在厨房的书中的说明(另一个程序)。比如,如果厨房里没有海鲜食谱,面包师就无法遵循这些说明,也无法制作任何海鲜。面包师只能烘焙厨房里的食谱。
所以想象一下,一个厨房里只有一本厨师皮埃尔的法式烹饪食谱。如果这是厨房里唯一的一本书,那么面包师所能做的就是烤法式烹饪食谱,因为厨房里根本没有其他食谱可以遵循。所有面包师都在使用相同的食谱(运行相同程序)。但一位面包师可能刚刚准备好《料理鼠王》,而另外两位面包商都在为书中的蛋奶酥食谱做最后的润色。与此同时,在街上,可能还有另一个厨房,配备了一套完全不同的食谱——也许是我们以前的海鲜餐厅。这两个厨房将使用不同的食谱(运行不同的程序)。可以想象,在另一个厨房的某个地方,他们也有一本厨师皮埃尔的书。在这种情况下,你会有两个不同的厨房能够准备相同的食谱(运行相同程序的两个不同过程)
因此:
- 单线程=一个面包师
- 多线程=同一厨房中有多个面包师
- 单一流程-一个厨房(任意数量的面包师)
- 多工序=多个厨房(每个厨房有任意数量的面包师)