Kernel 如何将流程状态更新为阻止状态(任务可中断)?

Kernel 如何将流程状态更新为阻止状态(任务可中断)?,kernel,process,io,block-device,scheduling,Kernel,Process,Io,Block Device,Scheduling,当进程等待I/O时,如何将任务状态更新为task_可中断(即阻塞) 想象一下,在这种情况下,进程向块设备发出I/O请求。根据我之前的描述,流程最终调用elv\u add\u request()将请求添加到I/O队列。因此,我猜在这个elv\u add\u request()调用中,实现类似于: elv_add_request(){ // Register IO_CALLBACK() set_task_state(task, TASK_INTERRUPTABLE); // blocke

当进程等待I/O时,如何将任务状态更新为task_可中断(即阻塞)

想象一下,在这种情况下,进程向块设备发出I/O请求。根据我之前的描述,流程最终调用
elv\u add\u request()
将请求添加到I/O队列。因此,我猜在这个
elv\u add\u request()
调用中,实现类似于:

elv_add_request(){
   // Register IO_CALLBACK()
   set_task_state(task, TASK_INTERRUPTABLE); // blocked
   // flush IO request to disk
   ...
}

IO_CALLBACK(){
    set_task_state(task, TASK_RUNNING); // IO completed, ready to run
}
逻辑是这样的:当I/O请求完成时,它将使用回调函数通知内核进程现在已经就绪。这有意义吗


如果是这样,回调机制是如何实现的?它是CPU/硬件功能吗?

它的行为与您描述的类似,只是在调用
elv\u add\u request()
之前设置了io回调。如果我们从上一个线程获取堆栈:

 [<c027fac4>] error_code+0x74/0x7c
 [<c019ed65>] elv_next_request+0x6b/0x116
 [<e08335db>] scsi_request_fn+0x5e/0x26d [scsi_mod]
 [<c019ee6a>] elv_insert+0x5a/0x134
 [<c019efc1>] __elv_add_request+0x7d/0x82
 [<c019f0ab>] elv_add_request+0x16/0x1d
 [<e0e8d2ed>] pkt_generic_packet+0x107/0x133 [pktcdvd]
 [<e0e8d772>] pkt_get_disc_info+0x42/0x7b [pktcdvd]
 [<e0e8eae3>] pkt_open+0xbf/0xc56 [pktcdvd]
 [<c0168078>] do_open+0x7e/0x246
 [<c01683df>] blkdev_open+0x28/0x51
 [<c014a057>] __dentry_open+0xb5/0x160
 [<c014a183>] nameidata_to_filp+0x27/0x37
 [<c014a1c6>] do_filp_open+0x33/0x3b
 [<c014a211>] do_sys_open+0x43/0xc7
 [<c014a2cd>] sys_open+0x1c/0x1e
 [<c0102b82>] sysenter_past_esp+0x5f/0x85
pkt_generic_packet() 
  blk_execute_rq()
    initialize a 'struct completion' object
    set it as 'struct request->end_io_data'
    blk_execute_rq_nowait(..., blk_end_sync_rq) // that's the io callback
    wait_for_completion_io() //sets task to TASK_UNINTERRUPTIBLE, waits on the 'struct completion' object to be complete

 ...
 the io then happens, a possible scenario would then be:
   blk_end_request()
     blk_end_bidi_request()
       blk_finish_request()
         req->end_io() // This is blk_end_sync_rq
           blk_end_sync_rq()
             complete() // sets task to TASK_NORMAL, signals completion