LinuxIO数据通道分享_第1页
LinuxIO数据通道分享_第2页
LinuxIO数据通道分享_第3页
LinuxIO数据通道分享_第4页
LinuxIO数据通道分享_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1.IO数据通道处理层次2.块IO层——截获IO3.IO调度4.中断和中断处理

5.总结目录IO数据通道处理层次VFSLayerNFSext2ext3NTFSPagecacheGenericBlockLayerI/OSchedulerLayerBlockDeviceDriverLayerBlockDeviceLayer系统调用1、IO数据通道处理层次:块IO子系统块设备:块设备是支持以固定长度的块为单位读/写数据的存储设备的总称。块设备包括支持随机访问(如数码相机存储卡,RAM盘)和寻到的硬件设备(如磁盘、软盘、CDROM、内存区域等),也可以是逻辑设备,如MD设备,Devicemapper。注册块设备:一、

分配,初始化请求队列,绑定请求队列和请求函数;二、分配,初始化gendisk,给gendisk的major,fops,queue等成员赋值,最后添加gendisk.;

三、注册块设备驱动。注销块设备:一、

清除请求队列.二、

删除gendisk和gendisk的引用三、删除对块设备的引用,注销块设备驱动.块IO层——截获IO块设备处理请求函数:请求处理是块设备驱动的核心,实际的工作都是在这个函数执行,是块设备驱动提供给上层的借口,块设备将通过这个函数获得I/O请求。请求函数原型:intmake_request(structrequest_queue*

q,

struct

bio*

bio);或intmake_request(structrequest_queue_t*

q);块IO层——截获IOstructrequest{ structlist_headqueuelist; structrequest_queue*q; unsignedintcmd_flags;//请求的类型 sector_t__sector; //请求开始扇区 unsignedint__data_len; 请求的数据长度 structbio*bio;请求的第一个bio structbio*biotail;请求的最后一个bio……………….};请求的几个重要结构:structrequest_queue{ structlist_head queue_head;//请求队列 request_fn_proc *request_fn;// make_request_fn *make_request_fn;//请求处理函数unsignedlong queue_flags;//请求标志unsignedlong nr_requests;请求队列中最大请求数spinlock_t *queue_lock;自旋锁…………….};块IO层——截获IOstructbio_vec{ structpage *bv_page; unsignedint bv_len; unsignedint bv_offset;};请求的几个重要结构:structbio{sector_t bi_sector; structbio *bi_next; /*requestqueuelink*/ unsignedlong bi_rw; unsignedshort bi_vcnt; /*howmanybio_vec's*/ unsignedshort bi_idx; structbio_vec *bi_io_vec;//请求数据的数据存放位置…………….};块IO层——截获IOrequest_queuerequestbiobiobio_vecbio_vecbio_vecqueue_headBio_vecbiotailBio_vecBv_pageBv_pageBv_pageBioBi_nextq_sectorBi_sectorBi_sector块IO层——截获IO分配,初始化请求队列,绑定请求队列和请求函数的两种方式:

一.无请求队列:适合于完全可以随机访问的设备数码相机存储卡,RAM盘等(现在我们的SSD适合),这种方式不会经过IOScheduleLayer。分配请求队列、绑定请求队列和请求函数:blk_alloc_queue——分配请求队列;Blk_queue_make_request(xxx_request_queue,make_request)——绑定请求队列和请求函数块IO层——截获IO分配请求队列、绑定请求队列和请求函数:blk_init_queue(make_request,queue_lock)——分配请求队列且绑定请求队列和请求函数。二.有请求队列:适合于机械磁盘设备,使用请求队列可以提高系统的性能,会经过IOScheduleLayer。块IO层——截获IOIO调度层

IO调度层:接收上层发出的I/O请求,缓存请求并试图合并相邻的请求,并根据设置好的调度算法,回调驱动层提供的请求处理函数,以处理具体的I/O请求。NOOPCFQDeadlineAnticipatory实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作.之说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求按照IO请求的地址进行排序,而不是按照先来后到的顺序来进行响应.除了CFQ本身具有的IO排序队列外,DEADLINE额外分别为读IO和写IO提供了FIFO队列.ANTICIPATORY的在DEADLINE的基础上,为每个读IO都设置了6ms的等待时间窗口.如果在这6ms内OS收到了相邻位置的读IO请求,就可以立即满足Linux的四种I/O调度算法IO调度层

IO调度的流程:__make_request中断和中断处理硬件(如键盘)中断控制器处理器处理器中断内核do_IRQ()该线上是否有中断处理程序handle_IRQ_event在该线上运行所有的中断处理程序ret_from_intr()产生一个中断否是中断:中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。Linux中通常分为外部中断(又叫硬件中断)和内部中断(又叫异常)。中断和中断处理中断处理:中断处理程序要求快速、高效,而又想中断处理程序处理的工作量多,所以把中断处理分成中断上半部和下半部。上半部:有严格时限的工作,如:对接收中断进行答复或复位;下半部:可以稍后或者说可以延迟一点的工作;中断处理程序:操作系统在响应一个中断的时候,内核会执行一个函数,该函数,这个函数就是中断处理程序。中断和中断处理注册中断处理函数原型:

intrequest_irq(unsignedintirq,irq_handler_thandler, unsignedlongflags,constchar*devname,void*dev_id)释放中断处理函数原型:voidfree_irq(unsignedintirq,void*dev_id)Irq:表示要分配的中断号;handler:中断处理函数;Flags:中断处理程序标志;如IRQ_DISABLED,IRQ_SHARED等;Name:中断相关设备的名字;Dev_id:用于共享中断线:注册、释放中断处理程序:驱动处理程序可以通过request_irq()函数注册一个中断处理程序,并且激活中断线,以便处理中断。中断和中断处理三、工作队列:二、tasklet:中断下半部实现机制:一、软中断:中断和中断处理软中断的实现:软中断是在编译期间静态分配的,它由softirq_action的结构表示:structsoftirq_action{void(*action)(structsoftirq_action*);};软中断处理程序:软中断处理程序action的函数原型如下:Voidsoftirq_handler(structsoftirq_action*)当内核运行一个软中断处理程序时,它会执行这个action函数。

中断和中断处理中断和中断处理执行软中断:一个注册的软中断必须被标记后才会执行,这叫触发软中断,通常,中断处理程序会在返回结束前会触发软中断,使其在稍后被执行。触发软中断的函数是:raise_softirq_irqoff();

raise_softirq();

中断上半部、下半部的例子:SCSI子系统中断上半部:scsi_done——中断处理函数最终会调用的回调函数;blk_complete_request——一个结束请求的函数,会触发软中断;到此中断上半部结束;中断下半部:(软中断机制)blk_done_softirqscsi_softirq_donescsi_finish_commandscsi_io_completionscsi_end_requestblk_end_iobio_endio。中断和中断处理工作队列:工作队列是另一种将工作推后执行的形式,它可以把推后执行的工作交给一个内核线程来执行,也就是用这种机制实现中断下半部的是在进程上下文中执行的,工作队列可以重新调度甚至睡眠。工作队列的实现:工作队列子系统是一个用于创建内核线程的接口,通过它创建的进程负责由内核其他部分排到队列里的任务。它创建内核线程称为工作者线程。工作队列线程可以让你的驱动程序创建一个专门的工作者线程来处理推后执行的工作。同时也提供一个缺省的工作者线程来处理这些操作。表示线程的数据结构:中断和中断处理表示线程的数据结构:structworkqueue_struct{ structcpu_workqueue_struct*cpu_wq; structlist_headlist; constchar*name; intsinglethread; intfreezeable; /*Freezethreadsduringsuspend*/ intrt;#ifdefCONFIG_LOCKDEP structlockdep_maplockdep_map;#endif};表示工作的数据结构:structwork_struct{ atomic_long_tdata; structlist_headentry; work_func_tfunc;};中断和中断处理使用工作队列:一、创建推后执行的工作:1、静态创建:DECLARE_WORK(name,void

(*func)(void*),void*data);2、动态创建:INIT_WORK(structwork_struct*work,oid

(*func)(void*),void*data);二、工作队列处理函数:工作处理函数的原型:voidwork_handler(void*data);不能访问用户空间。中断和中断处理三、对工作进行调度:把给定工作的处理函数提交给缺省的events工作者线程:

schedule_work();

调用此函数work马上会被调度,当所在处理器上的工作队列线程被唤醒时就会被执行;中断和中断处理中断和中断处理

工作队列实际例子:如:擦除命令中断上半部:Mvumi_isr_handler()——中断处理函数;Mvumi_launch_events()——创建将要推后执行的工作,调用schedule_work(),调度work把给定的工作的处理函数提交给缺省的events工作者线程

,最后调用mvumi_complete_internel_cmd——中断处理程序上半部结束,唤醒发送内部管理命令的线程。中断下半部:工作队列机制缺省的events工作者线程,当该线程被唤醒时,会处理执行推后处理的work。下半部机制的选择:首先,如果需要一个可以休眠、可以调度的实体来执行推后完成的工作,选择工作队列;否则用tasklet,还有如果专注性能的提高,可以使用软中断。

下半部

上下文

顺序执行保障

接口复杂度

软中断

中断

没有

复杂tasklet

中断同类型不能同时执行

次之

工作队列

进程没有(进程一样)

最简单实现下半部机制比较中断和中断处理中断和中断处理实际实现:对于普通读写和trim命令中断处理只有上半部:Mvumi_isr_handlermvumi_receive_ob_list_entryg_complete_cmdraid0_end_iohost_cmd_donebio_endio关于在调试trim命令时mkfs.xfs/dev/sdb–f时出现堆栈,但是系统能够正常运行且不影响数据一致性,当时找不到原因,现在怀疑就是trim命令中断处理程序只有上半部,导致中断处理程序不及时高效所致;此猜想的依据:现在在注册成有请求队列的块设备的代码结束请求的函数用blk_end_request_all,曾经出现和调试trim命令时一样的情况,参考内核源码

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论