## 11.3.?接口特定的類型
內核中一些通常使用的數據類型有它們自己的 typedef 語句, 因此阻止了任何移植性問題. 例如, 一個進程標識符 ( pid ) 常常是 pid_t 而不是 int. 使用 pid_t 屏蔽了任何在實際數據類型上的不同. 我們使用接口特定的表達式來指一個類型, 由一個庫定義的, 以便于提供一個接口給一個特定的數據結構.
注意, 在近期, 已經相對少定義新的接口特定類型. 使用 typedef 語句已經有許多內核開發者不喜歡, 它們寧愿看到代碼中直接使用的真實類型信息, 不是藏在一個用戶定義的類型后面. 很多老的接口特定的類型在內核中保留, 但是, 并且它們不會很快消失.
甚至當沒有定義接口特定的類型, 以和內核其他部分保持一致的方式使用正確的數據類型是一直重要的. 一個嘀噠計數, 例如, 一直是 unsigned long, 獨立于它實際的大小, 因此 unsigned long 類型應當在使用 jiffy 時一直使用. 本節我們集中于 _t 類型的使用.
很多 _t 類型在 <linux/types.h> 中定義, 但是列出來是很少有用. 當你需要一個特定類型, 你會在你需要調用的函數的原型中發現它, 或者在你使用的數據結構中.
無論何時你的驅動使用需要這樣"定制"類型的函數并且你不遵照慣例, 編譯器發出一個警告; 如果你使用 -Wall 編譯器標志并且小心去除所有的警告, 你能有信心你的代碼是可移植的.
_t 數據項的主要問題是當你需要打印它們時, 常常不容易選擇正確的 printk 或 printf 格式, 你在一個體系上出現的警告會在另一個上重新出現. 例如, 你如何打印一個 size_t, 它在一些平臺上是 unsigned long 而在其他某個上面是 unsigned int?
無論何時你需要打印某個接口特定的數據, 最好的方法是轉換它的值為最大的可能類型(常常是 long 或者 unsigned long ) 并且接著打印它通過對應的格式. 這種調整不會產生錯誤或者警告, 因為格式匹配類型, 并且你不會丟失數據位, 因為這個轉換或者是一個空操作或者是數據項向更大數據類型的擴展.
實際上, 我們在談論的數據項不會常常要打印的, 因此這個問題只適用于調試信息. 常常, 代碼只需要存儲和比較接口特定的類型, 加上傳遞它們作為給庫或者內核函數的參數.
盡管 _t 類型是大部分情況的正確解決方法, 有時正確的類型不存取. 這發生在某些還未被清理的老接口.
我們在內核頭文件中發現的一個模糊之處是用在 I/O 函數的數據類型, 它松散地定義( 看第 9 章"平臺相關性" 一節 ). 松散的類型在那里主要是因為歷史原因, 但是在寫代碼時它可能產生問題. 例如, 交換給函數如 outb 的參數可能會有麻煩; 如果有一個 port_t 類型, 編譯器會發現這個類型.
- Linux設備驅動第三版
- 第 1 章 設備驅動簡介
- 1.1. 驅動程序的角色
- 1.2. 劃分內核
- 1.3. 設備和模塊的分類
- 1.4. 安全問題
- 1.5. 版本編號
- 1.6. 版權條款
- 1.7. 加入內核開發社團
- 1.8. 本書的內容
- 第 2 章 建立和運行模塊
- 2.1. 設置你的測試系統
- 2.2. Hello World 模塊
- 2.3. 內核模塊相比于應用程序
- 2.4. 編譯和加載
- 2.5. 內核符號表
- 2.6. 預備知識
- 2.7. 初始化和關停
- 2.8. 模塊參數
- 2.9. 在用戶空間做
- 2.10. 快速參考
- 第 3 章 字符驅動
- 3.1. scull 的設計
- 3.2. 主次編號
- 3.3. 一些重要數據結構
- 3.4. 字符設備注冊
- 3.5. open 和 release
- 3.6. scull 的內存使用
- 3.7. 讀和寫
- 3.8. 使用新設備
- 3.9. 快速參考
- 第 4 章 調試技術
- 4.1. 內核中的調試支持
- 4.2. 用打印調試
- 4.3. 用查詢來調試
- 4.4. 使用觀察來調試
- 4.5. 調試系統故障
- 4.6. 調試器和相關工具
- 第 5 章 并發和競爭情況
- 5.1. scull 中的缺陷
- 5.2. 并發和它的管理
- 5.3. 旗標和互斥體
- 5.4. Completions 機制
- 5.5. 自旋鎖
- 5.6. 鎖陷阱
- 5.7. 加鎖的各種選擇
- 5.8. 快速參考
- 第 6 章 高級字符驅動操作
- 6.1. ioctl 接口
- 6.2. 阻塞 I/O
- 6.3. poll 和 select
- 6.4. 異步通知
- 6.5. 移位一個設備
- 6.6. 在一個設備文件上的存取控制
- 6.7. 快速參考
- 第 7 章 時間, 延時, 和延后工作
- 7.1. 測量時間流失
- 7.2. 獲知當前時間
- 7.3. 延后執行
- 7.4. 內核定時器
- 7.5. Tasklets 機制
- 7.6. 工作隊列
- 7.7. 快速參考
- 第 8 章 分配內存
- 8.1. kmalloc 的真實故事
- 8.2. 后備緩存
- 8.3. get_free_page 和其友
- 8.4. 每-CPU 的變量
- 8.5. 獲得大量緩沖
- 8.6. 快速參考
- 第 9 章 與硬件通訊
- 9.1. I/O 端口和 I/O 內存
- 9.2. 使用 I/O 端口
- 9.3. 一個 I/O 端口例子
- 9.4. 使用 I/O 內存
- 9.5. 快速參考
- 第 10 章 中斷處理
- 10.1. 準備并口
- 10.2. 安裝一個中斷處理
- 10.3. 前和后半部
- 10.4. 中斷共享
- 10.5. 中斷驅動 I/O
- 10.6. 快速參考
- 第 11 章 內核中的數據類型
- 11.1. 標準 C 類型的使用
- 11.2. 安排一個明確大小給數據項
- 11.3. 接口特定的類型
- 11.4. 其他移植性問題
- 11.5. 鏈表
- 11.6. 快速參考
- 第 12 章 PCI 驅動
- 12.1. PCI 接口
- 12.2. 回顧: ISA
- 12.3. PC/104 和 PC/104+
- 12.4. 其他的 PC 總線
- 12.5. SBus
- 12.6. NuBus 總線
- 12.7. 外部總線
- 12.8. 快速參考
- 第 13 章 USB 驅動
- 13.1. USB 設備基礎知識
- 13.2. USB 和 sysfs
- 13.3. USB 的 Urbs
- 13.4. 編寫一個 USB 驅動
- 13.5. 無 urb 的 USB 傳送
- 13.6. 快速參考
- 第 14 章 Linux 設備模型
- 14.1. Kobjects, Ksets 和 Subsystems
- 14.2. 低級 sysfs 操作
- 14.3. 熱插拔事件產生
- 14.4. 總線, 設備, 和驅動
- 14.5. 類
- 14.6. 集成起來
- 14.7. 熱插拔
- 14.8. 處理固件
- 14.9. 快速參考
- 第 15 章 內存映射和 DMA
- 15.1. Linux 中的內存管理
- 15.2. mmap 設備操作
- 15.3. 進行直接 I/O
- 15.4. 直接內存存取
- 15.5. 快速參考
- 第 16 章 塊驅動
- 16.1. 注冊
- 16.2. 塊設備操作
- 16.3. 請求處理
- 16.4. 一些其他的細節
- 16.5. 快速參考
- 第 17 章 網絡驅動
- 17.1. snull 是如何設計的
- 17.2. 連接到內核
- 17.3. net_device 結構的詳情
- 17.4. 打開與關閉
- 17.5. 報文傳送
- 17.6. 報文接收
- 17.7. 中斷處理
- 17.8. 接收中斷緩解
- 17.9. 連接狀態的改變
- 17.10. Socket 緩存
- 17.11. MAC 地址解析
- 17.12. 定制 ioctl 命令
- 17.13. 統計信息
- 17.14. 多播
- 17.15. 幾個其他細節
- 17.16. 快速參考
- 第 18 章 TTY 驅動
- 18.1. 一個小 TTY 驅動
- 18.2. tty_driver 函數指針
- 18.3. TTY 線路設置
- 18.4. ioctls 函數
- 18.5. TTY 設備的 proc 和 sysfs 處理
- 18.6. tty_driver 結構的細節
- 18.7. tty_operaions 結構的細節
- 18.8. tty_struct 結構的細節
- 18.9. 快速參考