linux塊裝置讀寫的底層實現

來源:互聯網
上載者:User

ll_re_block()函數:核心塊裝置讀寫都是通過該函數申請請求項來完成的。該函數首先建立請求項,並插入到指定塊裝置的請求隊列中,實際的讀寫操作則是用請求項函數request_fn()來完成的--對與硬碟來說是do_hd_request().該函數建立的請求項後,首先會檢查對應的請求項隊列是否為空白,如果為空白則設定該請求項為當前請求項,否則利用電梯演算法將該請求項加入請求項隊列。由於每個do_hd_request()在結束每個請求項處理後,都會通過終端回呼函數(read_intr和write_intr)來再次調用do_hd_request()來處理請求項隊列中的其他請求項。直到請求項隊列為空白為止,當請求項為空白時停止發送請求(通過INIT_REQUEST宏來實現)。

這裡將ll_re_block(),read_intr和write_intr三者的實現與調用關係分析如下:

void do_hd_request(void)
{

//定義硬碟用到的一些參數
 int i,r;
 unsigned int block,dev;
 unsigned int sec,head,cyl;
 unsigned int nsect;

//goto語句定義的宏,用來檢查請求項隊列是否為空白

 INIT_REQUEST;

//初始化硬碟參數,並做相應檢查
 dev = MINOR(CURRENT->dev);
 block = CURRENT->sector;
 if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
  end_request(0);
  goto repeat;
 }
 block += hd[dev].start_sect;
 dev /= 5;
 __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
  "r" (hd_info[dev].sect));
 __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
  "r" (hd_info[dev].head));
 sec++;
 nsect = CURRENT->nr_sectors;

//檢查之前是否設定了一些複位參數
 if (reset) {
  reset = 0;
  recalibrate = 1;
  reset_hd(CURRENT_DEV);
  return;
 }
 if (recalibrate) {
  recalibrate = 0;
  hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
   WIN_RESTORE,&recal_intr);
  return;
 } 

//這裡開始處理請求項,是讀還是寫發送相應命令,並設定相應的回呼函數
 if (CURRENT->cmd == WRITE) {

//如果是讀則發送讀命令,並設定中斷回呼函數為write_intr
  hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
//迴圈檢查硬碟狀態,如果就緒則發送資料,這裡發送出資料以後,do_hd_request()函數就已經推出了,至於資料用沒有發送玩是在回呼函數write_intr中判斷執行的,在write_intr函數中如果將所有資料都發送晚,則會調用end_request(1)和do_hd_request()。其中end_request(1)完成該請求項的善後工作,do_hd_request()用來處理請求項中的下一個請求項,這樣迴圈起來知道隊列為空白為止。

for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
   /* nothing */ ;
  if (!r) {
   bad_rw_intr();
   goto repeat;
  }
  port_write(HD_DATA,CURRENT->buffer,256);
 } else if (CURRENT->cmd == READ) {

//這裡對寫操作進行處理,處理過程類似於寫。
  hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
 } else
  panic("unknown hd-command");
}

 

request_fn()是請求項處理的發起者,但其在發送命令和設定好回呼函數以後就退出了,後續工作都是通過回呼函數進行的。

static void write_intr(void)
{
 if (win_result()) {
  bad_rw_intr();

//檢測操作結果,如果失敗則再次調用do_hd_request()來對當前請求項進行處理
  do_hd_request();
  return;
 }

//這裡表示do_hd_request()發送命令成功,並且硬碟控制器已經準備後發出了中斷,開始傳輸資料(沒有發送晚繼續發)。
 if (--CURRENT->nr_sectors) {
  CURRENT->sector++;
  CURRENT->buffer += 512;
  do_hd = &write_intr;
  port_write(HD_DATA,CURRENT->buffer,256);
  return;
 }

//這裡表示當前請求項的操作完畢,資料轉送完畢,則結束當前請求項處理,調用do_hd_request()開始請求項隊列的下一個請求。
 end_request(1);
 do_hd_request();
}

 

 

static void read_intr(void)
{
 if (win_result()) {
  bad_rw_intr();
  do_hd_request();
  return;
 }
 port_read(HD_DATA,CURRENT->buffer,256);
 CURRENT->errors = 0;
 CURRENT->buffer += 512;
 CURRENT->sector++;
 if (--CURRENT->nr_sectors) {
  do_hd = &read_intr;
  return;
 }
 end_request(1);
 do_hd_request();
}讀的過程類似

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.