返璞归真系列——————微内核与宏内核

        我发现我一直是一个后知后觉的人。不知道是心里的浮躁还是自己脑子小装不下那么多知识。不过幸好我还是一个善于思考的人。现在重新想到了要区分一下这两个概念。也不至于稀里糊涂的过着。了解了如下的问题之后更有利于对linux架构的认识。

         在通常情况下,我们会想到把凡是能够为进程服务的模块就应该放在操作系统的内核中。例如:文件管理模块是为进程服务的,所以放在内核中;各种驱动模块是为进程服务的,所以要放在内核中;进程模块当然要放在内核中。随着进程服务请求的增加,操作系统内核就会越来越大,随之也将出现一系列的问题。

        首先,内核是常驻内存的,因此大内核占用的存储空间就大,这样在硬件系统比较小,存储器资源比较紧张的系统就不太适用;其次,是维护起来也比较困难,假设内核中的某一个服务模块进行了修改,那么修改之后就必修对整个系统进行一次编译,显得极不方便;再次,就是使得处理器在内核运行的时间比较长,从而不适合在速度要求比较高的场合下应用。

         总之,操作系统内核大到一定程度之后,会出现一系列因为大而产生的诸多问题。为了解决这些问题,人们想了一系列的办法试图在满足应用程序所需服务的前提下把内核做小。其中一个有效的办法是,把内核各个服务程序模块中的部分内容移到内核外面作为一个进程来看待,在内核中只保留内核服务与用户进程的接口。内核只作为一个消息的中转站,这样内核就大大变小了。这样的内核就叫做微内核。

         宏内核和微内核谁好谁坏也不是我这个菜鸟级水平的人能够评判的。但是如果我把这些代表请上来的话也许大家会在内心对他们有个自己的评价。

          微内核系统有WindowNT,Minix,Mac,etc.宏内核的系统有Unix,Linux,etc。其中有个有意思的现象:Unix是宏内核,而Mac却是微内核。另外废话一句:minix和linux也都没说服对方。

          两个系统的内核是通过进程的创建FORK的实现比较,因为进程的创建涉及到系统调用,内存管理,文件管理等系统的主要方面。因此可以通过比较fork来大致了解一下内核的差别。

微内核的代表Minix

        在Minix中,操作系统的内核,内存管理,系统管理都有自己的进程表,每个部分的表包含了自己需要的域。表是精确对应的,为了保持同步,在进程创建和结束时,这三个部分都要更新自己的表。由内存管理器协调。

       系统启动后,kernel,mm,fs系统进程在各自的空间运行main()函数循环等待消息

      while (true)

                   {

                             ……

                            receive(ANY,&mm_in);

                             ……

                   }

        当一个fork传给mm的main(),main()调用do_fork(),do_fork()函数把父i函数的data、segment和stack segment创造了一个精确副本给子进程,并把父进程的text segment与子进程共享,然后在mm的进程表mproc[ ]中添加新进程,并设置各属性。添加完后发送消息给kernel(sys_fork(...))和fs(tell_fs(...)),kernel中的函数sys_task()接收到系统消息,调用do_fork( message *m_ptr),拷贝父进程的proc 结构体到子进程,并设置进程在内核进程表中的属性。tell_fs( )是内存管理器与文件系统之间的接口。tell_fs(...)调用_taskcall(...),文件管理器接收到fork系统消息,调用do_fork( )函数,拷贝父进程的 fproc 结构体到子进程并设置进程在文件进程表中的属性。这样整个进程的属性就设置完成。

       在Minix创建新进程的过程中,可以看到一个很大特点,就是整个系统按照功能分成几个部分,各模块之间利用消息机制通信,调用其他模块的函数必须通过目标模块的守护进程调用完成。

宏内核的代表:linux

      在linux中,进程的结构如下:

        struct task_struct{

               pid_t pid;

               pid_t pgrp;

              ...

             /*filesystem information*/

            struct fs_struct *fs;

           /*memory managment info */

          struct mm_struct *mm;

         ...   

        };

       在linux进程的结构定义中,task_struct包含了所有的信息,包括进程的内存情况,文件系统情况。在创建进程时,系统调用sys_fork调用do_fork(...)函数。

      int do_fork(unsigned long clong_flags,...)

        {

             struct task_struct *p;

             p->pid = get_pid(clone_flags);

             ....

            /*copy all the process information*/

        copy_files(clone_flags,p);

        copy_fs(clone_flags,p);

         copy_mm(nr,clone_flags,p);

          ...

        }

         在创建进程时,do_fork函数把所有的工作完成,分配pid。。。号,拷贝父进程数据段,堆栈段,等等。linux的进程创建过程是一个完整的过程,直接调用其他模块的函数,而不是消息传递。

          Minix与Linux创建新进程的过程比较可以看出两者之间的区别,Minix是建立在分模块之上的,模块之间以信息传递联系。Linux内部是分模块的,但是在运行的时候,它是一个独立的二进制大映像,其模块之间的通讯是直接调用其他模块中的函数实现的。宏内核与微内核的区别也就在此。微内核是一个信息中转站,自身完成的功能很少,主要是传递一个模块对另一个模块的功能请求,而宏内核则是一个大主管,把内存管理,文件管理等等一股脑全部接管。

          从理论上来看,微内核的思想更好一些,微内核把系统分为各个小的功能模块,降低了设计难度,系统的维护与修改也容易,但是通信带来的损失效率是个问题。宏内核的功能块之间的耦合度太高造成修改与维护的代价太高,不过在目前的linux里面还不是太大的问题,因为目前linux还不算太复杂,宏内核因为是直接调用的,所以效率比较高。

你可能感兴趣的:(linux,struct,unix,存储,通讯,文件管理器)