在 Linux 字符設備驅動開發中,有三個至關重要的數據結構:struct file、struct inode 和 struct file_operations。它們構成了驅動程序與用戶空間交互的基石。本文將結合 GPIO 驅動實例,深入剖析這三大結構的角色與協作機制。
struct file 代表一個已打開的文件實例,由內核在進程調用 open() 時創建。它包含文件指針、打開模式、私有數據指針等關鍵信息,是驅動程序識別具體打開實例的關鍵。
struct inode 存儲文件的物理屬性:inode 號、權限、時間戳、數據塊指針等。對於設備文件,它還包含主/次設備號,幫助內核定位對應驅動。驅動開發中通常不直接操作它,但理解其作用至關重要。
這是驅動程序的「介面契約」,由一組函數指針組成(open、read、write、ioctl、release 等)。驅動開發者需實現這些函數並填充結構體,內核根據用戶空間調用自動分發。
以下代碼展示如何定義並註冊 GPIO 驅動的操作集:
// 打開操作
ssize_t SIMPLE_GPIO_open(struct inode *inode, struct file *file) {
#ifdef OURS_GPIO_DEBUG
printk("SIMPLE_GPIO_open [--kernel--]\n");
#endif
return 0;
}
// 釋放操作
ssize_t SIMPLE_GPIO_release(struct inode *inode, struct file *file) {
#ifdef OURS_GPIO_DEBUG
printk("SIMPLE_GPIO_release [--kernel--]\n");
#endif
return 0;
}
// 定義 file_operations 結構體
struct file_operations gpio_fops = {
.open = SIMPLE_GPIO_open,
.read = SIMPLE_GPIO_read,
.write = SIMPLE_GPIO_write,
.ioctl = SIMPLE_GPIO_ioctl,
.release = SIMPLE_GPIO_release,
};
此處 .open = SIMPLE_GPIO_open 建立了用戶空間 open() 到內核 SIMPLE_GPIO_open 的映射關係。
#define DEVICE_NAME "/dev/gpio"
int main(void) {
int fd = open(DEVICE_NAME, O_RDWR);
if (fd == -1) {
printf("open device %s error\n", DEVICE_NAME);
return -1;
}
// ... 後續操作
}
用戶調用 open("/dev/gpio", O_RDWR) 時,內核將自動填充 struct inode* 和 struct file* 並調用驅動的 SIMPLE_GPIO_open。驅動開發者無需關心參數構造,只需專注業務邏輯實現。
ssize_t (*open)(struct inode*, struct file*)),不可隨意更改掌握這三大數據結構的協作關係,是編寫健壯 Linux 字符設備驅動的基礎。建議結合內核源碼(fs.h、file.h)深入學習其完整定義與字段含義。
Linux 命令行入門掃盲:su/pwd/cd/ls/find/tar/gzip/mkdir/cp/rm/mv/reboot/halt 十二大核心命令詳解
Linux 核心新增驅動程式完整教學:Kconfig、Makefile 與選單配置實戰
Linux 桌面市場份額邊緣化分析:伺服器稱霸、桌面失語、行動端借 Android 東山再起
Linux 系統管理核心命令速查:chkconfig、df、ps、netstat 參數詳解與實戰場景
Verilog wire 與 reg 深度對比:類型語義、綜合映射、埠連接規則與避坑指南
Linux 新增/刪除 FTP 使用者並限制目錄權限 (vsftpd 實作)