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

正文內(nèi)容

高級字符驅(qū)動操作說明-文庫吧

2025-04-03 04:29 本頁面


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