精华内容
下载资源
问答
  • 本文基于 LINUX2.6.18 内核,从 SCSI 设备访问请求的提交,SCSI 命令的处理、错误恢复几个方面浅析了 LINUX 内核中 SCSI 子系统的 IO 的处理机制。 概述 LINUX 内核中 SCSI

    Linux 内核 SCSI IO 子系统分析

    研究 LINUX 内核中 SCSI 子系统处理 IO 的过程

    本文基于 LINUX2.6.18 内核,从 SCSI 设备访问请求的提交,SCSI 命令的处理、错误恢复几个方面浅析了 LINUX 内核中 SCSI 子系统的 IO 的处理机制。

    概述

    LINUX 内核中 SCSI 子系统由 SCSI 上层,中间层和底层驱动模块 [1] 三部分组成,主要负责管理 SCSI 资源和处理其他子系统,如文件系统,提交到 SCSI 子系统中的 IO 请求。因此,理解 SCSI 子系统的 IO 处理机制对理解整个 SCSI 子系统就显的十分重要,同时也有助于理解整个 LINUX 内核的 IO 处理机制。本文从 SCSI 设备访问请求的提交,SCSI 子系统对访问请求的处理和 SCSI 子系统错误处理三个方面,阐述了 SCSI 子系统的 IO 处理机制。

    SCSI 设备访问请求的提交

    SCSI 设备访问请求的提交分为两个步骤:用户空间提交访问请求到通用块层以及通用块层提交块访问请求到 SCSI 子系统。

    用户空间提交访问请求到通用块层

    在 LINUX 用户空间,有三种方式提交对 SCSI 设备的访问请求到通用块层:

    • 通过文件系统提供的文件访问接口进行访问。对建立在 SCSI 设备上的 LINUX 文件系统中的文件读写操作,就属于这种访问方式;
    • RAW 设备访问方式。这种访问方式比较常见的应用就是dd命令。 RAW 设备访问方式和通过文件系统提供的文件访问接口进行访问的最大区别在于前者对 SCSI 设备直接进行线性地址访问,不需要由文件系统进行地址映射;
    • SCSI PASSTHROUGH 方式。通过 LINUX 提供的 SG 进行访问,就属于这种方式,用户可以直接发 CDB[2] 命令给 SCSI 设备。所以,通过该接口,用户可以做一些 SCSI 管理操作,如 SES 管理等。

    图 1 显示了 LINUX 内核对于三种请求提交方式的处理过程。

    图 1. LINUX 内核处理三种访问请求的方式
    LINUX 内核处理三种访问请求的方式

    经由文件系统或 RAW 设备方式提交的请求,会通过底层块设备访问层(ll_rw_block()),由其生成块 IO 请求(BIO),并提交给通用块层 [3] ;而通过 SG 接口提交的访问请求,会调用 SCSI 中间层提供的接口,将请求直接交由通用块层进行处理。

    通用块层提交块访问请求到 SCSI 子系统

    为什么要通过通用块层呢?这是因为首先通用块层会根据磁盘访问的特性对请求进行优化操作;其次,通用块层提供了调度功能,能够对请求进行调度;再次,通用块层可扩展的结构,使各种设备的块驱动都能比较容易的和其集成。

    当请求提交到通用块层后,通用块层需要完成准备,调度并交付块访问请求给 SCSI 中间层的操作。块访问请求可以理解为描述了块访问区域,访问方式和关联的 BIO 的请求,在内核中用 'struct request'结构表示。块设备会有对应的块访问请求设备队列,用于记录需要该设备处理的访问请求,新生成的块访问请求会被加入到对应设备的块访问请求队列中。 SCSI 子系统对 IO 的处理,实际上是处理块访问请求队列上的块访问请求。

    通用块层提供了两种方式调度处理块访问请求队列:直接调度和通过 LINUX 内核工作队列机制调度执行。两种方式,最后都会调用块访问请求队列处理函数进行处理,而 SCSI 设备在初始化时会向通用块层注册 SCSI 子系统定义的块访问请求队列处理函数。清单 1[4] 显示了这个过程。这样当通用块层处理 SCSI 设备的块访问请求队列时,调用的就是 SCSI 中间层定义的这些处理函数。通过这种方式,通用块层就将块访问请求的处理交给了 SCSI 子系统。

    清单 1. 处理函数
    struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) 
     {   ……
        q = blk_init_queue(scsi_request_fn, NULL);
         //request generate block layer allocate a request queue 
        ……
        blk_queue_prep_rq(q, scsi_prep_fn); //Prepare a scsi request 
        blk_queue_max_hw_segments(q, shost->sg_tablesize); 
        //define sg table size 
        ……
        blk_queue_softirq_done(q, scsi_softirq_done); 
     }

    SCSI 子系统处理块访问请求

    当 SCSI 子系统的请求队列处理函数被通用块层调用后,SCSI 中间层会根据块访问请求的内容,生成、初始并提交 SCSI 命令 (struct scsi_cmd) 到 SCSI TARGET 端。

    SCSI 命令初始化和提交

    SCSI 命令记录了命令描述块 (CDB),感测数据缓存 (SENSE BUFFER),IO 超时时间等 SCSI 相关的信息和 SCSI 子系统处理命令需要的一些其他信息,如回调函数等。清单 2 显示了这个命令的主要结构。

    清单 2. 主要结构
    struct scsi_cmnd { 
        ……
        void (*done) (struct scsi_cmnd *); 	 /* Mid-level done function */ 
        ……
        int retries;                /*retried time*/ 
        int timeout_per_command;   /*timeout define*/ 
        ……
        enum dma_data_direction sc_data_direction;  /*data transfer direction*/ 
        ……
        unsigned char cmnd[MAX_COMMAND_SIZE];   /*cdb*/ 
        void *request_buffer; 		 /* Actual requested buffer */ 
        struct request *request; 	 /* The command we are working on */ 
        ……
        unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; 
                                   /* obtained by REQUEST SENSE when 
                                   * CHECK CONDITION is received on original 
                                   * command (auto-sense) */ 
        /* Low-level done function - can be used by */
        /*low-level driver to point  to completion function. */ 
        void (*scsi_done) (struct scsi_cmnd *); 
        ……
     };

    初始化的过程首先按照电梯调度算法,从块设备的请求队列上取出一个块访问请求,根据块访问请求的信息,定义 SCSI 命令中数据传输的方向,长度和地址。其次,定义 CDB,SCSI 中间层的回调函数等。

    在完成初始化后,SCSI 中间层通过调用scsi_host_template[5]结构中定义queuecommand函数将 SCSI 命令提交给 SCSI 底层驱动部分。queuecommand函数,是一个 SCSI 命令队列处理函数,在 SCSI 底层驱动中,定义了queuecommand函数的具体实现。因此,SCSI 中间层,调用queuecommand函数实际上就是调用了底层驱动定义的queuecommand函数的处理实体,将 SCSI 命令提交给了各个厂家定义的 SCSI 底层驱动进行处理。这个过程和通用块设备层调用 SCSI 中间层的处理函数进行块请求处理的机制很相似,这也体现了 LINUX 内核代码具有很好的扩展性。底层驱动接受到请求后,就要开始处理 SCSI 命令了,这一层和硬件关系紧密,所以这块代码一般都是由各个厂家自己实现。基本流程可概括为:从底层驱动维护的队列中,取出一个 SCSI 命令,封装成厂家自定义的请求格式,然后采用 DMA 或者其他方式,将请求提交给 SCSI TARGET 端,由 SCSI TARGET 端对请求处理,并返回执行结果给 SCSI 底层驱动层。

    SCSI 命令执行结果的处理

    当 SCSI 底层驱动接受到 SCSI TARGET 端返回的命令执行结果后,SCSI 子系统主要通过两次回调过程完成对命令执行结果的处理。 SCSI 底层驱动在接受到 SCSI TARGET 端返回的命令执行结果后,会调用 SCSI 中间层定义的回调函数,将处理结果交付给 SCSI 中间层进行处理,这是第一次回调过程。 SCSI 中间层处理完成后,将调用 SCSI 上层定义的回调函数,结束 IO 在整个 SCSI 子系统中的处理,这为第二次回调过程。

    第一次回调:

    SCSI 中间层在调用queuecommand函数将 SCSI 命令提交给 SCSI 底层驱动的同时,也将回调函数指针传给了 SCSI 底层驱动。底层驱动接受到 SCSI TARGET 端返回的命令执行结果后,会调用该回调函数,产生一个中断号为 BLOCK_SOFTIRQ 的软中断进行第一次回调处理。在这次回调处理过程中,SCSI 中间层首先会根据 SCSI 底层驱动处理的结果判断请求处理是否成功。处理成功,并不意味着处理没有错误,而是返回的信息,能够让 SCSI 中间层很明确的知道,对于这个命令,中间层已经没有必要继续进行处理了。所以,对于处理成功的 SCSI 命令,SCSI 中间层会调用第二次回调函数进入到第二次回调过程。清单 3 显示了 SCSI 中间层定义的该软中断的处理函数。

    清单 3. 该软中断的处理函数
    static void scsi_softirq_done(struct request *rq) 
     { 
        ……
        disposition = scsi_decide_disposition(cmd); 
        ……
        switch (disposition) { 
          case SUCCESS: 
            scsi_finish_command(cmd);   
            //enter to second callback process 
            break; 
          case NEEDS_RETRY: 
            scsi_retry_command(cmd); 
            break; 
          case ADD_TO_MLQUEUE: 
            scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); 
             break; 
           default: 
             if (!scsi_eh_scmd_add(cmd, 0)) 
                scsi_finish_command(cmd); 
        } 
     }

    第二次回调:

    不同的 SCSI 上层模块会定义自己不同的第二次回调函数,如 SD 模块,会在sd_init_command函数中,定义自己的第二次回调函数sd_rw_intr,这个回调函数会根据 SD 模块的需要,对 SCSI 命令执行的结果做进一步的处理。清单 4 显示了 SD 模块注册第二次回调的代码。虽然各个 SCSI 上层模块可以定义自己的第二次回调函数,但是这些回调函数最终都会结束 SCSI 子系统对这个块访问请求的处理。

    清单 4. SD 模块注册第二次回调的代码
    static int sd_init_command(struct scsi_cmnd * SCpnt) 
     { 
        ……
        SCpnt->done = sd_rw_intr; 
        return 1; 
     }

    SCSI 子系统的错误处理

    由于 SCSI 底层驱动是由厂商自己实现的,在此就不予讨论。除此之外,SCSI 子系统的出错处理,主要是由 SCSI 中间层完成。在第一次回调过程中,SCSI 底层驱动将 SCSI 命令的处理结果以及获取的 SCSI 状态信息返回给 SCSI 中间层,SCSI 中间层先对 SCSI 底层驱动返回的 SCSI 命令执行的结果进行判断,若无法得到明确的结论,则对 SCSI 底层驱动返回的 SCSI 状态、感测数据等进行判断。对于判断结论为处理成功的 SCSI 命令,SCSI 中间层会直接进行第二次回调;对于判断结论为需要重试的命令,则会被加入块设备请求对列,重新被处理。这个过程可称为 SCSI 中间层对 SCSI 命令执行结果的基本判断方法。

    一切看起来似乎是这么简单,但是实际上并非如此,有些错误是没有明确的判断依据的,如感测数据错误或 TIMEOUT 错误。为了解决这个问题,LINUX 内核中 SCSI 子系统引入了一个专门进行错误处理的线程,对于无法判断错误原因的 SCSI 命令,都会交由该线程进行处理。线程处理过程和两个队列密切相关,一个是错误处理队列(eh_work_q),一个是错误处理完成队列 (done_q) 。错误处理队列记录了需要进行错误处理的 SCSI 命令,错误处理完成队列记录了在错误处理过程中被处理完成的 SCSI 命令。清单 5 显示了线程对错误处理队列上记录的命令进行错误处理的过程。

    清单 5. 错误处理的过程
    scsi_unjam_host{ 
        ……
        if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))  
         //get sense data 
            if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q))   
            //abort command 
    	    scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);   
    	    //reset 
        scsi_eh_flush_done_q(&eh_done_q);   
        //complete error io on done_q 
        ……
     }

    整个处理过程可归纳为四个阶段:

    • 感测数据查询阶段

      通过查询感测数据,为处理 SCSI 命令重新提供判断依据,并按照前述基本判断方法进行判断。如果判断结果为成功或者重试,则可将该命令从错误处理队列移到错误处理完成队列。若判断失败,则命令将会继续保留在 SCSI 错误处理队列中,错误处理进入到 ABORT 阶段。

    • ABORT阶段

      在这个阶段中,错误处理队列上的 SCSI 命令会被主动 ABORT 掉。被 ABORT 的命令,会被加入到错误处理完成队列。若 ABORT 过程结束,错误处理队列上还存在未能被处理的命令,则需进入 START STOP UNIT 阶段进行处理。

    • START STOP UNIT阶段

      在这个阶段,START STOP UNIT[6] 命令会被发送到与错误处理队列上的命令相关的 SCSI DEVICE 上,去试图恢复 SCSI DEVICE,如果在 START STOP UNIT 阶段结束后,依旧有命令在错误处理队列上,则需要进入 RESET 阶段进行处理。

    • RESET阶段

      RESET 阶段的处理过程分三个层次:DEVICE RESET,BUS RESET 和 HOST RESET 。首先对与错误队列上的命令相关的 SCSI DEVICE,进行 RESET 操作,如果 DEVICE RESET 后,SCSI 设备能处于正常状态,则和该设备相关的错误处理队列上的错误命令,会被加入到错误处理完成队列中。若通过 DEVICE RESET 不能处理所有的错误命令,则需进入到 BUS RESET 阶段,BUS RESET 会对与错误处理队列上的命令相关的 BUS,进行 RESET 操作。若 BUS RESET 还不能成功处理所有错误处理队列上的 SCSI 命令,则会进入到 HOST RESET 阶段,HOST RESET 会对与错误处理队列上的命令相关的 HOST 进行 RESET 操作。当然,很有可能 HOST RESET 也不能成功处理所有错误命令,则只能认为错误处理队列上错误命令相关的 SCSI 设备不能被使用了。这些不能被使用的设备会被标记为不能使用状态,同时相关的错误命令都会被加入到错误处理完成队列中。

    对于被加入到错误处理完成队列上的请求,若是在设备状态正确,命令重试次数小于允许次数的情况下,这些命令将被重新加入到块访问请求队列中,进行重新处理;否则,直接进行第二次回调处理,完成 SCSI 子系统对块访问请求的处理。这样,SCSI 子系统就完成了 SCSI 命令错误处理的整个过程。

    结束语

    本文浅析了 SCSI 子系统中的 IO 处理机制,希望对大家理解 SCSI 子系统和块设备驱动能有所帮助。

    展开全文
  • 对计算机硬件有一定了解之后,对理解Linux内核中的设备和驱动模型非常有帮助。如图1是常规计算机的硬件架构简图。 这里面需要重点理解的概念包括:总线、PCI桥和设备三个概念。我们下面大概介绍一下这几个概念的...

    关于硬件架构

    想要了解Linux操作系统的内核设备和驱动模型,最好先了解一下现在计算机硬件的架构。对计算机硬件有一定了解之后,对理解Linux内核中的设备和驱动模型非常有帮助。如图1是常规计算机的硬件架构简图。

    图1 计算机硬件架构简图

    这里面需要重点理解的概念包括:总线、PCI桥和设备三个概念。我们下面大概介绍一下这几个概念的含义:

    总线: 我们知道计算机通常包括几大件,CPU、内存、输入设备和输出设备等。这些设备之间进行通信需要依赖一种通道,这个通道就是总线。说的直白写,总线就是传输数据的通道,可以类比日常生活中的马路,各个不同的城市通过马路来交换物资。总线有很多种,比如常见的PCI总线,ISA总线和I2C总线等等,我们这里就不相信介绍。

    PCI桥: PCI桥是连接PCI总线的纽带,其作用与网络领域的网桥类似。其实我们平时说的北桥,就包含PCI桥。PCI桥主要分3种,3种桥的具体含义如下:

    1. HOST/PCI桥:提供CPU和PCI设备相互访问的通道,实现CPU空间和PCI空间的映射。
    2. PCI-PCI桥:实现PCI设备的级联。
    3. PCI/ISA或LPC桥:实现对ISA设备的兼容。

    设备:设备就是具体的设备了,比如网卡、键盘和鼠标等等。

    Linux中的设备软件模型

    为了降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等,Linux内核提出了设备模型(也称作Driver Model)的概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现。Linux中的软件概念与实际物理的概念有一个大致的对应关系,在内核中相关的概念主要包括Bus、Device、Device Driver和Class等。下面是Linux对上述概念的介绍:

    Bus(总线):Linux认为(可以参考include/linux/device.h中struct bus_type的注释)总线是CPU和一个或多个设备之间信息交互的通道。而为了方便设备模型的抽象,所有的设备都应连接到总线上。Linux总线是在上述物理总线基础上做的抽象,它可以对应物理总线,也可以没有对应物理总线。

    Device(设备):抽象系统中所有的硬件设备,描述它的名字、属性、从属的Bus、从属的Class等信息。

    Device Driver(驱动):Linux设备模型用Driver抽象硬件设备的驱动程序,它包含设备初始化、电源管理相关的接口实现。而Linux内核中的驱动开发,基本都围绕该抽象进行(实现所规定的接口函数)。

    Class(分类):在Linux设备模型中,Class的概念非常类似面向对象程序设计中的Class(类),它主要是集合具有相似功能或属性的设备,这样就可以抽象出一套可以在多个设备之间共用的数据结构和接口函数。因而从属于相同Class的设备的驱动程序,就不再需要重复定义这些公共资源,直接从Class中继承即可。

    设备模型的核心思想

    前面介绍了Linux的设备软件模型相关的概念,下面介绍一下各种概念间的关系。对于Linux来说,其软件层面的模型与硬件基本是一致的。由图1, 如果把CPU和内存开成一个树根的话,整个计算机的设备间的关系其实类似一个树,总线类似于树枝。Linux内核在具体实现的时候也是按照此规律进行的,最底层的是根总线(bus),然后是各种具体类型的总线(bus_type),而其下则是设备(device)。

    图2 Linux内核驱动关键数据结构

    **如图2所示,Linux内核针对上面介绍的概念,实现了具体的数据结构。**数据结构的名称基本与硬件类型名称一致。比如bus_type表示某种类型的总线,device表示一个物理设备等。

    设备和驱动: 用Device(struct device)和Device Driver(struct device_driver)两个数据结构,分别从“有什么用”和“怎么用”两个角度描述硬件设备。这样就统一了编写设备驱动的格式,使驱动开发从论述题变为填空体,从而简化了设备驱动的开发。

    总线与设备: 通过"Bus–>Device”类型的树状结构解决设备之间的依赖,而这种依赖在开关机、电源管理等过程中尤为重要。

    试想,一个设备挂载在一条总线上,要启动这个设备,必须先启动它所挂载的总线。很显然,如果系统中设备非常多、依赖关系非常复杂的时候,无论是内核还是驱动的开发人员,都无力维护这种关系。

    而设备模型中的这种树状结构,可以自动处理这种依赖关系。启动某一个设备前,内核会检查该设备是否依赖其它设备或者总线,如果依赖,则检查所依赖的对象是否已经启动,如果没有,则会先启动它们,直到启动该设备的条件具备为止。而驱动开发人员需要做的,就是在编写设备驱动时,告知内核该设备的依赖关系即可。

    : 使用Class结构,在设备模型中引入面向对象的概念,这样可以最大限度地抽象共性,减少驱动开发过程中的重复劳动,降低工作量。在Linux内核驱动中,类是对具有共性的设备的抽象,比如显示设备类,音频设备类和SCSI设备类等等。比如SCSI设备类包括磁盘设备、光驱设备和USB设备等。

    即插即用: 在现代操作系统中即插即用成为常态,我们普通PC的U盘、光驱等都是即插即用的。而对于企业级的服务器甚至要求CPU和内存等组件都是可以即插即用的。

    即插即用的实现同样借用Device和Device Driver两个数据结构。在Linux内核中,只要任何Device和Device Driver具有相同的名字,内核就会执行Device Driver结构中的初始化函数(probe),该函数会初始化设备,使其为可用状态。

    而对大多数热拔插设备而言,它们的Device Driver一直存在内核中。当设备没有插入时,其Device结构不存在,因而其Driver也就不执行初始化操作。当设备插入时,内核会创建一个Device结构(名称和Driver相同),此时就会触发Driver的执行。这就是即插即用的概念。

    SCSI设备示例

    SCSI设备是Linux内核中支持的众多设备中的一种。SCSI设备也遵循上面介绍的设备、驱动和总线的结构,但略有不同。Linux内核中抽象了一个称谓SCSI总线的虚拟总线。而在SCSI总线上又包含SCSI的驱动和设备。

    图3 SCSI体系结构

    SCSI整个架构分为3层,其中中间是中间层,用于实现SCSI的公共功能,比如错误处理等。而上面一层称谓高层,它代表各种scsi设备类型的驱动,如scsi磁盘驱动,scsi磁带驱动,高层驱动认领低层驱动发现的scsi设备,为这些设备分配名称,将对设备的IO转换为scsi命令,交由低层驱动处理。而最下面的称谓底层,它代表与SCSI的物理接口的实际驱动器,主要为各个厂商为其特定的主机适配器(Host Bus Adapter, HBA)驱动,例如: FC卡驱动、SAS卡驱动和iSCSI(iSCSI可以使硬件HBA卡或者基于普通网卡的软件实现)等。

    在图3中,Disk Driver就是一个SCSI磁盘驱动,通过该驱动对用户呈现一个普通的磁盘。中间层的驱动是必须第一个被内核加载的,如果编译成内核模块的话,该内核模块为scsi_mod。然后是上层的驱动和底层的驱动。以SCSI磁盘为例,加载的模块是sd_mod。

    在SCSI中实现对应上述概念的结构体包括scsi_driver、scsi_device和SCSI类型的总线(bus)。其中SCSI类型的总线并没有定义一个特别的数据结构体,而是对bus_type数据结构的实例化。

    需要说明的是对于SCSI设备,其实现又是比较复杂的。我们以光纤适配卡为例,其中一个适配卡又包含多个通路,而每个通路同网络的方式可以跟多个存储设备连接。因此,对于SCSI设备来说,实现上要复杂很多。

    图4 光纤适配卡

    在内核中通过Scsi_Host、scsi_target等结构体表示上述概念。具体细节本文不再详述,后面我们再详细介绍SCSI体系架构、FC相关流程和iSCSI相关流程。

    展开全文
  • Linux内核主要由五个子系统组成: 进程调度内存管理虚拟文件系统网络接口进程间通信 (1)进程调度(SCHED) 控制系统多个进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可...

    一、linux体系结构

    (1)用户空间:用户空间中又包含了,用户的应用程序,C库

    (2)内核空间:内核空间包括,系统调用,内核,以及与平台架构相关的代码


    Linux内核可以划分为3层,最上面是系统调用层(SCI),它实现了一些基本的功能,such as read and write。系统调用接口之下是内核代码,可以更加精确地定义为独立于体系结构的内核代码,这些代码是Linux所支持的所有处理器体系结构所通用的。在这些代码之下是依赖于体系结构的代码(Architecture-Depandent Kernel Code),构成通常称为BSP(Board Support Package)的部分,这些代码用作给定体系结构的处理器和特定于平台的代码。


        上图展示了整个进程地址空间的分布,其中4G的地址空间分为两部分,在用户空间内,对应了内存分布的五个段:数据段、代码段、BSS段、堆、栈。

    二、Linux内核结构

    主要由个子系统组成:

    • 进程调度
    • 内存管理
    • 虚拟文件系统
    • 网络接口
    • 进程间通信


    1)进程调度(SCHED)

           控制系统中多个进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。在系统运行时,每个进程都会分得一定的时间片,然后进程调度器根据时间片的不同,选择每个进程依次运行,例如当某个进程的时间片用完后,调度器会选择一个新的进程继续运行。由于切换的时间和频率都非常的快,由此用户感觉是多个程序在同时运行,而实际上,CPU在同一时间内只有一个进程在运行,这一切都是进程调度管理的结果。使得多个进程“微观串行,宏观并行”地执行。

    (2)内存管理(MMU)

           内存管理的主要作用是控制多个进程安全地共享内存区域。当CPU提供内存管理单元(MMU)时,Linux内存管理完成为每个进程进行虚拟内存到物理内存的转换。Linux 2.6引入了对无MMU CPU的支持。

           一般而言,Linux的每个进程享有4GB的内存空间,0~3GB属于用户空间,3~4GB属于内核空间,内核空间对常规内存、I/O设备内存以及高端内存存在不同的处理方式。

    (3)虚拟文件系统(VFS)

           隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。

    (4)网络接口(NET)

           提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。

    (5)进程间通讯(IPC) 

           进程通信支持进程间的通信,Linux支持进程间的多种进程的通信机制,包含信号量、共享内存、管道等。这些机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。

    进程间通信主要用于控制不同进程之间在用户空间的同步、数据共享和交换。由于不用的用户进程拥有不同的进程空间,因此进程间的通信要借助于内核的中转来实现。一般情况下,当一个进程等待硬件操作完成时,会被挂起。当硬件操作完成,进程被恢复执行,而协调这个过程的就是进程间的通信机制。

    各个子系统之间的依赖关系如下:
    1.进程调度与内存管理之间的关系:这两个子系统互相依赖。在多道程序环境下,程序要运行必须为之创建进程,而创建进程的第一件事情,就是将程序和数据装入内存。
    2.进程间通信与内存管理的关系:进程间通信子系统要依赖内存管理支持共享内存通信机制,这种机制允许两个进程除了拥有自己的私有空间,还可以存取共同的内存区域。
    3.虚拟文件系统与网络接口之间的关系:虚拟文件系统利用网络接口支持网络文件系统(NFS),也利用内存管理支持RAMDISK设备。
    4.内存管理与虚拟文件系统之间的关系:内存管理利用虚拟文件系统支持交换,交换进程(swapd)定期由调度程序调度,这也是内存管理依赖于进程调度的唯一原因。当一个进程存取的内存映射被换出时,内存管理向文件系统发出请求,同时,挂起当前正在运行的进程。

    处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。

    1、系统调用接口

    SCI层(system callinterface)为用户空间提供了一套标准的系统调用函数来访问Linux内核,搭起了用户空间到内核空间的桥梁

    2、进程管理

    进程管理的重点是创建进程(fork、exec),停止进程(kill、exit),并控制它们之间的通信(signal或者POSIX)。进程管理还包括控制活动进程如何共享CPU,即进程调度

    3、内存管理

    内存管理的主要作用是控制多个进程安全地共享内存区域

    4、网络协议栈

    内核协议栈为Linux提供了丰富的网络协议的实现

    5、虚拟文件系统(VFS)

    VFS隐藏各种文件系统的具体细节,为文件操作提供统一的接口

    6、设备驱动

    Linux内核中有大量代码都在设备驱动程序中,它们控制特定的硬件设备

    7、CPU体系结构相关代码

    存放支持各个CPU的代码

    三、内核目录结构



    /: 根目录,一般根目录下只存放目录,不要存放文件,/etc、/bin、/dev、/lib、/sbin应该和根目录放置在一个分区中
    /bin:/usr/bin: 可执行二进制文件的目录,如常用的命令ls、tar、mv、cat等。
    /boot: 放置linux系统启动时用到的一些文件。/boot/vmlinuz为linux的内核文件,以及/boot/gurb。建议单独分区,分区大小100M即可
    /dev: 存放linux系统下的设备文件,访问该目录下某个文件,相当于访问某个设备,常用的是挂载光驱mount /dev/cdrom /mnt。
    /etc: 系统配置文件存放的目录,不建议在此目录下存放可执行文件,重要的配置文件有/etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d修改配置文件之前记得备份。注:/etc/X11存放与x windows有关的设置。
    /home: 系统默认的用户家目录,新增用户账号时,用户的家目录都存放在此目录下,~表示当前用户的家目录,~test表示用户test的家目录。建议单独分区,并设置较大的磁盘空间,方便用户存放数据
    /lib:/usr/lib:/usr/local/lib: 系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助,比较重要的目录为/lib/modules。
    /lost+fount: 系统异常产生错误时,会将一些遗失的片段放置于此目录下,通常这个目录会自动出现在装置目录下。如加载硬盘于/disk 中,此目录下就会自动产生目录/disk/lost+found
    /mnt:/media: 光盘默认挂载点,通常光盘挂载于/mnt/cdrom下,也不一定,可以选择任意位置进行挂载。
    /opt: 给主机额外安装软件所摆放的目录。如:FC4使用的Fedora 社群开发软件,如果想要自行安装新的KDE 桌面软件,可以将该软件安装在该目录下。以前的 Linux 系统中,习惯放置在 /usr/local 目录下
    /proc: 此目录的数据都在内存中,如系统核心,外部设备,网络状态,由于数据都存放于内存中,所以不占用磁盘空间,比较重要的目录有/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等
    /root: 系统管理员root的家目录,系统第一个启动的分区为/,所以最好将/root和/放置在一个分区下。
    /sbin:/usr/sbin:/usr/local/sbin: 放置系统管理员使用的可执行命令,如fdisk、shutdown、mount等。与/bin不同的是,这几个目录是给系统管理员root使用的命令,一般用户只能"查看"而不能设置和使用。
    /tmp: 一般用户或正在执行的程序临时存放文件的目录,任何人都可以访问,重要数据不可放置在此目录下
    /srv: 服务启动之后需要访问的数据目录,如www服务需要访问的网页数据存放在/srv/www内
    /usr: 应用程序存放目录,/usr/bin 存放应用程序, /usr/share 存放共享数据,/usr/lib 存放不能直接运行的,却是许多程序运行所必需的一些函数库文件。/usr/local:存放软件升级包。/usr/share/doc: 系统说明文件存放目录。/usr/share/man: 程序说明文件存放目录,使用 man ls时会查询/usr/share/man/man1/ls.1.gz的内容建议单独分区,设置较大的磁盘空间
    /var: 放置系统执行过程中经常变化的文件,如随时更改的日志文件
     /var/log,/var/log/message: 所有的登录文件存放目录,/var/spool/mail: 邮件存放的目录, /var/run: 程序或服务启动

    后,其PID存放在该目录下。建议单独分区,设置较大的磁盘空间
       
    ------------------------------------------ 

    /dev: 目录
      dev是设备(device)的英文缩写。/dev这个目录对所有的用户都十分重要。因为在这个目录中包含了所有Linux系统中使用的外部设备。但是这里并不是放的外部设备的驱动程序,这一点和

    windows,dos操作系统不一样。它实际上是一个访问这些外部设备的端口。我们可以非常方便地去访问这些外部设备,和访问一个文件,一个目录没有任何区别。

      Linux沿袭Unix的风格,将所有设备认成是一个文件。

      设备文件分为两种:块设备文件(b)和字符设备文件(c)

      设备文件一般存放在/dev目录下,对常见设备文件作如下说明:

      /dev/hd[a-t]:IDE设备

      /dev/sd[a-z]:SCSI设备

      /dev/fd[0-7]:标准软驱

      /dev/md[0-31]:软raid设备

      /dev/loop[0-7]:本地回环设备

      /dev/ram[0-15]:内存

      /dev/null:无限数据接收设备,相当于黑洞

      /dev/zero:无限零资源

      /dev/tty[0-63]:虚拟终端

      /dev/ttyS[0-3]:串口

      /dev/lp[0-3]:并口

      /dev/console:控制台

      /dev/fb[0-31]:framebuffer

      /dev/cdrom => /dev/hdc

      /dev/modem => /dev/ttyS[0-9]

      /dev/pilot => /dev/ttyS[0-9]

      /dev/random:随机数设备

      /dev/urandom:随机数设备

      (PS:随机数设备,后面我会再写篇博客总结一下)

      /dev目录下的节点是怎么创建的?

      devf或者udev会自动帮你创建得。

      kobject是sysfs文件系统的基础,udev通过监测、检测sysfs来获取新创建的设备的。

    ------------------------------------------ 

    /etc: 目录

      包含很多文件.许多网络配置文件也在/etc 中. 
    /etc/rc   or /etc/rc.d   or /etc/rc*.d  
      启动、或改变运行级时运行的scripts或scripts的目录.
    /etc/passwd  
      用户数据库,其中的域给出了用户名、真实姓名、家目录、加密的口令和用户的其他信息. 
    /etc/fstab  
      启动时mount -a命令(在/etc/rc 或等效的启动文件中)自动mount的文件系统列表. Linux下,也包括用swapon -a启用的swap区的信息.
    /etc/group   
      类似/etc/passwd ,但说明的不是用户而是组. 
    /etc/inittab  
      init 的配置文件. 
    /etc/issue  
      getty 在登录提示符前的输出信息.通常包括系统的一段短说明或欢迎信息.内容由系统管理员确定. 
    /etc/motd  
      Message Of The Day,成功登录后自动输出.内容由系统管理员确定.经常用于通告信息,如计划关机时间的警告. 
    /etc/mtab  
      当前安装的文件系统列表.由scripts初始化,并由mount 命令自动更新.需要一个当前安装的文件系统的列表时使用,例如df 命令. 
    /etc/shadow  
      在安装了影子口令软件的系统上的影子口令文件.影子口令文件将/etc/passwd 文件中的加密口令移动到/etc/shadow 中,而后者只对root可读.这使破译口令更困难. 
    /etc/login.defs  
      login 命令的配置文件. 
    /etc/printcap  
      类似/etc/termcap ,但针对打印机.语法不同. 
    /etc/profile , /etc/csh.login , /etc/csh.cshrc  
      登录或启动时Bourne或C shells执行的文件.这允许系统管理员为所有用户建立全局缺省环境. 
    /etc/securetty  
      确认安全终端,即哪个终端允许root登录.一般只列出虚拟控制台,这样就不可能(至少很困难)通过modem或网络闯入系统并得到超级用户特权. 
    /etc/shells  
      列出可信任的shell.chsh 命令允许用户在本文件指定范围内改变登录shell.提供一台机器FTP服务的服务进程ftpd 检查用户shell是否列在 /etc/shells 文件中,如果不是将不允许该用户登录. 
    /etc/sysconfig 
      网络配置相关目录

    ------------------------------------------ 

     

    /proc: 目录

    档名    文件内容
    /proc/cmdline     加载 kernel 时所下达的相关参数!查阅此文件,可了解系统是如何启动的!
    /proc/cpuinfo     本机的 CPU 的相关资讯,包含时脉、类型与运算功能等
    /proc/devices     这个文件记录了系统各个主要装置的主要装置代号,与 mknod 有关呢!
    /proc/filesystems     目前系统已经加载的文件系统罗!
    /proc/interrupts     目前系统上面的 IRQ 分配状态。
    /proc/ioports     目前系统上面各个装置所配置的 I/O 位址。
    /proc/kcore     这个就是内存的大小啦!好大对吧!但是不要读他啦!
    /proc/loadavg     还记得 top 以及 uptime 吧?没错!上头的三个平均数值就是记录在此!
    /proc/meminfo     使用 free 列出的内存资讯,嘿嘿!在这里也能够查阅到!
    /proc/modules     目前我们的 Linux 已经加载的模块列表,也可以想成是驱动程序啦!
    /proc/mounts     系统已经挂载的数据,就是用 mount 这个命令呼叫出来的数据啦!
    /proc/swaps     到底系统挂加载的内存在哪里?呵呵!使用掉的 partition 就记录在此啦!
    /proc/partitions     使用 fdisk -l 会出现目前所有的 partition 吧?在这个文件当中也有纪录喔!
    /proc/pci     在 PCI 汇流排上面,每个装置的详细情况!可用 lspci 来查阅!
    /proc/uptime     就是用 uptime 的时候,会出现的资讯啦!
    /proc/version     核心的版本,就是用 uname -a 显示的内容啦!
    /proc/bus/*     一些汇流排的装置,还有 U盘 的装置也记录在此喔!

    ------------------------------------------ 

    /usr: 目录
      /usr 文件系统经常很大,因为所有程序安装在这里. /usr 里的所有文件一般来自Linux distribution;本地安装的程序和其他东西在/usr/local 下.这样可能在升级新版系统或新distribution时无须重新安装全部程序.
    /usr/etc            存放设置文件
    /usr/games      存放游戏和教学文件
    /usr/include      存放C开发工具的头文件
    /usr/share         存放结构独立的数据
    /usr/bin  
      几乎所有用户命令.有些命令在/bin 或/usr/local/bin 中.
    /usr/sbin  
      根文件系统不必要的系统管理命令,例如多数服务程序.  
    /usr/share/man , /usr/share/info , /usr/share/doc   
      手册页、GNU信息文档和各种其他文档文件.  
    /usr/include  
      C编程语言的头文件.为了一致性这实际上应该在/usr/lib 下,但传统上支持这个名字.
    /usr/lib  
      程序或子系统的不变的数据文件,包括一些site-wide配置文件.名字lib来源于库(library); 编程的原始库存在/usr/lib 里.  
    /usr/local  
      本地安装的软件和其他文件放在这里.  
    /usr/src             存放程序的源代码


    ------------------------------------------ 

    /var: 目录
      /var 包括系统一般运行时要改变的数据.每个系统是特定的,即不通过网络与其他计算机共享.  
    /var/catman  
      当要求格式化时的man页的cache.man页的源文件一般存在/usr/man/man* 中;有些man页可能有预格式化的版本,存在/usr/man/cat* 中.而其他的man页在第一次看时需要格式化,格式化完的版本存在/var/man 中,这样其他人再看相同的页时就无须等待格式化了. (/var/catman 经常被清除,就象清除临时目录一样.)  
    /var/lib  
      系统正常运行时要改变的文件.  
    /var/local  
      /usr/local 中安装的程序的可变数据(即系统管理员安装的程序).注意,如果必要,即使本地安装的程序也会使用其他/var 目录,例如/var/lock .  
    /var/lock  
      锁定文件.许多程序遵循在/var/lock 中产生一个锁定文件的约定,以支持他们正在使用某个特定的设备或文件.其他程序注意到这个锁定文件,将不试图使用这个设备或文件.  
    /var/log  

      各种程序的Log文件,特别是login  (/var/log/wtmp log所有到系统的登录和注销) 和syslog (/var/log/messages 里存储所有核心和系统程序信息. /var/log 里的文件经常不确定地增长,应该定期清除.  
    /var/run  

      保存到下次引导前有效的关于系统的信息文件.例如, /var/run/utmp 包含当前登录的用户的信息.
    /var/spool  
      mail, news, 打印队列和其他队列工作的目录.每个不同的spool在/var/spool 下有自己的子目录,例如,用户的邮箱在/var/spool/mail 中.  
    /var/tmp  

      比/tmp 允许的大或需要存在较长时间的临时文件. (虽然系统管理员可能不允许/var/tmp 有很旧的文件.) 


    ------------------------------------------ 


     比较重要的目录 

        在 Linux 系统中,有几个目录是特别需要注意的,以下提供几个需要注意的目录,以及预设相关的用途: 
            /etc: 这个目录相当重要,如前所述,你的开机与系统数据文件均在这个目录之下,因此当这个目录被破坏,那你的系统大概也就差不多该死掉了!而在往后的文件中,你会发现我们常常使用这个目录下的 /etc/rc.d/init.d 这个子目录,因为这个 init.d 子目录是开启一些 Linux 系统服务的 scripts (可以想成是批次檔 )的地方。而在 /etc/rc.d/rc.local 这个文件是开机的执行档。 
            /bin, /sbin, /usr/bin, /usr/sbin: 这是系统预设的执行文件的放置目录,例如 root 常常使用的 userconf, netconf, perl, gcc, c++ 等等的数据都放在这几个目录中,所以如果你在提示字符下找不到某个执行档时,可以在这四个目录中查一查!其中, /bin, /usr/bin 是给系统使用者使用的指令,而 /sbin, /usr/sbin 则是给系统管理员使用的指令!   
            /usr/local: 这是系统预设的让你安装你后来升级的套件的目录。例如,当你发现有更新的 Web 套件(如 Apache )可以安装,而你又不想以 rpm 的方式升级你的套件,则你可以将 apache 这个套件安装在 /usr/local 底下。安装在这里有个好处,因为目前大家的系统都是差不多的,所以如果你的系统要让别人接管的话,也比较容易上手呀!也比较容易找的到数据喔!因此,如果你有需要的话,通常我都会将 /usr/local/bin 这个路径加到我的 path 中。 
            /home: 这个是系统将有账号的人口的家目录设置的地方。     
            /var: 这个路径就重要了!不论是登入、各类服务的问题发生时的记录、以及常态性的服务记录等等的记录目录,所以当你的系统有问题时,就需要来这个目录记录的文件数据中察看问题的所在啰!而 mail 的预设放置也是在这里,所以他是很重要的     
            /usr/share/man, /usr/local/man: 这两个目录为放置各类套件说明档的地方,例如你如果执行 man man,则系统会自动去找这两个目录下的所有说明文件


    展开全文
  • 内核源码目录结构

    2014-03-10 21:17:53
    浏览内核代码之前,有必要知道内核源码的整体分布情况,按照惯例,内核代码安装在/usr/src/linux目录下,该目录下的每一个子目录都代表了一个特定的内核功能性子集,下面针对2.6.23版本进行简单描述。 (1)...
    浏览内核代码之前,有必要知道内核源码的整体分布情况,按照惯例,内核代码安装在/usr/src/linux目录下,该目录下的每一个子目录都代表了一个特定的内核功能性子集,下面针对2.6.23版本进行简单描述。

    (1)Documentation。

    这个目录下面没有内核代码,只有很多质量参差不齐的文档,但往往能够给我们提供很多的帮助。

    (2)arch。

    所有与体系结构相关的代码都在这个目录以及include/asm-*/目录中,Linux支持的每种体系结构在arch目录下都有对应的子目录,而在每个体系结构特有的子目录下又至少包含3个子目录。

    kernel:存放支持体系结构特有的诸如信号量处理和SMP之类特征的实现。

    lib:存放体系结构特有的对诸如strlen和memcpy之类的通用函数的实现。

    mm:存放体系结构特有的内存管理程序的实现。

    除了这3个子目录之外,大多数体系结构在必要的情况下还有一个boot子目录,包含了在这种硬件平台上启动内核所使用的部分或全部平台特有代码。

    此外,大部分体系结构所特有的子目录还根据需要包含了供附加特性使用的其他子目录。比如,i386目录包含一个math-emu子目录,其中包括了在缺少数学协处理器(FPU)的CPU上运行模拟FPU的代码。

    (3)drivers。

    这个目录是内核中最庞大的一个目录,显卡、网卡、SCSI适配器、PCI总线、USB总线和其他任何Linux支持的外围设备或总线的驱动程序都可以在这里找到。

    (4)fs。

    虚拟文件系统(VFS,Virtual File System)的代码,和各个不同文件系统的代码都在这个目录中。Linux支持的所有文件系统在fs目录下面都有一个对应的子目录。比如ext2文件系统对应的是fs/ext2目录。

    一个文件系统是存储设备和需要访问存储设备的进程之间的媒介。存储设备可能是本地的物理上可访问的,比如硬盘或CD-ROM驱动器,它们分别使用ext2/ext3和isofs文件系统;也可能是通过网络访问的,使用NFS文件系统。

    还有一些虚拟文件系统,比如proc,它以一个标准文件系统出现,然而,它其中的文件只存在于内存中,并不占用磁盘空间。

    (5)include。

    这个目录包含了内核中大部分的头文件,它们按照下面的子目录进行分组。

    include/asm-*/,这样的子目录有多个,每一个都对应着一个arch的子目录,比如include/asm-alpha、include/asm-arm、include/asm-i386等。每个子目录中的文件都定义了支持给定体系结构所必须的预处理器宏和内联函数,这些内联函数多数都是全部或部分使用汇编语言实现的。

    编译内核时,系统会建立一个从include/asm目录到目标体系结构特有的目录的符号链接。比如对于arm平台,就是include/asm-arm到include/asm的符号链接。因此,体系结构无关部分的内核代码可以使用如下形式包含体系相关部分的头文件。

    #include <asm/some-file>
    include/linux/,与平台无关的头文件都在这个目录下面,它通常会被链接到目录/usr/include/linux(或者它里面的所有文件会被复制到/usr/include/linux目录下面)。因此用户应用程序里和内核代码里的语句:

    #include <linux/some-file>
    包含的头文件的内容是一致的。

    include目录下的其他子目录,在此不做赘述。

    (6)init。

    内核的初始化代码。包括main.c、创建早期用户空间的代码以及其他初始化代码。

    (7)ipc。

    IPC,即进程间通信(interprocess communication)。它包含了共享内存、信号量以及其他形式IPC的代码。

    (8)kernel。

    内核中最核心的部分,包括进程的调度(kernel/sched.c),以及进程的创建和撤销(kernel/fork.c和kernel/exit.c)等,和平台相关的另外一部分核心的代码在arch/*/kernel目录。

    (9)lib。

    库代码,实现了一个标准C库的通用子集,包括字符串和内存操作的函数(strlen、mmcpy和其他类似的函数)以及有关sprintf和atoi的系列函数。与arch/lib下的代码不同,这里的库代码都是使用C编写的,在内核新的移植版本中可以直接使用。

    (10)mm。

    包含了体系结构无关部分的内存管理代码,体系相关的部分位于arch/*/mm目录下。

    (11)net。

    网络相关代码,实现了各种常见的网络协议,如TCP/IP、IPX等。

    (12)scripts。

    该目录下没有内核代码,只包含了用来配置内核的脚本文件。当运行make menuconfig或者make xconfig之类的命令配置内核时,用户就是和位于这个目录下的脚本进行交互的。

    (13)block。

    block层的实现。最初block层的代码一部分位于drivers目录,一部分位于fs目录,从2.6.15开始,block层的核心代码被提取出来放在了顶层的block目录。

    (14)crypto。

    内核本身所用的加密API,实现了常用的加密和散列算法,还有一些压缩和CRC校验算法。

    (15)security。

    这个目录包括了不同的Linux安全模型的代码,比如NSA Security-Enhanced Linux。

    (16)sound。

    声卡驱动以及其他声音相关的代码。

    (17)usr。

    实现了用于打包和压缩的的cpio等。
    展开全文
  • linux内核源代码位于/usr/src/linux/目录下 include/ 子目录包含了建立内核代码时所需的大部分包含文件(例如 #include),这个模块利用其他模块重建内核 ...init/ 子目录包含了内核...drivers/ 目录包含了内核中
  • linux内核结构

    2011-12-19 18:11:11
    Linux内核结构详解  时间:2005-11-25 10:46:36 来源: 作者:  Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。  1.进程调度(SCHED):控制进程对CPU的访问。当...
  • LinuxSCSI模型及iSCSI示例

    千次阅读 2019-04-10 20:31:52
    在Linux内核中SCSI驱动应该是最为复杂的驱动,没有之一。因为对于整个SCSI系统来说,不只包含一种类型的设备,而是一类设备。前面文章我们简单介绍了Linux操作系统内核中SCSI子系统的整体架构,我们这里简单回忆一下...
  • Linux内核结构

    2014-08-20 23:05:32
    Linux内核结构
  • arch 所有与体系结构相关的代码都在这个目录以及include/ asm-×/ 目录,Linux支持的每种体系结构在arch目录下都有对应的子目录,而在每个体系结构特有的子目录下又至少包含3个子目录。 kernel:存放体系结构特有...
  •  每个驱动对象代表一个已加载的内核驱动程序,指向驱动对象结构的指针常常作为DriverEntry,AddDevice, Unload等函数的参数。驱动对象结构式半透明的。其中公开的域包括DeviceObject,DriverExtensio
  • Linux内核源代码结构

    2013-11-29 14:50:14
    源代码所有在目录:/usr/src/linux (大部分linux发行版本)  init 内核初始化代码   kernel 内核核心部分:进程、定时、程序执行、信号、模块。。。   mm 内存处理   arch 平台相关代码   i386...
  • Linux2.6.34源码目录结构 1、 arch 体系结构相关的代码,例如arm, x86等等。 arch/mach- ---- 具体的machine/board相关的代码。...该目录每个子目录都与某种体系结构对应,用于存放系统结构相关代码,向平台无...
  • Linux内核具体体系结构之虚拟文件系统译自:《Concrete Architecture of the Linux Kernel》作者: Waterloo, Ontario N2L 3G1 CS 746G, Winter 1998 刘建文略译(http://blog.csdn.net/keminlau) 3.3 Virtual File...
  • Linux内核目录结构

    2012-09-11 13:01:00
    /include 子目录包含了建立内核代码是所需要的大部分包含文件,这个模块利用其他模块重建.../drivers 子目录包含了内核中所有的设备驱动程序,如块设备和SCSI设备; /fs 子目录包含了所有的文件系统的代码,如:ext...
  • linux内核源码结构

    2012-08-30 15:41:28
    浏览内核代码之前,有必要知道内核源码的整体分布情况,按照惯例,内核代码安装在/usr/src/linux目录下,该目录下的每一个子目录都代表了一个特定的内核功能性子集,下面针对2.6.23版本进行简单描述。  (1)...
  • linux内核结构详解

    千次阅读 2013-01-24 20:49:40
    Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。   1.进程调度(SCHED):控制多个进程对CPU的访问,使得多个进程能在CPU微观串行运行,看起来却像是并行运行。驱动...
  • Linux2.6.35.7 内核源代码文件的目录结构
  • Linux内核源代码位于/usr/src/linux目录下。 /include子目录包含了建立内核代码时所需的大部分包含文件,这个...如:i386,alpha /drivers子目录包含了内核中所有的设备驱动程序,如块设备和SCSI设备。 /fs子目录包含
  • SCSI、ATA与T10的SAS  1981年SCSI产生。后一致与ATA并行竞争发展。例如串行的SATA的出现就导致了串行的SCSI:SAS的出现。SCSI目前的最新标准是T10,而RAID则是一种组织多个磁盘的冗余备份或加速的高层次并行架构,...
  • 源代码所有在目录:/usr/src/linux (大部分linux发行版本)  init 内核初始化代码   kernel 内核核心部分:进程、定时、程序执行、信号、模块。。。   mm 内存处理   arch 平台相关代码   i386 IBM的PC...
  • 纵向系统是指具体的功能模块,如USB功能,一个对USB文件的操作要走完内核中的很多个层次,即文件系统层、缓存层、通用块层、SCSI层、USB层等。Linux一般将这些层次划分为3个大的层次,接口层、功能逻辑层和驱动...
  • Linux内核源代码目录结构详解

    千次阅读 2015-03-02 21:19:42
    3.1 Linux内核源代码目录如下:  /arch:目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此...
  • Linux内核结构详解

    千次阅读 2005-02-05 12:38:00
    Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。 1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,344
精华内容 7,737
关键字:

内核中scsi的结构