open方法
提供給驅動程序以初始化的能力,open方法應完成以下工作
檢查設備特定的錯誤
如果設備是首次打開,則對其進行初始化工作
如有必要,更新f_op組件
分配並填寫置於filp->private_data裏的數據結構
- int (*open)(struct inode *inode, struct file *filep);
inode: 在其i_cdev字段中包含了我們想要的信息
file: 文件指針
我們指向得到包含某cdev結構體的scull_dev結構體,可以通過以下方法
- int (*open)(struct inode *inode, struct file *filep);
- struct scull_dev
*dev;
- dev = container_of(inode->i_cdev,
struct scull_dev, cdev);
- filp ->private_data = dev;
經過簡化的scuall_open
- int scuall_open(struct inode
*inode, struct file* filp)
- {
- struct scull_dev
*dev;
- dev
= container_of(inode->i_cdev, struct scull_dev, cdev);
- filp->private_data
= dev;
- if
((filp->f_flags
& O_ACCMODE)
== O_WRONLY)
{
- scull_trim(dev);
- }
- return 0;
- }
release方法
任務:
釋放由open分配的,保存在file->private_data中的所有內容
在最後一次關閉操作時關閉設備
- int scull_release(struct inode *inode, struct file* filp);
scull內存使用
- void *kmalloc(size_t size, int flags);
試圖分配size個字節大小的內存,其返回值指向該內存的指針,分配失敗的時候返回NULL
flags參數用來描述內存的分配方法
- void kfree(void *ptr);
釋放kmalloc分配的空間
read和write
- ssize_t read(struct file
*filp, char __user
*buff,
- size_t count, loff_t
*offp);
- /*拷貝數據到應用程序空間*/
- ssize_t write(struct file
*filp, char __user
*buff,
- size_t count, loff_t
*offp);
- /*從應用程序空間拷貝數據*/
filp 是文件指針
count 是請求傳輸數據的長度
buff 是指向用戶空間的緩衝區
offp 指明用戶在文件中進行存取操作的位置(long offset type)
內核代碼不能直接引用buff中的內容:
用戶空間的地址可能是無效的;
內存可能不再ram中,造成oops錯誤
遭到惡意程序打開後門
用戶地址空間和內核地址空間數據的交換
- unsigned long copy_to_user(void __user
*to,
- const void
*from,
- unosigned long count);
- /*將數據拷貝到用戶空間*/
- unsigned long copy_from_user(void
*to,
- const void __user
*from,
- unsigned long count);
- /*從用戶空間將數據考到內核空間*/
read和write發生錯誤的時候將返回一個負值
如果返回一個大於等於0的值則表示成功和操作的數據的字節數
read方法
調用程序對read的返回值的解釋如下
返回值等於count,表示所請求的字節數成功並完全傳輸
返回值小於count,表示部分數據傳輸成功,傳輸的字節數小於請求的字節數
返回值等於0,表示傳輸達到了文件尾部
返回值小於0,表示發生了錯誤,錯誤碼在<linux/errno.h>
-EINTR 系統調用被中斷
-EFAULT 無效地址
或者現在還沒有數據,但以後可能會有,read系統調用會被阻塞
write方法
調用程序對write的返回值的解釋如下
返回值等於count,表示所請求的字節數成功並完全傳輸
返回值小於count,表示部分數據傳輸成功,傳輸的字節數小於請求的字節數
返回值等於0,表示什麼也沒有寫入
返回值小於0,表示發生了錯誤,錯誤碼在<linux/errno.h>
-EINTR 系統調用被中斷
-EFAULT 無效地址
readv和writev
處理向量的函數
- ssize_t
(*readv)
(struct file *filp,
const struct iovec
*lov,
- unsigned long count, loof_t
*ppos);
- /* 將指定數量的數據依次讀入每個緩衝區*/
- ssize_t
(*writev)
(struct file *filp,
const struct iovec
*lov,
- unsigned long count, loof_t *ppos);
/* 把各個緩衝區的內容收集起來, 並將它們在第一次寫入操作中進行輸出 */
- struct iovec
{
- void __user
*iov_base;
- __kernel_size_t iov_len;
- };