開啟字元裝置檔案,還是通過 sys_open() 系統呼叫。在經過一連串的呼叫後,nameidata_to_filp, 核心會走到 __dentry_open() 函式。在這個函式中,執行了以下**片段:
f->f_path.dentry = dentry;
f->f_path.mnt = mnt;
f->f_pos = 0;
f->f_op = fops_get(inode->i_fop);
file_move(f, &inode->i_sb->s_files);
error = security_dentry_open(f, cred);
if (error)
goto cleanup_all;
if (!open && f->f_op)
open = f->f_op->open;
if (open)
ima_counts_get(f);
其中重要的三行:
f->f_op = fops_get(inode->i_fop);
open = f->f_op->open;
error = open(inode, f);
其中,f 是 struct file 型的指標,open 是乙個函式指標。所以這三行**主要做了兩件事:
1. 給 struct file 型變數的 f_op 字段賦值;
2. 呼叫 f_op->open() 函式。這裡需要說明的是,f_op 欄位的值是從 inode->i_fop 中得來的,那 inode->i_fop 的值又是怎麼來的呢?對於乙個裝置檔案來說,它的 inode->i_fop 的值是在 mknod() 時由核心根據裝置檔案的型別預設指定的。對應字元裝置檔案,i_fop 就指向 def_chr_fops 這個 struct file_operations 型變數。
def_chr_fops 定義在 fs/char_dev.c 檔案中:
const struct file_operations def_chr_fops = ;
哈,這個 file_operations 真偷懶,就定義了乙個 open 方法。
下面看一下 chrdev_open() 函式的實現,它是所有字元裝置檔案的最初通用的 open 方法。
static int chrdev_open(struct inode *inode, struct file *filp)
else if (!cdev_get(p))
ret = -enxio;
} else if (!cdev_get(p))
ret = -enxio;
spin_unlock(&cdev_lock);
cdev_put(new);
if (ret)
return ret;
ret = -enxio;
filp->f_op = fops_get(p->ops);
if (!filp->f_op)
goto out_cdev_put;
if (filp->f_op->open)
return 0;
out_cdev_put:
cdev_put(p);
return ret;
}簡單地說,這個函式從字元裝置檔案的 inode 節點中取出 cdev 結構的指標(如果 inode 是第一次開啟的話,則通過 kobj_lookup() 根據裝置號從 cdev_map 中找出 cdev,並儲存在 inode->i_cdev 中)。然後用 cdev->ops 替換 file->f_op 從而使用字元裝置驅動自己提供的 file_operations。最後,呼叫字元裝置驅動提供的 open 方法。
字元裝置檔案的開啟
開啟字元裝置檔案,還是通過 sys open 系統呼叫。在經過一連串的呼叫後,核心會走到 dentry open 函式。在這個函式中,執行了以下 片段 f f op fops get inode i fop open f f op open error open inode,f 其中,f 是 str...
字元裝置驅動 裝置號 裝置檔案
主裝置號用來標識與裝置檔案相連的驅動程式.用來反映裝置型別.次裝置號被驅動程式用來辨別操作的是哪乙個裝置.用來區分同型別的裝置.通過的是主裝置號.字元裝置檔案 本身沒有太多的內容,通過 字元裝置檔案 能找到 字元裝置驅動程式 字元裝置檔案 能將 應用程式 的需求傳遞給 字元裝置驅動程式.核心中如何描...
Linux字元裝置檔案
申請字元裝置 第一種方法 檢視系統中哪個裝置號屬於空閒 我們可以檢視字元裝置,塊裝置 int register chrdev region dev t from,unsigned count,const char name from 待申請的裝置號 count 待申請的裝置號數目 次裝置號 name...