久久久久久久性爱潮,国产又粗又猛又爽又黄下载视频,尤物国产在线一区视频,欧美日本国产在线不卡

<sup id="4uqqy"><ol id="4uqqy"></ol></sup>
  • <th id="4uqqy"></th>

      • <strike id="4uqqy"><nobr id="4uqqy"><ins id="4uqqy"></ins></nobr></strike><sup id="4uqqy"></sup><strong id="4uqqy"><u id="4uqqy"></u></strong>
        <sub id="4uqqy"></sub>

          綠色資源網:您身邊最放心的安全下載站! 最新軟件|熱門排行|軟件分類|軟件專題|廠商大全

          綠色資源網

          技術教程
          您的位置:首頁操作系統(tǒng)linux → 關于Linux的簡單字符設備驅動程序

          關于Linux的簡單字符設備驅動程序

          我要評論 2011/09/19 14:31:15 來源:綠色資源網 編輯:downcc.com [ ] 評論:0 點擊:178次

          一、重要知識點


          1. 主次設備號

          dev_t

          dev_t是內核中用來表示設備編號的數(shù)據(jù)類型;

          int MAJOR(dev_t dev)

          int MINOR(dev_t dev)

          這兩個宏抽取主次設備號。

          dev­_t MKDEV(unsigned int major, unsignedint minor)

          這個宏由主/次設備號構造一個dev_t結構。



          2. 分配和釋放設備號

          int register_chardev_region(dev_t first,unsigned int count, char *name)

          靜態(tài)申請設備號。

          Int alloc_chardev_region(dev_t *dev,unsigned int firstminor, unsigned int count, char *name)

          動態(tài)申請設備號,注意第一個參數(shù)是傳地址,而靜態(tài)則是傳值。



          3. 幾種重要的數(shù)據(jù)結構

          struct file

          file結構代表一個打開的文件,它由內核在open時創(chuàng)建,并傳遞給該文件上進行操作的所有函數(shù),直到最后的close函數(shù)。

          file結構private_data是跨系統(tǒng)調用時保存狀態(tài)信息非常有用的資源。

          file結構的f_ops 保存了文件的當前讀寫位置。

          struct inode

          內核用inode代表一個磁盤上的文件,它和file結構不同,后者表示打開的文件描述符。對于單個文件,可能會有許多個表示打開文件的文件描述符file結構,但他們都指單個inode結構。inode的dev_t i_rdev成員包含了真正的設備編號,struct cdev *i_cdev包含了指向struct cdev結構的指針。

          struct file_operations

          file_operations結構保存了字符設備驅動程序的方法。



          4. 字符設備的注冊和注銷

          struct cdev *cdev_alloc(void);

          void cdev_init(struct cdev *dev, structfile_operations *fops);

          int cdev_add(struct cdev *dev, dev_t num,unsigned int count);

          void cdev_del(struct cdev *dev);

          用來管理cdev結構的函數(shù),內核中使用該結構表示字符設備。注意cdev_add函數(shù)的count參數(shù)為次設備的個數(shù),要想擁有多個次設備,就必須將該參數(shù)設為次設備的個數(shù)。



          5. 并發(fā)處理

          信號量和自旋鎖的區(qū)別,使用信號量時當調用進程試圖獲得一個鎖定了的鎖時會導致進程睡眠,而自旋鎖則是一直循法的等待一直到該鎖解鎖了為止。

          1)信號量

          DECLARE_MUTEX(name);

          DECLARE_MUTEX_LOCKED(name);

          聲明和初始化用在互斥模式中的信號量的兩個宏

          void init_MUTEX(struct semaphore *sem)

          void init_MUTEX_LOCKER(struct semaphore*sem);

          這兩個函數(shù)可以在運行時初始化信號量

          void down(struct semaphore *sem);

          int down_interruptible(struct semaphore*sem);

          int down_trylock(struct semahpore *sem);

          void up(struct semaphore *sem);

          鎖定和解鎖信號量。如果必要,down會將調用進程置于不可中斷的休眠狀態(tài);相反,down_interruptible可被信號中斷。down_trylock不會休眠,并且會在信號量不可用時立即返回。鎖定信號量的代碼最后必須使用up解鎖該信號量。

          2)自旋鎖

          spionlock_t lock = SPIN_LOCK_UNLOCKED;

          spin_lock_init(spinlock_t *lock);

          初始化自旋鎖的兩種方式。

          voidspin_lock(spinlock_t *lock);

          鎖定自旋鎖

          voidspin_unlock(spinlock_t *lock);

          解鎖自旋鎖

          二、驅動代碼




          view plaincopy to clipboardprint?#include <linux/module.h>
          #include <linux/types.h>
          #include <linux/fs.h>
          #include <linux/errno.h>
          #include <linux/mm.h>
          #include <linux/sched.h>
          #include <linux/init.h>
          #include <linux/cdev.h>
          #include <asm/io.h>
          #include <asm/system.h>
          #include <asm/uaccess.h>


          #define MEMDEV_MAJOR 251
          #define MEMDEV_NUM 2
          #define MEMDEV_SIZE 1024

          struct mem_dev
          {
          unsignedint size;
          char*data;
          structsemaphore sem;
          };


          static int mem_major = MEMDEV_MAJOR;

          struct cdev mem_cdev;
          struct mem_dev *mem_devp;


          static int mem_open(struct inode *inode,struct file *filp)
          {
          structmem_dev *dev;
          unsignedint num;

          printk("mem_open.\n");

          num= MINOR(inode->i_rdev);//獲得次設備號
          if(num> (MEMDEV_NUM -1)) //檢查次設備號有效性
          return-ENODEV;

          dev= &mem_devp[num];
          filp->private_data= dev; //將設備結構保存為私有數(shù)據(jù)

          return0;
          }

          static int mem_release(struct inode *inode,struct file *filp)
          {
          printk("mem_release.\n");
          return0;
          }

          static ssize_t mem_read(struct file *filp,char __user *buf, size_t size, loff_t *ppos)
          {
          intret = 0;
          structmem_dev *dev;
          unsignedlong p;
          unsignedlong count;

          printk("mem_read.\n");

          dev= filp->private_data;//獲得設備結構
          count= size;
          p= *ppos;

          //檢查偏移量和數(shù)據(jù)大小的有效性
          if(p> MEMDEV_SIZE)
          return0;
          if(count> (MEMDEV_SIZE-p))
          count= MEMDEV_SIZE - p;

          if(down_interruptible(&dev->sem))//鎖定互斥信號量
          return -ERESTARTSYS;

          //讀取數(shù)據(jù)到用戶空間
          if(copy_to_user(buf,dev->data+p, count)){
          ret= -EFAULT;
          printk("copyfrom user failed\n");
          }
          else{
          *ppos+= count;
          ret= count;
          printk("read%d bytes from dev\n", count);
          }

          up(&dev->sem);//解鎖互斥信號量

          returnret;
          }

          static ssize_t mem_write(struct file *filp,const char __user *buf, size_t size, loff_t *ppos)//注意:第二個參數(shù)和read方法不同
          {
          intret = 0;
          structmem_dev *dev;
          unsignedlong p;
          unsignedlong count;

          printk("mem_write.\n");

          dev= filp->private_data;
          count= size;
          p= *ppos;

          if(p> MEMDEV_SIZE)
          return0;
          if(count> (MEMDEV_SIZE-p))
          count= MEMDEV_SIZE - p;

          if(down_interruptible(&dev->sem))//鎖定互斥信號量
          return-ERESTARTSYS;

          if(copy_from_user(dev->data+p,buf, count)){
          ret= -EFAULT;
          printk("copyfrom user failed\n");
          }
          else{
          *ppos+= count;
          ret= count;
          printk("write%d bytes to dev\n", count);
          }

          up(&dev->sem);//解鎖互斥信號量

          returnret;
          }

          static loff_t mem_llseek(struct file *filp,loff_t offset, int whence)
          {
          intnewpos;

          printk("mem_llseek.\n");

          switch(whence)
          {
          case0:
          newpos= offset;
          break;

          case1:
          newpos= filp->f_pos + offset;
          break;

          case2:
          newpos= MEMDEV_SIZE - 1 + offset;
          break;

          default:
          return-EINVAL;
          }

          if((newpos<0)|| (newpos>(MEMDEV_SIZE - 1)))
          return-EINVAL;

          filp->f_pos= newpos;
          returnnewpos;
          }
          static const struct file_operationsmem_fops = {
          .owner= THIS_MODULE,
          .open= mem_open,
          .write= mem_write,
          .read= mem_read,
          .release= mem_release,
          .llseek= mem_llseek,
          };

          static int __init memdev_init(void)
          {
          intresult;
          interr;
          inti;

          //申請設備號
          dev_tdevno = MKDEV(mem_major, 0);

          if(mem_major)
          result= register_chrdev_region(devno, MEMDEV_NUM, "memdev");//注意靜態(tài)申請的dev_t參數(shù)和動態(tài)dev_t參數(shù)的區(qū)別 <

          關鍵詞:Linux,設備驅動

          閱讀本文后您有什么感想? 已有 人給出評價!

          • 1 歡迎喜歡
          • 1 白癡
          • 1 拜托
          • 1 哇
          • 1 加油
          • 1 鄙視