<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 16.2.?塊設備操作 在前面一節中我們對 block_device_operations 有了簡短的介紹. 現在我們詳細些看看這些操作, 在進入請求處理之前. 為此, 是時間提到 sbull 驅動的另一個特性: 它假裝是一個可移出的設備. 無論何時最后一個用戶關閉設備, 一個 30 秒的定時器被設置; 如果設備在這個時間內不被打開, 設備的內容被清除, 并且內核被告知介質已被改變. 30 秒延遲給了用戶時間, 例如, 來卸載一個 sbull 設備在創建一個文件系統之后. ### 16.2.1.?open 和 release 方法 為實現模擬的介質移出, 當最后一個用戶已關閉設備時 sbull 必須知道. 一個用戶計數被驅動維護. 它是 open 和 close 方法的工作來保持這個計數最新. open 方法看起來非常類似于它的字符驅動對等體; 它用相關的節點和文件結構指針作為參數. 當一個節點引用一個塊設備, i_bdev->bd_disk 包含一個指向關聯 gendisk 結構的指針; 這個指針可用來獲得一個驅動的給設備的內部數據結構. 即, 實際上, sbull open 方法做的第一件事: ~~~ static int sbull_open(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; del_timer_sync(&dev->timer); filp->private_data = dev; spin_lock(&dev->lock) ; if (! dev->users) check_disk_change(inode->i_bdev); dev->users++; spin_unlock(&dev->lock) ; return 0; } ~~~ 一旦 sbull_open 有它的設備結構指針, 它調用 del_timer_sync 來去掉"介質移出"定時器, 如果有一個是活的. 注意我們不加鎖設備自旋鎖, 直到定時器被刪除后; 如果定時器函數在我們可刪除它之前運行, 反過來做會有死鎖. 在設備加鎖下, 我們調用一個內核函數, 稱為 check_disk_change, 來檢查是否已發生一個介質改變. 可能有人爭論說內核應當做這個調用, 但是標準模式是為驅動來在打開時處理它. 最后一步是遞增用戶計數并且返回. 釋放方法的任務是, 相反, 來遞減用戶計數, 以及, 如果被指示了, 啟動介質移出定時器: ~~~ static int sbull_release(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; spin_lock(&dev->lock) ; dev->users--; if (!dev->users) { dev->timer.expires = jiffies + INVALIDATE_DELAY; add_timer(&dev->timer); } spin_unlock(&dev->lock) ; return 0; } ~~~ 在一個處理真實的硬件設備的驅動中, open 和 release 方法應當相應地設置驅動和硬件的狀態. 這個工作可能包括起停磁盤, 加鎖一個可移出設備的門, 分配 DMA 緩沖, 等等. 你可能奇怪誰實際上打開了一個塊設備. 有一些操作可導致一個塊設備從用戶空間直接打開; 這包括分區一個磁盤, 在一個分區上建立一個文件系統, 或者運行一個文件系統檢查器. 當加載一個分區時, 塊驅動也可看到一個 open 調用. 在這個情況下, 沒有用戶空間進程持有一個這個設備的打開的文件描述符; 相反, 打開的文件被內核自身持有. 塊驅動無法知道一個加載操作(它從內核打開設備)和調用如 mkfs 工具(從用戶空間打開它)之間的差別. ### 16.2.2.?支持可移出的介質 block_device_operations 結構包含 2 個方法來支持可移出介質. 如果你為一個非可移出設備編寫一個驅動, 你可安全地忽略這些方法. 它們的實現是相對直接的. media_changed 方法被調用( 從 check_disk_change ) 來看是否介質已經被改變; 它應當返回一個非零值, 如果已經發生. sbull 實現是簡單的; 它查詢一個已被設置的標志, 如果介質移出定時器已超時: ~~~ int sbull_media_changed(struct gendisk *gd) { struct sbull_dev *dev = gd->private_data; return dev->media_change; } ~~~ revalidate 方法在介質改變后被調用; 它的工作是做任何需要的事情來準備驅動對新介質的操作, 如果有. 在調用 revalidate 之后, 內核試圖重新讀分區表并且啟動這個設備. sbull 的實現僅僅復位 media_change 標志并且清零設備內存來模擬一個空盤插入. ~~~ int sbull_revalidate(struct gendisk *gd) { struct sbull_dev *dev = gd->private_data; if (dev->media_change) { dev->media_change = 0; memset (dev->data, 0, dev->size); } return 0; } ~~~ ### 16.2.3.?ioctl 方法 塊設備可提供一個 ioctl 方法來進行設備控制函數. 高層的塊子系統代碼在你的驅動能見到它們之前解釋許多的 ioctl 命令, 但是( 全部內容見 drivers/block/ioctl.c , 在內核源碼中). 實際上, 一個現代的塊驅動根本不必實現許多的 ioctl 命令. sbull ioctl 方法只處理一個命令 -- 一個對設備的結構的請求: ~~~ int sbull_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { long size; struct hd_geometry geo; struct sbull_dev *dev = filp->private_data; switch(cmd) { case HDIO_GETGEO: /* * Get geometry: since we are a virtual device, we have to make * up something plausible. So we claim 16 sectors, four heads, * and calculate the corresponding number of cylinders. We set the * start of data at sector four. */ size = dev->size*(hardsect_size/KERNEL_SECTOR_SIZE); geo.cylinders = (size & ~0x3f) >> 6; geo.heads = 4; geo.sectors = 16; geo.start = 4; if (copy_to_user((void __user *) arg, &geo, sizeof(geo))) return -EFAULT; return 0; } return -ENOTTY; /* unknown command */ } ~~~ 提供排列信息可能看來象一個奇怪的任務, 因為我們的設備是純粹虛擬的并且和磁道和柱面沒任何關系. 甚至大部分真正的塊硬件都已很多年不再有很多更復雜的結構. 內核不關心一個塊設備的排列; 只把它看作一個扇區的線性數組. 但是, 有某些用戶工具仍然想能夠查詢一個磁盤的排列. 特別的, fdisk 工具, 它編輯分區表, 依靠柱面信息并且如果這個信息沒有則不能正確工作. 我們希望 sbull 設備是可分區的, 即便使用老的, 簡單的工具. 因此, 我們已提供了一個 ioctl 方法, 這個方法提供了一個可靠的能夠匹配我們設備容量的排列的假象. 大部分磁盤驅動做類似的事情. 注意, 象通常, 扇區計數被轉換, 如果需要, 來匹配內核使用的 512-字節 的慣例.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看