linux驅動程序開發2

驅動程序設備號
1 驅動程序有主設備號,次設備號之分,主設備號是區分設備屬於哪個驅動的標誌,次設備號是驅動程序用來區別多個設備的。
2 設備號的內部表示:
   typedef unsigned long dev_t;其中搞12位爲主設備號,低20位爲次設備號。
   已知dev_t類型的變量,要想獲取主設備號或者次設備號,使用宏:MAJOR(dev_t dev)  MINOR(dev_t dev)
   已知主次設備號,生成dev_t類型變量,使用宏:MKDEV(int major, int minor);
3 分配主次設備號的方法
   一般請求分配設備號的時機應該是在驅動程序的初始化函數中,內核API有:
   int register_chrdev_region(dev_t first, unsigned int count, char *name)
   靜態請求設備號,失敗返回負數,dev_t爲要申請的主次設備號,count爲總共要申請的設備個數,name爲驅動的名稱
   int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)
   動態申請設備號,失敗返回負數,dev保存得到的設備號,firstminor爲第一個要求申請的次設備號,count爲申請的設備個數,name爲驅動名稱
   例子:
   int scull_major=0;
   int scull_minor=0;
   if(scull_major)
   {
      dev=MKDEV(scull_major, scull_minor);
      result=register_chrdev_region(dev, scull_nr_devs,  "scull");
   }
   else
   {
      result=alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");
    }
   if(result<0)
   {
      printk("cannot get major");
      return result;
   }
4 釋放設備號
unregister_chrdev_region(devno, scull_nr_devs);
5 創建設備文件
#mknod /dev/scull0 c 252 0
c爲字符設備文件
6 註冊設備驅動到內核
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner=THIS_MODULE;
dev->cdev.ops=&scull_fops;
err=cdev_add(&dev->cdev, devno, 1);
if(err)
   printk("add scull fail");
其中cdev_init和下面的兩行代碼都是初始化各個cdev的字段,cdev_add是將這個設備加入到操作系統字符設備鏈表中。
7 註銷字符設備
cdev_del(&scull_devices[i].cdev);
cdev_del是將字符設備從字符設備鏈表中移除。
8 實現驅動中的重要功能函數
struct file_operations scull_fops = {
 .owner =    THIS_MODULE,
 .llseek =   scull_llseek,
// .llseek = no_llseek,
 .read =     scull_read,
 .write =    scull_write,
 .compat_ioctl =    scull_ioctl,
 .open =     scull_open,
 .release =  scull_release,
};
int scull_open(struct inode *inode, struct file *filp)
用戶程序調用open的時候系統會調用驅動的open
int scull_release(struct inode *inode, struct file *filp)
用戶調用close的時候一般會調用函數,是當文件表被釋放的時候調用的,如果close的時候文件表沒有被釋放,則不會調用release函數
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
                loff_t *f_pos)
用戶調用read的時候,系統會調用驅動中的read函數,filp爲文件表指針,buf,count爲用戶調用時傳入的,f_pos爲文件表中的f_pos字段
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
                loff_t *f_pos)
loff_t scull_llseek(struct file *filp, loff_t off, int whence)
int scull_ioctl(struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章