99久久99久久精品免观看,国产精品久久久久国产精品,国产黄色录像视频,免费的黄色毛片,国产一区精品普通话对白,色妞妞成人在线观看,最新aⅴ福利在线观看免费

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

綠色資源網(wǎng)

技術(shù)教程
您的位置:首頁操作系統(tǒng)linux → 關(guān)于Linux的簡單字符設(shè)備驅(qū)動(dòng)程序

關(guān)于Linux的簡單字符設(shè)備驅(qū)動(dòng)程序

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

一、重要知識點(diǎn)


1. 主次設(shè)備號

dev_t

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

int MAJOR(dev_t dev)

int MINOR(dev_t dev)

這兩個(gè)宏抽取主次設(shè)備號。

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

這個(gè)宏由主/次設(shè)備號構(gòu)造一個(gè)dev_t結(jié)構(gòu)。



2. 分配和釋放設(shè)備號

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

靜態(tài)申請?jiān)O(shè)備號。

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

動(dòng)態(tài)申請?jiān)O(shè)備號,注意第一個(gè)參數(shù)是傳地址,而靜態(tài)則是傳值。



3. 幾種重要的數(shù)據(jù)結(jié)構(gòu)

struct file

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

file結(jié)構(gòu)private_data是跨系統(tǒng)調(diào)用時(shí)保存狀態(tài)信息非常有用的資源。

file結(jié)構(gòu)的f_ops 保存了文件的當(dāng)前讀寫位置。

struct inode

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

struct file_operations

file_operations結(jié)構(gòu)保存了字符設(shè)備驅(qū)動(dòng)程序的方法。



4. 字符設(shè)備的注冊和注銷

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結(jié)構(gòu)的函數(shù),內(nèi)核中使用該結(jié)構(gòu)表示字符設(shè)備。注意cdev_add函數(shù)的count參數(shù)為次設(shè)備的個(gè)數(shù),要想擁有多個(gè)次設(shè)備,就必須將該參數(shù)設(shè)為次設(shè)備的個(gè)數(shù)。



5. 并發(fā)處理

信號量和自旋鎖的區(qū)別,使用信號量時(shí)當(dāng)調(diào)用進(jìn)程試圖獲得一個(gè)鎖定了的鎖時(shí)會導(dǎo)致進(jìn)程睡眠,而自旋鎖則是一直循法的等待一直到該鎖解鎖了為止。

1)信號量

DECLARE_MUTEX(name);

DECLARE_MUTEX_LOCKED(name);

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

void init_MUTEX(struct semaphore *sem)

void init_MUTEX_LOCKER(struct semaphore*sem);

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

void down(struct semaphore *sem);

int down_interruptible(struct semaphore*sem);

int down_trylock(struct semahpore *sem);

void up(struct semaphore *sem);

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

2)自旋鎖

spionlock_t lock = SPIN_LOCK_UNLOCKED;

spin_lock_init(spinlock_t *lock);

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

voidspin_lock(spinlock_t *lock);

鎖定自旋鎖

voidspin_unlock(spinlock_t *lock);

解鎖自旋鎖

二、驅(qū)動(dòng)代碼




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);//獲得次設(shè)備號
if(num> (MEMDEV_NUM -1)) //檢查次設(shè)備號有效性
return-ENODEV;

dev= &mem_devp[num];
filp->private_data= dev; //將設(shè)備結(jié)構(gòu)保存為私有數(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;//獲得設(shè)備結(jié)構(gòu)
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)//注意:第二個(gè)參數(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;

//申請?jiān)O(shè)備號
dev_tdevno = MKDEV(mem_major, 0);

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

關(guān)鍵詞:Linux,設(shè)備驅(qū)動(dòng)

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

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