块驱动程序在哪个线程中向块设备发出命令?

块驱动程序在哪个线程中向块设备发出命令?

我目前正在阅读《Understanding The Linux Kernel》一书,因为我了解到块 I/O 请求顺序是这样的;用户空间调用 => vfs 调用 => I/O 调度程序调用 => 块设备驱动程序调用。

我想知道块设备驱动程序在哪里向块设备(硬盘等)发出命令?它是在专用的调度内核线程中还是在块 I/O 请求开始的用户进程线程中发出命令?

答案1

如果您不执行同步 IO,则执行写入的用户只会为 kjournald 线程创建事务以出列(此处注意:我正在使用外部3文件系统与日记=已订购,使用给出的轨迹Linux 3.0-rc7

我们可以通过在 IO 调度程序 lift_dispatch_fn 方法上放置一个断点来看看发生了什么,例如,deadline_dispatch_requests 为截止时间 IO 调度程序:

设备队列有两种运行方式:

要么从将运行的 kjournald 线程调用(ext3 文件系统,使用默认 commit=5 挂载,因此计划每 5 秒运行一次)

#0  deadline_dispatch_requests (q=, force=0) at block/deadline-iosched.c:246
#1  __elv_next_request (q=<optimized out>) at block/blk.h:86
#2  blk_peek_request (q=q@entry=) at block/blk-core.c:1829
#3  scsi_request_fn (q=) at drivers/scsi/scsi_lib.c:1511
#4  __blk_run_queue (q=) at block/blk-core.c:305
#5  queue_unplugged (q=, depth=1, from_schedule=<optimized out>) at block/blk-core.c:2673
#6  blk_flush_plug_list (plug=plug@entry=, from_schedule=from_schedule@entry=false) at block/blk-core.c:2755
#7  blk_finish_plug (plug=plug@entry=) at block/blk-core.c:2762
#8  journal_commit_transaction (journal=journal@entry=) at fs/jbd/commit.c:412
#9  kjournald (arg=) at fs/jbd/journal.c:152
#10 kthread (_create=) at kernel/kthread.c:96
#11 kernel_thread_helper () at arch/x86/kernel/entry_64.S:1161
#12 ?? ()

从中断中调用:

#0  deadline_dispatch_requests (q=, force=0) at block/deadline-iosched.c:246
#1  __elv_next_request (q=<optimized out>) at block/blk.h:86
#2  blk_peek_request (q=q@entry=) at block/blk-core.c:1829
#3  scsi_request_fn (q=) at drivers/scsi/scsi_lib.c:1511
#4  __blk_run_queue (q=) at block/blk-core.c:305
#5  blk_run_queue (q=q@entry=) at block/blk-core.c:339
#6  scsi_run_queue (q=q@entry=) at drivers/scsi/scsi_lib.c:449
#7  scsi_next_command (cmd=cmd@entry=) at drivers/scsi/scsi_lib.c:502
#8  scsi_end_request (requeue=<optimized out>, bytes=<optimized out>, error=<optimized out>, cmd=) at drivers/scsi/scsi_lib.c:574
#9  scsi_io_completion (cmd=cmd@entry=, good_bytes=<optimized out>) at drivers/scsi/scsi_lib.c:822
#10 scsi_finish_command (cmd=cmd@entry=) at drivers/scsi/scsi.c:847
#11 scsi_softirq_done (rq=<optimized out>) at drivers/scsi/scsi_lib.c:1456
#12 blk_done_softirq (h=<optimized out>) at block/blk-softirq.c:34
#13 __do_softirq () at kernel/softirq.c:238
#14 call_softirq () at arch/x86/kernel/entry_64.S:1210
#15 do_softirq () at arch/x86/kernel/irq_64.c:80
#16 invoke_softirq () at kernel/softirq.c:325
#17 irq_exit () at kernel/softirq.c:340
#18 smp_apic_timer_interrupt (regs=<optimized out>) at arch/x86/kernel/apic/apic.c:862
#19 <signal handler called>
#20 irq_stack_union ()

现在,如果您正在进行同步调用,request_fn 方法将直接在 write 系统调用中运行,如下所示:

#0  deadline_dispatch_requests (q=, force=0) at block/deadline-iosched.c:246
#1  __elv_next_request (q=<optimized out>) at block/blk.h:86
#2  blk_peek_request (q=q@entry=) at block/blk-core.c:1829
#3  scsi_request_fn (q=) at drivers/scsi/scsi_lib.c:1511
#4  __blk_run_queue (q=) at block/blk-core.c:305
#5  queue_unplugged (q=, depth=1, from_schedule=<optimized out>) at block/blk-core.c:2673
#6  blk_flush_plug_list (plug=<optimized out>, from_schedule=from_schedule@entry=false) at block/blk-core.c:2755
#7  blk_flush_plug (tsk=<optimized out>) at include/linux/blkdev.h:880
#8  io_schedule () at kernel/sched.c:5669
#9  sleep_on_page (word=<optimized out>) at mm/filemap.c:182
#10 __wait_on_bit (wq=, q=q@entry=, action=action@entry=<sleep_on_page>, mode=mode@entry=2) at kernel/wait.c:202
#11 wait_on_page_bit (page=page@entry=, bit_nr=bit_nr@entry=13) at mm/filemap.c:571
#12 wait_on_page_writeback (page=) at include/linux/pagemap.h:394
#13 filemap_fdatawait_range (mapping=mapping@entry=, start_byte=start_byte@entry=0, end_byte=end_byte@entry=511) at mm/filemap.c:292
#14 filemap_write_and_wait_range (mapping=, lstart=0, lend=511) at mm/filemap.c:371
#15 filemap_write_and_wait_range (mapping=mapping@entry=, lstart=lstart@entry=0, lend=lend@entry=511) at mm/filemap.c:378
#16 vfs_fsync_range (file=, start=start@entry=0, end=end@entry=511, datasync=0) at fs/sync.c:176
#17 generic_write_sync (file=file@entry=, pos=pos@entry=0, count=count@entry=512) at fs/sync.c:242
#18 generic_file_aio_write (iocb=<optimized out>, iov=, nr_segs=1, pos=<optimized out>) at mm/filemap.c:2614
#19 do_sync_write (filp=, buf=<optimized out>, len=<optimized out>, ppos=) at fs/read_write.c:348
#20 vfs_write (file=file@entry=, buf=buf@entry="", count=<optimized out>, count@entry=512, pos=pos@entry=) at fs/read_write.c:377
#21 sys_write (fd=<optimized out>, buf="", count=512) at fs/read_write.c:429

答案2

据我目前的理解,用户空间进程要求系统返回I/O。然后,该进程将等待来自内核的中断,表明工作已完成。用户空间不关心也不应该关心内核如何检索数据。 vfs 可能在其缓存中的某个位置找到了数据,因此 I/O 调度程序与用户进程无关。

相关内容