【內核&驅動】字符設備驅動程序【3】

open和release
open方法
提供給驅動程序以初始化的能力,open方法應完成以下工作
    檢查設備特定的錯誤
    如果設備是首次打開,則對其進行初始化工作
    如有必要,更新f_op組件
    分配並填寫置於filp->private_data裏的數據結構


  1. int (*open)(struct inode *inode, struct file *filep);


    inode: 在其i_cdev字段中包含了我們想要的信息
    file: 文件指針

    我們指向得到包含某cdev結構體的scull_dev結構體,可以通過以下方法
   
  1. int (*open)(struct inode *inode, struct file *filep);


  1. struct scull_dev *dev;
  2. dev = container_of(inode->i_cdev, struct scull_dev, cdev);
  3. filp ->private_data = dev;


經過簡化的scuall_open

  1. int scuall_open(struct inode *inode, struct file* filp)
  2. {
  3.     struct scull_dev *dev;

  4.     dev = container_of(inode->i_cdev, struct scull_dev, cdev);
  5.     filp->private_data = dev;

  6.     if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
  7.         scull_trim(dev);
  8.     }
  9.     return 0;
  10. }



release方法
任務:
釋放由open分配的,保存在file->private_data中的所有內容
在最後一次關閉操作時關閉設備

  1. int scull_release(struct inode *inode, struct file* filp);



scull內存使用

  1. void *kmalloc(size_t size, int flags);

試圖分配size個字節大小的內存,其返回值指向該內存的指針,分配失敗的時候返回NULL
flags參數用來描述內存的分配方法

  1. void kfree(void *ptr);

釋放kmalloc分配的空間

read和write

  1. ssize_t read(struct file *filp, char __user *buff,
  2.         size_t count, loff_t *offp);
  3.         /*拷貝數據到應用程序空間*/
  4. ssize_t write(struct file *filp, char __user *buff,
  5.         size_t count, loff_t *offp);
  6.         /*從應用程序空間拷貝數據*/


filp     是文件指針
count    是請求傳輸數據的長度
buff     是指向用戶空間的緩衝區
offp    指明用戶在文件中進行存取操作的位置(long offset type)

內核代碼不能直接引用buff中的內容:
    用戶空間的地址可能是無效的;
    內存可能不再ram中,造成oops錯誤
    遭到惡意程序打開後門

用戶地址空間和內核地址空間數據的交換

  1. unsigned long copy_to_user(void __user *to,
  2.                const void *from,
  3.                unosigned long count);
  4. /*將數據拷貝到用戶空間*/
  5. unsigned long copy_from_user(void *to,
  6.                  const void __user *from,
  7.                  unsigned long count);
  8. /*從用戶空間將數據考到內核空間*/



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
處理向量的函數

  1. ssize_t (*readv) (struct file *filp, const struct iovec *lov,
  2.             unsigned long count, loof_t *ppos);
  3.     /* 將指定數量的數據依次讀入每個緩衝區*/
  4. ssize_t (*writev) (struct file *filp, const struct iovec *lov,
  5.             unsigned long count, loof_t *ppos);


    /* 把各個緩衝區的內容收集起來, 並將它們在第一次寫入操作中進行輸出 */

 
  1. struct iovec {
  2.         void __user *iov_base;
  3.         __kernel_size_t iov_len;
  4.     };

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章