freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內容

高級字符驅動操作說明-文庫吧

2025-04-03 04:29 本頁面


【正文】 實現(xiàn)常常是一個 switch 語句, 基于命令號. 但是當命令號沒有匹配一個有效的操作時缺省的選擇應當是什么? 這個問題是有爭議的. 幾個內核函數(shù)返回 ENIVAL(Invalid argument), 它有意義是因為命令參數(shù)確實不是一個有效的. POSIX 標準, 但是, 說如果一個不合適的 ioctl 命令被發(fā)出, 那么 ENOTTY 應當被返回. 這個錯誤碼被 C 庫解釋為設備的不適當?shù)?ioctl, 這常常正是程序員需要聽到的. 然而, 它仍然是相當普遍的來返回 EINVAL, 對于響應一個無效的 ioctl 命令..預定義的命令盡管 ioctl 系統(tǒng)調用最常用來作用于設備, 內核能識別幾個命令. 注意這些命令, 當用到你的設備時, 在你自己的文件操作被調用之前被解碼. 因此, 如果你選擇相同的號給一個你的 ioctl命令, 你不會看到任何的給那個命令的請求, 并且應用程序獲得某些不期望的東西, 因為在 ioctl 號之間的沖突.預定義命令分為 3 類: 可對任何文件發(fā)出的(常規(guī), 設備, FIFO, 或者 socket) 的那些. 只對常規(guī)文件發(fā)出的那些. 對文件系統(tǒng)類型特殊的那些.最后一類的命令由宿主文件系統(tǒng)的實現(xiàn)來執(zhí)行(這是 chattr 命令如何工作的). 設備驅動編寫者只對第一類命令感興趣, 它們的魔數(shù)是 T. 查看其他類的工作留給讀者作為練習。 ext2_ioctl 是最有趣的函數(shù)(并且比預期的要容易理解), 因為它實現(xiàn) appendonly 標志和 immutable 標志.下列 ioctl 命令是預定義給任何文件, 包括設備特殊的文件:FIOCLEX 設置 closeonexec 標志(File IOctl Close on EXec). 設置這個標志使文件描述符被關閉, 當調用進程執(zhí)行一個新程序時.FIONCLEX 清除 closenoexec 標志(File IOctl Not CLose on EXec). 這個命令恢復普通文件行為, 復原上面 FIOCLEX 所做的. FIOASYNC 為這個文件設置或者復位異步通知(如同在本章中異步通知一節(jié)中討論的). 注意直到 Linux 版本的內核不正確地使用這個命令來修改 O_SYNC 標志. 因為兩個動作都可通過 ftl 來完成, 沒有人真正使用 FIOASYNC 命令, 它在這里出現(xiàn)只是為了完整性.FIOQSIZE 這個命令返回一個文件或者目錄的大小。 當用作一個設備文件, 但是, 它返回一個 ENOTTY 錯誤.FIONBIO File IOctl NonBlocking I/O(在阻塞和非阻塞操作一節(jié)中描述). 這個調用修改在 filpf_flags 中的 O_NONBLOCK 標志. 給這個系統(tǒng)調用的第 3 個參數(shù)用作指示是否這個標志被置位或者清除. (我們將在本章看到這個標志的角色). 注意常用的改變這個標志的方法是使用 ftl 系統(tǒng)調用, 使用 F_SETFL 命令.列表中的最后一項介紹了一個新的系統(tǒng)調用, ftl, 它看來象 ioctl. 事實上, ftl 調用非常類似 ioctl, 它也是獲得一個命令參數(shù)和一個額外的(可選地)參數(shù). 它保持和 ioctl 獨立主要是因為歷史原因: 當 Unix 開發(fā)者面對控制 I/O 操作的問題時, 他們決定文件和設備是不同的. 那時, 有 ioctl 實現(xiàn)的唯一設備是 ttys, 它解釋了為什么 ENOTTY 是標準的對不正確 ioctl 命令的回答. 事情已經改變, 但是 ftl 保留為一個獨立的系統(tǒng)調用..使用 ioctl 參數(shù)在看 scull 驅動的 ioctl 代碼之前, 我們需要涉及的另一點是如何使用這個額外的參數(shù). 如果它是一個整數(shù), 就容易: 它可以直接使用. 如果它是一個指針, 但是, 必須小心些.當用一個指針引用用戶空間, 我們必須確保用戶地址是有效的. 試圖存取一個沒驗證過的用戶提供的指針可能導致不正確的行為, 一個內核 oops, 系統(tǒng)崩潰, 或者安全問題. 它是驅動的責任來對每個它使用的用戶空間地址進行正確的檢查, 并且返回一個錯誤如果它是無效的.在第 3 章, 我們看了 copy_from_user 和 copy_to_user 函數(shù), 它們可用來安全地移動數(shù)據(jù)到和從用戶空間. 這些函數(shù)也可用在 ioctl 方法中, 但是 ioctl 調用常常包含小數(shù)據(jù)項, 可通過其他方法更有效地操作. 開始, 地址校驗(不傳送數(shù)據(jù))由函數(shù) access_ok 實現(xiàn), 它定義在 asm/:int access_ok(int type, const void *addr, unsigned long size)。 第一個參數(shù)應當是 VERIFY_READ 或者 VERIFY_WRITE, 依據(jù)這個要進行的動作是否是讀用戶空間內存區(qū)或者寫它. addr 參數(shù)持有一個用戶空間地址, size 是一個字節(jié)量. 例如, 如果 ioctl 需要從用戶空間讀一個整數(shù), size 是 sizeof(int). 如果你需要讀和寫給定地址, 使用 VERIFY_WRITE, 因為它是 VERIRY_READ 的超集.不象大部分的內核函數(shù), access_ok 返回一個布爾值: 1 是成功(存取沒問題)和 0 是失敗(存取有問題). 如果它返回假, 驅動應當返回 EFAULT 給調用者.關于 access_ok有多個有趣的東西要注意. 首先, 它不做校驗內存存取的完整工作。 它只檢查看這個內存引用是在這個進程有合理權限的內存范圍中. 特別地, access_ok 確保這個地址不指向內核空間內存. 第2, 大部分驅動代碼不需要真正調用 access_ok. 后面描述的內存存取函數(shù)為你負責這個. 但是, 我們來演示它的使用, 以便你可見到它如何完成.scull 源碼利用了 ioclt 號中的位段來檢查參數(shù), 在 switch 之前:int err = 0, tmp。int retval = 0。/* * extract the type and number bitfields, and don39。t decode * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() */if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC) return ENOTTY。if (_IOC_NR(cmd) SCULL_IOC_MAXNR) return ENOTTY。/* * the direction is a bitmask, and VERIFY_WRITE catches R/W * transfers. `Type39。 is useroriented, while * access_ok is kerneloriented, so the concept of read and * write is reversed */if (_IOC_DIR(cmd) amp。 _IOC_READ) err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd))。else if (_IOC_DIR(cmd) amp。 _IOC_WRITE) err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd))。if (err) return EFAULT。在調用 access_ok 之后, 驅動可安全地進行真正的傳輸. 加上 copy_from_user 和 copy_to_user_ 函數(shù), 程序員可利用一組為被最多使用的數(shù)據(jù)大小(1, 2, 4, 和 8 字節(jié))而優(yōu)化過的函數(shù). 這些函數(shù)在下面列表中描述, 它們定義在 asm/:put_user(datum, ptr) __put_user(datum, ptr) 這些宏定義寫 datum 到用戶空間。 它們相對快, 并且應當被調用來代替 copy_to_user 無論何時要傳送單個值時. 這些宏已被編寫來允許傳遞任何類型的指針到 put_user, 只要它是一個用戶空間地址. 傳送的數(shù)據(jù)大小依賴 prt 參數(shù)的類型, 并且在編譯時使用 sizeof 和 typeof 等編譯器內建宏確定. 結果是, 如果 prt 是一個 char 指針, 傳送一個字節(jié), 以及對于 2, 4, 和 可能的 8 字節(jié).put_user 檢查來確保這個進程能夠寫入給定的內存地址. 它在成功時返回 0, 并且在錯誤時返回 EFAULT. __put_user 進行更少的檢查(它不調用 access_ok), 但是仍然能夠失敗如果被指向的內存對用戶是不可寫的. 因此, __put_user 應當只用在內存區(qū)已經用 access_ok 檢查過的時候.作為一個通用的規(guī)則, 當你實現(xiàn)一個 read 方法時, 調用 __put_user 來節(jié)省幾個周期, 或者當你拷貝幾個項時, 因此, 在第一次數(shù)據(jù)傳送之前調用 access_ok 一次, 如同上面 ioctl 所示.get_user(local, ptr) __get_user(local, ptr) 這些宏定義用來從用戶空間接收單個數(shù)據(jù). 它們象 put_user 和 __put_user, 但是在相反方向傳遞數(shù)據(jù). 獲取的值存儲于本地變量 local。 返回值指出這個操作是否成功. 再次, __get_user 應當只用在已經使用 access_ok 校驗過的地址.如果做一個嘗試來使用一個列出的函數(shù)來傳送一個不適合特定大小的值, 結果常常是一個來自編譯器的奇怪消息, 例如coversion to nonscalar type requested. 在這些情況中, 必須使用 copy_to_user 或者 copy_from_user..兼容性和受限操作存取一個設備由設備文件上的許可權控制, 并且驅動正常地不涉及到許可權的檢查. 但是, 有些情形, 在保證給任何用戶對設備的讀寫許可的地方, 一些控制操作仍然應當被拒絕. 例如, 不是所有的磁帶驅動器的用戶都應當能夠設置它的缺省塊大小, 并且一個已經被給予對一個磁盤設備讀寫權限的用戶應當仍然可能被拒絕來格式化它. 在這樣的情況下, 驅動必須進行額外的檢查來確保用戶能夠進行被請求的操作.傳統(tǒng)上 unix 系統(tǒng)對超級用戶帳戶限制了特權操作. 這意味著特權是一個全有或全無的東西 超級用戶可能任意做任何事情, 但是所有其他的用戶被高度限制了. Linux 內核提供了一個更加靈活的系統(tǒng), 稱為能力. 一個基于能力的系統(tǒng)丟棄了全有或全無模式, 并且打破特權操作為獨立的子類. 這種方式, 一個特殊的用戶(或者是程序)可被授權來進行一個特定的特權操作而不必泄漏進行其他的, 無關的操作的能力. 內核在許可權管理上排他地使用能力, 并且輸出 2 個系統(tǒng)調用 capget 和 capset, 來允許它們被從用戶空間管理.全部能力可在 linux/ 中找到. 這些是對系統(tǒng)唯一可用的能力。 對于驅動作者或者系統(tǒng)管理員, 不可能不修改內核源碼而來定義新的. 設備驅動編寫者可能感興趣的這些能力的一個子集, 包括下面:CAP_DAC_OVERRIDE 這個能力來推翻在文件和目錄上的存取的限制(數(shù)據(jù)存取控制, 或者 DAC).CAP_NET_ADMIN 進行網絡管理任務的能力, 包括那些能夠影響網絡接口的.CAP_SYS_MODULE 加載或去除內核模塊的能力.CAP_SYS_RAWIO 進行 raw I/O 操作的能力. 例子包括存取設備端口或者直接和 USB 設備通訊.CAP_SYS_ADMIN 一個捕獲全部的能力, 提供對許多系統(tǒng)管理操作的存取.CAP_SYS_TTY_CONFIG 進行 tty 配置任務的能力.在進行一個特權操作之前, 一個設備驅動應當檢查調用進程有合適的能力。 不這樣做可能導致用戶進程進行非法的操作, 對系統(tǒng)的穩(wěn)定和安全有壞的后果. 能力檢查是通過 capable 函數(shù)來進行的(定義在 linux/): int capable(int capability)。 在 scull 例子驅動中, 任何用戶被許可來查詢 quantum 和 quantum 集的大小. 只有特權用戶, 但是, 可改變這些值, 因為不適當?shù)闹悼赡芎軌牡赜绊懴到y(tǒng)性能. 當需要時, ioctl 的 scull 實現(xiàn)檢查用戶的特權級別, 如下: if (! capable (CAP_SYS_ADMIN)) return EPERM。在這個任務缺乏一個更加特定的能力時, CAP_SYS_ADMIN 被選擇來做這個測試..ioctl 命令的實現(xiàn)ioctl 的 scull 實現(xiàn)只傳遞設備的配置參數(shù), 并且象下面這樣容易:switch(cmd){case SCULL_IOCRESET: scull_quantum = SCULL_QUANTUM。 scull_qset = SCULL_QSET。 break。case SCULL_IOCSQUANTUM: /* Set: arg points to the value */ if (! capable (CAP_SYS_ADMIN)) return EPERM。 retval = __get_user(scull_quantum, (int __user *)arg)。 break。case SCULL_IOCTQUANTUM:
點擊復制文檔內容
公司管理相關推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1