精华内容
下载资源
问答
  • 内核包括的子系统

    千次阅读 2017-08-24 14:40:54
    内核包括的子系统:Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。进程调度(SCHED)控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的...

    内核包括的子系统:

    Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。


    进程调度(SCHED)

    控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。

    内存管理(MM)

    允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。

    虚拟文件系统

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

    网络接口(NET)

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

    进程间通讯(IPC)

    支持进程间各种通信机制。

    示意图如下

    image

    展开全文
  • 内核时间子系统开发

    千次阅读 2016-06-06 14:10:22
    内核的时间子系统,我们从功能上来划分,可以分为两种设备,一种叫做clocksource设备,另一种叫clockevent设备。对于一个MP Core SOC来说,一般和时间子系统相关的有两种器件,一种是free running的system counter...

    内核的时间子系统,我们从功能上来划分,可以分为两种设备,一种叫做clocksource设备,另一种叫clockevent设备。对于一个MP Core SOC来说,一般和时间子系统相关的有两种器件,一种是free running的system counter设备,它是向系统提供时间的硬件,属于clocksource设备。另一种就是timer定时器设备,不管是CPU内部私有的还是CPU外部公共的,都属于clockevent设备。

    内核提供两种设备的开发模型,分别提供了clocksource和clockevent公共模块。Clocksource模块向下提供system counter的注册接口,向上提供timekeeping的调用接口,timekeeping向上又提供时间相关的接口给用户层使用,如gettimeofday,等等。

    Clockevent模块向下提供clockevent设备(硬件timer操作)的注册接口,向上提供tick设备的调用接口,hrtimer又会调用tick设备的接口来实现高精度timer解决方案,最终形成接口由用户来使用。

    由上面的介绍可知,对于时间子系统的移植,只要是把最底层的硬件驱动做好,上层的框架代码基本不需要去改动,而对于底层的驱动,主要也就是指system counter驱动和timer定时器驱动。

    1.对于system counter,它的功能有两个,一个是作为clocksource设备提供给timekeeping,另一个是作为scheduler clock使用,sched_clock主要是提供一个获取当前时间点到系统启动之间的纳秒值。所以我们需要做如下关键的步骤:
    setup_sched_clock(…);
    clocksource_register_hz(…);
    这两个步骤只是为了把驱动加入到时间子系统的框架内,除了这个我们当然还要对硬件做初始化操作和一些具体的寄存器设置。

    2.对于硬件timer定时器,它需要注册为一个clockevent设备到内核。当然这一步也仅仅是为了加入时间子系统框架,我们还需要为该定时器设置好中断服务程序,以便定时器中断到来时进行event的通知和处理。我们要使用如下方式来注册一个clockevent设备:
    setup_irq(IRQ_TIMER1, &timer_irq);
    clockevents_config_and_register(&clockevent, rate,0xf, 0xffffffff);
    当然除了上面的这些,我们同样要对具体硬件进行初始化操作和寄存器配置。

    对于时间子系统来说,基本上只要完成了上面两种最底层驱动的实现,就OK了,上层的模块会依赖到他们进行工作,只要底层驱动没问题,上面就可以工作正常,内核开发人员已经帮你做好了整个框架的实现。

    展开全文
  • 内核时间子系统的配置

    千次阅读 2016-06-02 13:26:30
    内核中的时间子系统主要向上层提供两种功能,一个就是时间功能,另一个就是timer定时器功能。时间功能: 时间功能是由内核中的timekeeper模块来负责维护,该模块需要clocksource的支持。内核中的模块划分为如下: ...

    内核中的时间子系统主要向上层提供两种功能,一个就是时间功能,另一个就是timer定时器功能。

    时间功能:
    时间功能是由内核中的timekeeper模块来负责维护,该模块需要clocksource的支持。内核中的模块划分为如下:
    Timekeeper—>clocksource—>hardware

    定时器功能:
    从原理上说,定时器需要有一个定期到来的tick来驱动它运行,每个tick到来时检查一下定时器是否到时,由此来实现定时器的功能。所以定时器的实现可以分为tick device设备和基于tick device的上层timer定时器实现。在内核中的模块划分如下所示:
    timer—>tick device—>clockevent—>hardware

    基于tick device的timer定时器还分为两种类型,一种是低精度timer,一种是高精度timer。
    低精度timer是旧的内核中的实现,一直延续至今,也就是我们熟悉的基于jiffies系统滴答来实现的,旧的内核中只有这种定时器实现。
    高精度timer是为了满足新的需求而诞生的hrtimer。高精度基本可以满足任何情况下的需求了,但是由于历史原因低精度timer不能直接从内核中删除,必须保持兼容性。
    一个CPU内可能有多个local clock硬件,但是只会有一个被设置为该CPU的tick设备,每个CPU有且只有一个tick设备。

    内核配置

    1、通用clock source和clock event的内核配置

    (1)clock event是为tick设备提供支持的模块,它分为了新版和旧版两种架构。新架构采用的是通用模型,旧架构采用的是平台相关的实现。
    相关的配置项为:CONFIG_GENERIC_CLOCKEVENTS和CONFIG_GENERIC_CLOCKEVENTS_BUILD。
    如果配置了这两个选项,就会使用新的时间子系统的构架,如果不配置,将使用旧的时间子系统架构。 这一项的配置一般是在arch中选择的。比如arch/arm/Kconfig中,而其余的需要根据情况在menuconfig中配置,对应的Kconfig为kernel/kernel/time/Kconfig。

    arch/arm/Kconfig
    config ARCH_OMAP1
        bool "TI OMAP1"
        depends on MMU
        select ARCH_HAS_CPUFREQ
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_OMAP
        select ARCH_REQUIRE_GPIOLIB
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
        select GENERIC_CLOCKEVENTS---选择通用时间框架
        select GENERIC_IRQ_CHIP
        select HAVE_CLK
        select HAVE_IDE
        select IRQ_DOMAIN
        select NEED_MACH_IO_H if PCCARD
        select NEED_MACH_MEMORY_H
        help
          Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx)
    

    如上所示,定义ARCH_OMAP1的时候就已经select GENERIC_CLOCKEVENTS作为时间子系统的框架。

    (2)clocksource是为timekeeper提供支持的模块,目前的内核都是使用新的通用框架。不过为了兼容性考虑,kernel也保留了CONFIG_ARCH_USES_GETTIMEOFFSET这个配置项.

    2、tick device的配置

    如果选择了新的时间子系统的软件架构(配置了CONFIG_GENERIC_CLOCKEVENTS),那么内核会打开Timers subsystem的配置选项,主要是和tick以及高精度timer配置相关。

    tick相关的配置:

    CONFIG_HZ_PERIODIC
    

    无论何时,都启用周期性的tick,即便是在系统idle的时候。

    CONFIG_NO_HZ_IDLE
    

    Idle dynticks system (tickless idle)。在系统idle的时候,停掉tick。使能该选项会自动使能CONFIG_NO_HZ_COMMON选项。

    CONFIG_NO_HZ_FULL
    

    Full dynticks system (tickless)。即便在非idle的状态下,也就是说cpu上还运行在task时,也可能会停掉tick,这个选项和实时应用相关。使能该选项会自动使能CONFIG_NO_HZ_COMMON选项。

    上面的三个选项只能是配置其一,上面描述的是新的内核配置方法。对于旧的内核,只有CONFIG_NO_HZ一个配置项,用来配置idle dynticks system(非idle时有周期性tick,idle时无周期性tick),为了兼容旧的系统,新的内核仍然支持了这个选项。

    除此之外还有一个用来配置tick模式的选项:

    CONFIG_TICK_ONESHOT
    

    如果配置了这个选项,就决定了系统中所有的tick设备都是oneshot mode,否则就是periodic mode。
    当配置了CONFIG_NO_HZ_COMMON或者CONFIG_HIGH_RES_TIMERS的时候,这个选项就会一起被配置上,也就是说采用了dynticks或者hrtimer的系统中,它的tick设备模式必须是oneshot类型的。

    3、timer模块的配置

    CONFIG_HIGH_RES_TIMERS
    

    和高精度timer相关的配置只有一个的配置项。如果配置了高精度hrtimer,那么就会自动配置上CONFIG_TICK_ONESHOT,表示系统只支持one-shot类型的tick device。

    4、 time配置示例

    选择一个时间子系统的构架:
    (1)新的通用时间子系统软件框架(配置了CONFIG_GENERIC_CLOCKEVENTS)
    (2)传统时间子系统软件框架(不配置CONFIG_GENERIC_CLOCKEVENTS,配置CONFIG_ARCH_USES_GETTIMEOFFSET)
    除非维护一个旧的系统,否则建议用新的通用时间子系统框架了,这时候可能的配置包括如下几种情况:
    (1)使用低精度timer和不停的tick(HZ_PERIODIC)
    这种是旧的处理方式
    (2)使用低精度timer和dynamic tick(CONFIG_NO_HZ_IDLE)
    (3)使用高精度timer和不停的tick(HZ_PERIODIC)
    (4)使用高精度timer和dynamic tick(CONFIG_NO_HZ_IDLE)
    这种是时下较流行的配置
    注:上面描述的dynamic tick指的是Idle dynticks system。我们不考虑Full dynticks system的情况。
    采用了dynticks或者hrtimer的系统中,它的tick设备模式必须是oneshot类型的,也就是说上面4种情况,只有第1种情况下的tick 是周期模式的,其他三种都是oneshot mode。

    展开全文
  • Linux 内核 SCSI IO 子系统分析

    千次阅读 2015-07-30 21:57:54
    Linux 内核 SCSI IO 子系统分析 研究 LINUX 内核中 SCSI 子系统处理 IO 的过程 本文基于 LINUX2.6.18 内核,从 SCSI 设备访问请求的提交,SCSI 命令的处理、错误恢复几个方面浅析了 LINUX 内核中 SCSI...

    Linux 内核 SCSI IO 子系统分析

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

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

    方 敏 (fminsh@cn.ibm.com), 软件工程师, IBM

    2009 年 9 月 30 日

    • +内容

    概述

    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 子系统和块设备驱动能有所帮助。

    参考资料

    展开全文
  • i2c子系统内核中I2C子系统的结构

    千次阅读 2012-04-07 11:59:36
    本文开始,分析内核的i2c子系统。 说明:1.分析的内核版本为2.6.37.1  2.开发板为TQ2440,板载ARM9(S3C2440)  3.I2C设备为AT24C02  4.分析顺序就是内核I2C子系统的注册顺序(即本系列文章发表的先后顺序)。 ...
  • Linux内核由哪几个子系统组成

    千次阅读 2018-05-24 09:32:12
    *Linux内核由哪几个子系统组成?** Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序...
  • 内核的网络子系统定义了rtnetlink,用做和用户空间的交互,rtnetlink为AF_NETLINK协议的一个类别NETLINK_ROUTE,其它类别包括NETLINK_XFRM、NETLINK_GENERIC。renetlink主要注册了LINK、ROUTE、ADDRESS、NEI...
  • 一种是关键的,必须完成的而且必须以特定的顺序来完成的初始化,这部分的代码往往是直接便如内核的而且是直接调用的另一种是非关键的的子系统(或者说模块、功能)的初始化,这部分根据配置可以不加载,可以以built-...
  • 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处... Linux内核主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统(VFS)、网络接口(NET)和进程间通信(IPC)5个子系统组成,如图1所示。
  • 处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送...
  • Linux内核的5个子系统

    千次阅读 2014-03-13 21:17:44
    首先一张熟悉的图来说明GNU/linux的基本体系结构:  体系的上部分是用户(或应用程序)空间,这是用户应用程序执行的地方。...系统调用接口之下是内核代码,可以更精确地定义为独立于体系结构的内核
  • misc子系统在Linux中是一个非常简单的子系统,但是其清晰的框架结构非常适合用来研究设备识别模型。本文从misc子系统的使用出发,通过了解其机制来总结一套的设备识别的驱动框架,即使用使用同一个驱动,向上提供多...
  • Linux 内核系统架构

    千次阅读 多人点赞 2019-09-17 02:55:13
    描述Linux内核的文章已经有上亿字了但是对于初学者,还是应该多学习多看,毕竟上亿字不能一下就明白的。即使看了所有的Linux 内核文章,估计也还不是很明白,这时候,还...
  • 更高一层次的子系统和各项服务。  (5)系统登陆过程  [18] 系统首先启动Winlogon.exe。  [19] 启动Local Security Authority(Lsass.exe)  [20] 屏幕显示出登陆对话框。  [21] 系统执行Service...
  • linux 网络子系统

    千次阅读 2014-01-02 15:27:13
    网络子系统概述 Linux 内核中,与网络相关的代码是一个相对独立的子系统,称为网络子系统。  网络子系统是一个层次化的结构,可分为以下几个层次:  1、 Socket 层 Linux 在发展过程中,采用 BSD socket APIs 作为...
  • linux时间子系统 - 周期性任务

    千次阅读 2016-12-25 17:33:07
    内核中有大量的需求需要时间的帮助,比如:定时、进程调度、获得时间等等,在内核中时间子系统就是来实现这部分功能的,根据不同的工作模式(periodic和oneshot)会有不同的工作函数来实现周期性任务,具体分为低精度...
  • Linux内存管理子系统由七大部分 组成。。如下图: a>系统调用接口(SCI)、 b>进程管理(PM)、 c>内存管理(MM) 、 d>关于处理器代码(arch) 、 e>虚拟文件系统(VFS)、 f>网络协议...
  • Linux内核启动及文件系统加载过程

    千次阅读 2015-08-26 10:45:41
    Linux内核启动及文件系统加载过程 当u-boot开始执行bootcmd命令,就进入Linux内核启动阶段,与u-boot类似,普通Linux内核的启动过程也可以分为两个阶段,但针对压缩了的内核如uImage就要包括内核自解压过程了。...
  • Linux 查看内核 系统 软件版本命令

    万次阅读 2010-09-10 19:35:00
    内核版本:uname -a || cat /proc/version系统版本:lsb_release -a || cat /etc/redhat-release软件版本:rpm -aq |grep ** || ------------------------------- 查看内核版本: uname -a more /etc/*...
  • 初探linux子系统集之led子系统(一)

    千次阅读 2014-07-08 19:54:55
    就像学编程第一个范例helloworld一样,学嵌入式,单片机、...不过,既然linux系统自己本来就带有led子系统,那么就可以好好利用之。好处不用多说了,主要对于应用层来说,不同平台都用linux的led子系统,那么应用程序不
  • 我对Linux 最近的理解,Linux内核是一个支撑软件,是操作系统的核心,负责管理所有的硬件资源,cpu,内存,文件,我先说一下我理解的进程和线程,进程就是一个程序(软件)的动态过程,软件本身是静态,当启动软件时操作系统就...
  • Linux内核系统由哪些部分组成的

    千次阅读 2020-12-30 15:34:15
    Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。 Linux内核源代码的目录结构 Linux内核源代码包含如下目录。 arch:包含和硬件体系结构相关的代码,每种平台占一个...
  • 操作系统内核Hack:(二)底层编程基础在《操作系统内核Hack:(一)实验环境搭建》中,我们看到了一个迷你操作系统引导程序。尽管只有不到二十行,然而要完全看懂还是需要不少底层软硬件知识的。本文的目的就是跟大家...
  • Linux内核(四)系统调用

    千次阅读 2015-06-21 16:57:43
    系统调用就是内核实现的一系列函数,这些函数提供了一套固定的接口,通过这套接口,用户程序可以访问系统硬件和操作系统的资源,即内核提供的服务。 为什么提供系统调用? 用户空间只能通过系统调用来访问内核...
  • Linux内核系统调用

    千次阅读 2018-09-02 00:28:02
    关于系统调用,我们必须清楚linux内存分为用户空间和内核空间,当我们进行程序应用时用的是用户空间,当我们要打开文件和设备的时候就会使用系统调用来访问内核空间,这时候相当中断一样,我们进入内核空间,当 处理...
  • mmc子系统是Linux设备驱动中一个不可缺少的部分,但科技进步,时代发展,现在mmc已经不是从前的mmc(Multimedia Card),现在mmc子系统已经衍生到SD,SDIO相关的技术了,也就是说mmc子系统已经能够管理控制SD和SDIO...
  • Linux内核启动及根文件系统加载过程

    千次阅读 2016-08-11 17:00:41
    Linux内核启动及文件系统加载过程当u-boot开始执行bootcmd命令,就进入Linux内核启动阶段,与u-boot类似,普通Linux内核的启动过程也可以分为两个阶段,但针对压缩了的内核如uImage就要包括内核自解压过程了。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 87,695
精华内容 35,078
关键字:

内核分为等子系统