詳解應用層open函式如何呼叫到底層驅動中xxx_open函式
在上一篇Linux驅動(三)字元裝置驅動框架中,我們編寫函式操作集合ops,並編寫了應用層程式碼。我們現在來看一看,程式如何從應用到達驅動層的。
linux中一切皆檔案,核心如何來區別每一個檔案,這個叫做inode號,每個檔案有一個特定的inode號
用ls -i檢視檔案inode號,每個檔案會對應一個inode結構體,inode結構體的內容非常多,我們省略了一部分
struct inode {
umode_ti_mode; // 開啟方式
kuid_ti_uid; // 使用者id
kgid_ti_gid; // 組id
unsigned inti_flags; // 許可權標誌位,阻塞,非阻塞... 標誌位資訊
const struct inode_operations*i_op; // inode 操作方法集
struct super_block*i_sb;
struct address_space*i_mapping;
unsigned longi_ino; // inode 號碼
union {
const unsigned int i_nlink;
unsigned int __i_nlink; // 連結數
};
dev_ti_rdev; // 裝置號
struct timespeci_atime; // 訪問時間
struct timespeci_mtime; // 修改時間
struct timespeci_ctime; // 建立時間
// 儲存資訊
unsigned short i_bytes;
unsigned inti_blkbits;
blkcnt_ti_blocks;
const struct file_operations*i_fop;/* 檔案操作方法集合 */
struct list_headi_devices; // 核心迴圈雙鏈表節點
union {
struct pipe_inode_info*i_pipe;
struct block_device*i_bdev;
struct cdev*i_cdev; // 字元裝置物件指標
};
...
};
inode結構體包含很多資訊,如檔案的許可權資訊,檔案的時間資訊等等。在驅動檔案中,我們主要關注標紅的資訊,inode號,裝置號,檔案操作集合。使用mknod建立裝置節點時,會將inode號和裝置號關聯起來。若此時核心中已經註冊了該裝置號的物件,此時會將裝置物件的操作方法集合賦值到此處。
檔案操作集合i_fop指向了def_chr_fops,這個結構中的open函式指向了chrdev_open。chrdev_open完成的主要工作是:首先根據裝置號找到新增在核心中代表字元裝置的cdev。找到對應的cedv物件後,用cedv關聯的操作方法集和賦值給新建的file結構體中的檔案操作集合。並呼叫操作集合中的open函式,完成真正的開啟操作。
一個驅動可能會被多應用開啟,那多次開啟時是生成多個inode號嗎?答案是否定的。inode號是唯一的,那如何表示多次開啟一個驅動檔案呢?
系統中每個開啟的檔案在核心空間都有一個對應的file結構體。
struct file {struct pathf_path; // 路徑名稱
struct inode*f_inode;/*inode 指標*/
const struct file_operations*f_op; // 檔案操作集合
unsigned int f_flags; // 標誌位資訊
fmode_tf_mode; // 操作方式
loff_tf_pos;
struct fown_structf_owner; // 非同步通知 ,需要用到此結構體
void*private_data;
...
};
我們來看看struct file_operations中定義的方法原型,只有在open和release時才會有inode引數,其餘的操作都用file結構體來操作檔案。也就是在open時會將inode和file結構體關聯起來,fil結構體中有inode指標f_inode指向了檔案的inode結構體。
我們來看一下下面這副圖