2015-04-30 125 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