一区二区三区在线视频播放_一区在线播放视频_欧美.com_亚洲精品无人区_久久亚洲精品视频_国产精品久久久久久久免费软件_久久av一区二区三区_欧美国产日韩精品免费观看_亚洲一区自拍_91久久国产精品91久久性色_亚洲一区二区三区在线播放_久久久久久久一区_国产精品一区二区久久久_精品成人国产_亚洲欧洲精品一区二区三区波多野1战4_在线观看亚洲精品

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

綠色資源網

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

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

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

一、重要知識點


1. 主次設備號

dev_t

dev_t是內核中用來表示設備編號的數據類型;

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)

靜態申請設備號。

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

動態申請設備號,注意第一個參數是傳地址,而靜態則是傳值。



3. 幾種重要的數據結構

struct file

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

file結構private_data是跨系統調用時保存狀態信息非常有用的資源。

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結構的函數,內核中使用該結構表示字符設備。注意cdev_add函數的count參數為次設備的個數,要想擁有多個次設備,就必須將該參數設為次設備的個數。



5. 并發處理

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

1)信號量

DECLARE_MUTEX(name);

DECLARE_MUTEX_LOCKED(name);

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

void init_MUTEX(struct semaphore *sem)

void init_MUTEX_LOCKER(struct semaphore*sem);

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

void down(struct semaphore *sem);

int down_interruptible(struct semaphore*sem);

int down_trylock(struct semahpore *sem);

void up(struct semaphore *sem);

鎖定和解鎖信號量。如果必要,down會將調用進程置于不可中斷的休眠狀態;相反,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; //將設備結構保存為私有數據

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;

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

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

//讀取數據到用戶空間
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)//注意:第二個參數和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");//注意靜態申請的dev_t參數和動態dev_t參數的區別 <

關鍵詞:Linux,設備驅動

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

  • 1 歡迎喜歡
  • 1 白癡
  • 1 拜托
  • 1 哇
  • 1 加油
  • 1 鄙視
一区二区三区在线视频播放_一区在线播放视频_欧美.com_亚洲精品无人区_久久亚洲精品视频_国产精品久久久久久久免费软件_久久av一区二区三区_欧美国产日韩精品免费观看_亚洲一区自拍_91久久国产精品91久久性色_亚洲一区二区三区在线播放_久久久久久久一区_国产精品一区二区久久久_精品成人国产_亚洲欧洲精品一区二区三区波多野1战4_在线观看亚洲精品
国产精品va在线播放我和闺蜜| 99国产精品视频免费观看| 欧美另类高清视频在线| 国产一区二区三区精品久久久| 亚洲人成网在线播放| 国语自产精品视频在线看一大j8| 久久九九99视频| 国产欧美一区在线| 欧美精品在线免费观看| 亚洲欧美在线一区| 亚洲女性喷水在线观看一区| 亚洲精品一二三区| 国产精品久久久久毛片软件| 国产夜色精品一区二区av| 欧美区在线播放| 欧美在线播放视频| 国产精品日韩欧美| 性色av一区二区三区在线观看| 激情久久久久久久久久久久久久久久| 久久免费视频一区| 亚洲国产岛国毛片在线| 中文欧美日韩| 午夜国产欧美理论在线播放| 狠狠综合久久av一区二区老牛| 亚洲国产成人久久综合| 国产精品久久久久毛片软件| 国产精品99一区二区| 一级日韩一区在线观看| 亚洲网站在线| 国产精品99久久久久久久久久久久| 韩日午夜在线资源一区二区| 国产三级欧美三级| 国产亚洲欧洲997久久综合| 久久久蜜臀国产一区二区| 久久精品免视看| 国产精品视频免费观看www| 国产精品成人va在线观看| 久久天天躁狠狠躁夜夜av| 国产乱子伦一区二区三区国色天香| 可以看av的网站久久看| 久久岛国电影| 国产精品嫩草影院一区二区| 欧美在线综合| 一本高清dvd不卡在线观看| 99国产欧美久久久精品| 亚洲另类自拍| 亚洲图片激情小说| 亚洲视频免费观看| 亚洲电影下载| 亚洲国产精品成人综合| 国产亚洲人成网站在线观看| 欧美一区激情| 亚洲一级黄色av| 国产视频在线观看一区二区三区| 亚洲精品护士| 久久久久国产一区二区三区四区| 性18欧美另类| 国产精品久久777777毛茸茸| 亚洲精品影视| 免费看黄裸体一级大秀欧美| 国产日本欧美一区二区三区在线| 欧美日韩专区在线| 亚洲午夜在线| 国产模特精品视频久久久久| 亚洲第一精品福利| 免费成人高清视频| 99www免费人成精品| 欧美日韩播放| 午夜精品区一区二区三| 国产午夜精品在线观看| 在线观看日产精品| 久久久久国产精品一区二区| 亚洲主播在线观看| 国产精品99久久久久久白浆小说| 欧美—级在线免费片| 久久嫩草精品久久久精品| 国产欧美一区二区白浆黑人| 国产女人水真多18毛片18精品视频| 亚洲自拍偷拍视频| 欧美成人综合网站| 亚洲免费在线看| 一区二区三区免费看| 亚洲欧美日韩精品| 久久久久国产精品www| 欧美一区在线直播| 亚洲精品国久久99热| 日韩视频中文字幕| 美女主播视频一区| 一本一本久久a久久精品牛牛影视| 久久精品av麻豆的观看方式| 久久资源在线| 日韩特黄影片| 亚洲精品免费看| 91久久在线| 亚洲精品亚洲人成人网| 亚洲欧洲在线播放| 欧美一区二区三区精品| 欧美日韩三级| 欧美亚洲一区二区在线观看| 亚洲一级高清| 久久成人综合网| 欧美视频三区在线播放| 欧美一区二区三区精品电影| 亚洲午夜视频在线| 亚洲一区二区三区四区五区黄| 国产一区二区三区在线观看网站| 在线欧美亚洲| 中国日韩欧美久久久久久久久| 欧美在线亚洲一区| 国产欧美日韩免费| 中日韩视频在线观看| 亚洲国产精品久久久久婷婷老年| 久久综合九色综合久99| 国外精品视频| 国产精品久久久久国产精品日日| 亚洲福利视频三区| 一区二区三区四区精品| 久久高清免费观看| 亚欧成人在线| 欧美色123| 性欧美大战久久久久久久免费观看| 亚洲国产婷婷| 亚洲狼人精品一区二区三区| 欧美日韩日本视频| 免费成人高清| 欧美freesex8一10精品| 亚洲高清不卡一区| 狠狠久久亚洲欧美| 欧美三级日韩三级国产三级| 久久精品国产999大香线蕉| 亚洲欧美另类综合偷拍| 国产精品热久久久久夜色精品三区| 国产精品亚洲美女av网站| 国产亚洲欧美一区二区| 美女任你摸久久| 欧美激情一区二区在线| 中文网丁香综合网| 亚洲黄色有码视频| 一区二区三区四区五区视频| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产一区二区日韩| 午夜精品久久久久| 久久一区国产| 伊人夜夜躁av伊人久久| 日韩午夜在线观看视频| 国产无遮挡一区二区三区毛片日本| 亚洲精品之草原avav久久| 亚洲午夜精品久久久久久app| 久久精品30| 国产精品wwwwww| 久久亚洲精选| 欧美精品色综合| 欧美精品一区二区精品网| 99国产麻豆精品| 亚洲精品国产拍免费91在线| 欧美精品一区二区精品网| 日韩一级黄色大片| 99视频一区二区| 亚洲欧洲在线一区| 久热综合在线亚洲精品| 国产亚洲va综合人人澡精品| 久久综合久久美利坚合众国| 午夜国产欧美理论在线播放| 久久久久久亚洲精品中文字幕|