Em qual encadeamento bloquear os comandos de acionamento do driver para bloquear o dispositivo?

4

No momento, estou lendo o livro "Noções básicas sobre o Kernel do Linux", pois entendi que a ordem de requisição de E / S de bloco é assim; chamada de espaço do usuário = > vfs call = > Chamada do agendador de E / S = > bloquear chamada de driver de dispositivo.

O que eu quero saber é onde o driver de dispositivo de bloqueio emitir comandos para bloquear o dispositivo (disco rígido, etc)? Ele emite comandos em um encadeamento de kernel agendado dedicado ou no encadeamento do processo do usuário no qual a solicitação de E / S do bloco começa?

    
por user147311 13.12.2015 / 22:33

2 respostas

2

Se você não estiver fazendo IOs síncronos, o usuário que está gravando criará apenas transações para que o thread kjournald desencaixe (observe aqui: estou usando um sistema de arquivos ext3 com journal = ordered , rastreios dados usando Linux 3.0-rc7 )

Podemos dar uma olhada no que está acontecendo colocando um ponto de interrupção no método elevator_dispatch_fn do planejador de E / S, por exemplo, deadline_dispatch_requests para o planejador de E / S de prazo final:

Existem duas maneiras de executar a fila de dispositivos:

ou chamado a partir do encadeamento kjournald que será executado (sistema de arquivos ext3, montado com o padrão commit = 5 e, portanto, está programado para ser executado a cada 5s)

#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 ?? ()

Chamado de uma interrupção:

#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 ()

Agora, se você estiver fazendo chamadas síncronas, o método request_fn será executado diretamente na chamada do sistema de gravação, conforme mostrado abaixo:

#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
    
por 14.12.2015 / 15:05
0

Para minha compreensão atual, o processo de espaço do usuário pede ao sistema para retornar I / O. Então, o processo irá esperar por uma interrupção do kernel que o trabalho é feito. O espaço do usuário não deve e não deve se importar como o kernel recupera os dados. Pode ser que o vfs tenha encontrado os dados em algum lugar em seu cache, portanto, o agendador de E / S não é relevante do processo do usuário.

    
por 14.12.2015 / 15:05