linux/block/blk-core.c定义 void submit_bio(int rw, struct bio *bio) 该函数为通用块层的接口函数。submit_bio调用generic_make_request(bio);加入到对应的请求队列。 generic_make_request循环针对一个进行的所有bio调用__generic_make_request __generic_make_request 主要完成相关检查 分区的remap 然后调用对应请求队列的q- make_request_fn(q, bio); 请求队列的make_request_fn(q, bio) 通过blk_queue_make_request进行初始化 blk_queue_make_requestvoid blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)floppy_queue blk_init_queue(do_fd_request, amiflop_lock); blk_init_queue-》blk_init_queue_node-》blk_init_allocated_queue_node-》blk_queue_make_request(q, blk_queue_bio); 所有普通的块设备驱动 通过blk_init_queue初始化请求队列的设备。 q- make_request_fn(q, bio); 对应的是blk_queue_bio blk_queue_bio的处理流程 spin_lock_irq(q- queue_lock);  //加锁 由于该锁在中断上下文也是用 因此是关中断的如果请求队列是空的 则直接插入请求。    if (elv_queue_empty(q))         goto get_rq;     init_request_from_bio(req, bio);    spin_lock_irq(q- queue_lock);     if (test_bit(QUEUE_FLAG_SAME_COMP, q- queue_flags) ||          bio_flagged(bio, BIO_CPU_AFFINE))          req- cpu raw_smp_processor_id();              if (queue_should_plug(q) elv_queue_empty(q))         blk_plug_device(q);    /* insert the request into the elevator */     drive_stat_acct(req, 1);     __elv_add_request(q, req, where, 0); out:     if (unplug || !queue_should_plug(q))         __generic_unplug_device(q); out_unlock:     spin_unlock_irq(q- queue_lock); make_request_fn(q, bio);只是把请求加入到请求队列 并没有实际下发到控制器。 实际下发到控制器是由__generic_unplug_device触发。 __generic_unplug_device /*  * remove the plug and let it rip..  */ void __generic_unplug_device(struct request_queue *q) {     if (unlikely(blk_queue_stopped(q)))         return;     if (!blk_remove_plug(q) !blk_queue_nonrot(q))         return;    q- request_fn(q); }调用请求队列的 q- request_fn(q);函数。 这个函数对应的是驱动程序在初始化的时候传入。 floppy_queue blk_init_queue(do_fd_request, floppy_lock); request_fn的一般处理流程是循环下发所有的请求到控制器。 需要注意的是, 请求函数的启动(常常地)与任何用户空间进程之间是完全异步的. 你不能假设内核运行在发起当前请求的进程上下文. 你不知道由这个请求提供的 I/O 缓冲是否在内核或者用户空间. 因此任何类型的明确存取用户空间的操作都是错误的并且将肯定引起麻烦. 如你将见到的, 你的驱动需要知道的关于请求的所有事情, 都包含在通过请求队列传递给你的结构中. 请求处理完成的流程。 __blk_end_request_all         bio bio_alloc(GFP_NOFS, 1);         bio- bi_bdev inode- i_sb- s_bdev;         bio- bi_sector pblock (inode- i_blkbits - 9);         bio- bi_end_io metapage_write_end_io;         bio- bi_private page; bio完成的时候 会回调bi_end_iovoid bio_endio(struct bio *bio, int error) {     if (error)         clear_bit(BIO_UPTODATE, bio- bi_flags);     else if (!test_bit(BIO_UPTODATE, bio- bi_flags))         error -EIO;    if (bio- bi_end_io)         bio- bi_end_io(bio, error); } EXPORT_SYMBOL(bio_endio); jemmy858585 关注 关注 抵扣说明:1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。