2015-04-30 150 views
1

当进程等待IO时,如何将任务状态更新为TASK_INTERRUPTABLE(即阻塞)?进程状态如何更新为阻塞状态(TASK_INTERRUPTABLE)?

想象一下,这种情况下,进程向块设备发出IO请求。根据我以前的thread,该过程最终调用elv_add_request()将请求添加到IO队列。所以我想在这个elv_add_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 
} 

的逻辑是这样的:当IO请求完成后,它会使用回调函数来通知进程准备内核现在。是否有意义?

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

回答

1

它的行为与您所描述的类似,除了在致电elv_add_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 

的调用栈去(我在看一个4.1-RC1源)是这样的:

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