linux的线程和进程并不区分,其实这完全是设计思想造成的,在linux中,其朴素地继承了unix的思想,就是“任务”代理用户操作“资源”,这里的任务就是进程,而资源就是文件,unix为了纯朴的不做作的实现这个思想,因此才有了一切皆文件的设计同时进程的意义也明显起来。而在windows中,它面对的是丰富的用户应用而不仅仅是为了操作一些资源,比如可以看电影,可以玩游戏,可以...这一切使得还按照用户/进程/资源的大粒度设计变得十分不合适,对于面向丰富用户应用的windows来说,用户不是那么“专业”,当然其需求也就不那么“专一”,因此必须按照更细粒度的“对象”来作为基准设计系统,因此,在一切皆对象的windows里面,创建进程和创建线程是两码事,因为它们是不同的对象(在linux中,它们都是任务的元素)。记住,在linux中,其根本就是任务代理用户实现资源访问,而在windows中其根本就是对象的任意组合实现用户的任意需求。前面的文章不是说linux是小粒度的吗,这里怎么显得windows的粒度更小啊,其实linux的小粒度第一是进程层面上的,第二就是内核元素层面上的,其优势就是使扩展变得灵活容易,而且可以通过组合低消耗地完成巨大任务(注意任务巨大不一定需求复杂,这也就是linux和windows的根本不同之所在),而windows的小粒度就是对象化,这个优势决定了windows很容易实现用户的需求。在《漫谈兼容内核》系列文章中有这么一句话:进程在两个系统中的地位与权利有很大区别。在 Linux 中每个进程都有相当的独立性,有自己的“隐私”和“私有财产”,而在Windows 中一个进程甚至可以替另一个进程创建一个线程。其实想一下就知道这其中的缘由了,毕竟windows就没有把进程当成什么大不了的东西,它就是一个普通的对象,和文件简直没有什么本质的区别。不妨类比一下军事要塞和一个举行Party的礼堂,对于军事要塞,职能单一但是功能强大并且对于访问严格控制,闲人免进,而对于礼堂,大家乱作一团,疯狂畅饮,不亦乐乎,制定严格的制度只会扰乱气氛。
对于调度,两个系统仍不相同,linux的调度器是一种水平的结构,就是调度task_struct,而windows的调度却是一种层次化调度,在调度线程之前要先参考其所在的进程的优先级。但是linux的进程/线程统一化设计也有自己的优点,如果你为一个机制设计两个实体,那么在策略上你就要考虑两个实体,包括它们的互斥,它们的协作等等任何它们之间的交互,然而你只设计一个实体,那么你就可以少考虑很多事情,更加专注地解决需要解决的逻辑,对于linux来说,用task_struct很容易的就可以实现那种分层的层次化调度,而且不同于windows的整体化的严格的必须的分层调度,在linux中,这种分层调度只是调度器的一个策略而已,这就是分组调度,在2.6.25内核得到了增强。在windows中在调度一个线程运行前,必须参考其进程的优先级,这是它的进程/线程分离设计导致的,而对于linux,你想实现任何方式调度只需要给调度器写一个策略既可,调度器为外界提供了调度类,调度组等容器以及一系列的策略设置接口,你想让调度器怎么调度都行,你想实现windows的方式,那么好办,你把所有的属于一个进程的线程放到一个调度组中,然后让调度器分组调度,调度器的分组调度还可以嵌套,层层向上,比如你可以把进程的所有线程作为一组,称组1,然后一个用户的一个类别的进程的所有组1组成组2,然后按照用户组成组3...这种策略很不错,而且依据调度器提供的接口,你还可以做出更好的调度策略。在调度器看来linux的task_struct可以有多种拓扑结构,如果是一个链表,那么就是水平的调度,也就是task_struct的优先级比较然后调度(比如O(n)或者O(1)或者非组方式的cfs),如果是一棵树和简单图,那个就是分组调度了,根据树的高低可以看出组的深浅,你当然可以实现自己的策略使调度器把所有task_struct看成一个图或者一张表,这只是策略实现问题,在windows的调度器看来,所有的线程就是一个链表,然后指向它们的进程,进程也是一个链表,因此调度器看进程和线程就是一张扁平的图。那么除了调度器,别的内核管理机制会看到进程/线程的什么样的拓扑结构呢?众所周知,linux的fork机制可以像细胞分裂一样创建一个又一个新进程,而windows却不是这样的。fork机制让人觉得进程(当然还有线程)们最终会组织成一棵树,比如用pstree可以看到,但是那只是导出给用户的拓扑结构,在内核中其实进程们是一张网状的图,因为各个同级别进程之间会通过链表联系,比如兄弟进程之间的关系,其实在windows中虽然不是fork机制创建新进程,然后也是一张网状图的进程拓扑结构,因为这样容易定位和管理进程,毕竟操作系统再不把进程当回事,也要有进程管理这一块,windows的进程网和linux的进程网所不同的就是linux的网铺开的广度可能更大些,而windows的可能会是扁平状。
回到前面讨论过的问题,unix/linux的本质是任务代理用户访问资源,然后unix把资源统一成了文件这个概念,最终像套接字,管道都成了文件,于是进程作为任务在内核的数据结构,里面必然要有一个表示文件的结构数组,每一个元素代表进程使用的一个文件,这个结构就是打开文件表,对于windows而言,文件并没有被特殊抽象出来,因为没有必要,在windows中,一切都是对象,而且每个对象属于一个类别,实际上每一类对象都代表了一个现实中的实体,比如进程,线程,信号量,文件...windows的本质就是靠这些对象自身的协作满足用户需求而不是访问资源,可是不知道是历史原因导致操作系统理论已经成型还是这么实现不用自己发明轮子从而更简单,windows还是将进程/线程作为了执行任务的用户代理实体,进程作为容器,线程作为执行绪,于是在进程这个特殊的对象里面必然需要描述所有被这个用户代理使用的对象,这就是进程的对象句柄表,表中的每一个元素代表一个该进程使用的对象,类比在linux中的统一的文件资源架构,只要获得一个文件的访问权限,那么任何进程都可以访问,反过来到了windows中,文件统统被对象替代,同样的,只要获得了对象的访问权限就可以访问该对象,有什么错吗?没有!因此,对象的安全描述符才那么重要,因此,windows中才实现了基于角色的复杂的访问控制机制,因此,才有了跨进程创建线程等机制,对象间互访而已!
操作系统的理念—以windows和linux为例
最新推荐文章于 2021-05-14 05:42:24 发布