国语自产精品视频在线看:您身边最放心的安全下载站! 最新软件|热门排行|软件分类|软件专题|厂商大全

国语自产精品视频在线看

技术教程
您的位置:首页操作系统linux → 关于Linux的简单字符设备驱动程序

关于Linux的简单字符设备驱动程序

我要评论 2011/09/19 14:31:15 来源:国语自产精品视频在线看 编辑:downcc.com [ ] 评论:0 点击:178次

一、重要知【chóng yào zhī】🕚识点


1. 主次设【zhǔ cì shè】备【bèi】🌦号【hào】

dev_t

dev_t是内核【shì nèi hé】中用【yòng】来表示设备【bèi】👰编号【hào】的【de】数据类【shù jù lèi】型;

int MAJOR(dev_t dev)

int MINOR(dev_t dev)

这两个【zhè liǎng gè】🐸宏抽取主次设【zhǔ cì shè】备【bèi】🌦号【hào】。

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

这个【gè】宏🌕由主/次设备【cì shè bèi】🌦号【hào】构造一个【yī gè】🐸dev_t结构【jié gòu】🚐。



2. 分配和释放设备【bèi】👰号【hào】

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

静态申🖐请设备【qǐng shè bèi】👰号【hào】。

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

动态申请设备【qǐng shè bèi】👰号【hào】,注意第🕳一个【yī gè】🐸参数是传地址♑,而静态【ér jìng tài】♈则是传🏘值。



3. 几种重【jǐ zhǒng chóng】👚要的数【yào de shù】🏋据结构【jié gòu】🚐

struct file

file结构【jié gòu】🚐代表一个【yī gè】👾打开的文件【de wén jiàn】🧐,它由内核在🍔open时创建,并传递给该文✖件上进【jiàn shàng jìn】行操作的【de】所有👎函数【hán shù】🌋,直到最后的【hòu de】close函数【hán shù】🌋。

file结构【jié gòu】🚐private_data是跨系【shì kuà xì】统调用【tǒng diào yòng】时保存状态【zhuàng tài】信息非常有用的【yǒu yòng de】资源。

file结构的【jié gòu de】❇f_ops 保存了文件【jiàn】🙇的【de】当前读🥕写位置。

struct inode

内核用【nèi hé yòng】inode代表一个【yī gè】👾磁盘上的文【de wén】🌬件【jiàn】,它和🛏file结构【jié gòu】🚐不同,后者表示打开的文件【de wén jiàn】🧐描述符【miáo shù fú】。对于单【duì yú dān】个【gè】🐸文件【jiàn】🙇,可能会有许多个【gè】表示🖼打开文件【jiàn】🙇的文件【de wén jiàn】🧐描述符【miáo shù fú】file结构【jié gòu】🚐,但他们【dàn tā men】〽都指单个【gè】🐸inode结构【jié gòu】🚐。inode的【de】dev_t i_rdev成员包含了【bāo hán le】真🥪正的【de】设🏵备【bèi】编号【hào】⛲,struct cdev *i_cdev包含了【bāo hán le】指向【zhǐ xiàng】struct cdev结构的【jié gòu de】❇指针🉐。

struct file_operations

file_operations结构【jié gòu】保🔮存了字📖符设备【bèi】👰驱动程序的【de】方法。



4. 字符设🖌备【bèi】的【de】注册和注👰销👼

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);

用【yòng】来管理【lǐ】🈵cdev结构的【jié gòu de】❇函数【hán shù】🌋,内核中使用【yòng】该🥁结构【jié gòu】🚐表示字【biǎo shì zì】符设🖌备【bèi】。注意🛬cdev_add函数【hán shù】🌋的【de】count参数为次设备【cì shè bèi】🌦的个数【de gè shù】🔩,要想拥【yào xiǎng yōng】有多个【gè】🐸次设备【cì shè bèi】🌦,就必须将该参数设为次设备【cì shè bèi】🌦的个数【de gè shù】🔩。



5. 并发处理【lǐ】🈵

信号量【xìn hào liàng】⛎和自旋锁【zì xuán suǒ】🎋的【de】区别,使用【yòng】📃信号量【xìn hào liàng】⛎时当调【shí dāng diào】用【yòng】🌊进程试图获得【tú huò dé】一个【yī gè】🐸锁定了的【de】锁时会导致【huì dǎo zhì】进程睡【jìn chéng shuì】眠,而自旋【ér zì xuán】锁🎋则是一直循👮法的【de】等待一直🆖到该锁解锁了为止。

1)信号量【xìn hào liàng】⛎

DECLARE_MUTEX(name);

DECLARE_MUTEX_LOCKED(name);

声明和初始化【chū shǐ huà】用【yòng】在互斥模式👖中的【de】信👘号量【hào liàng】🎁的【de】两个【gè】🐸宏

void init_MUTEX(struct semaphore *sem)

void init_MUTEX_LOCKER(struct semaphore*sem);

这两个【zhè liǎng gè】🐸函数【hán shù】可📅以在运【yǐ zài yùn】行时初始化【chū shǐ huà】信🃏号量【hào liàng】🎁

void down(struct semaphore *sem);

int down_interruptible(struct semaphore*sem);

int down_trylock(struct semahpore *sem);

void up(struct semaphore *sem);

锁定和🥣解锁信号量【xìn hào liàng】⛎。如果必【rú guǒ bì】要,down会将调用【yòng】进程置于不【zhì yú bú】可中断的【de】休眠状态【zhuàng tài】;相反【xiàng fǎn】,down_interruptible可被信号【hào】中断😰。down_trylock不会休🗣眠,并且会在信号量【xìn hào liàng】⛎不可用【bú kě yòng】时立😖即返回。锁定信😯号量【hào liàng】🎁的代码【de dài mǎ】最后必【zuì hòu bì】须使用【xū shǐ yòng】📃up解锁该信号量【xìn hào liàng】⛎。

2)自旋锁【zì xuán suǒ】🎋

spionlock_t lock = SPIN_LOCK_UNLOCKED;

spin_lock_init(spinlock_t *lock);

初始化【chū shǐ huà】自旋锁【zì xuán suǒ】🎋的两种【de liǎng zhǒng】方式。

voidspin_lock(spinlock_t *lock);

锁定自旋锁【zì xuán suǒ】🎋

voidspin_unlock(spinlock_t *lock);

解锁自旋锁【zì xuán suǒ】🎋

二【èr】、驱动【qū dòng】♐代码【dài mǎ】✈




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è bèi hào】😊
if(num> (MEMDEV_NUM -1)) //检查次【jiǎn chá cì】设备号【shè bèi hào】😊有效性
return-ENODEV;

dev= &mem_devp[num];
filp->private_data= dev; //将设备【jiāng shè bèi】结构🕞保存为私有数据🗾

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;

//检查偏🔂移量【yí liàng】🕣和数据【hé shù jù】大小的有效性
if(p> MEMDEV_SIZE)
return0;
if(count> (MEMDEV_SIZE-p))
count= MEMDEV_SIZE - p;

if(down_interruptible(&dev->sem))//锁定互【suǒ dìng hù】斥信号🥩量【liàng】🕣
return -ERESTARTSYS;

//读取数据到用🌾户空间【hù kōng jiān】
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);//解锁互😤斥信号🥩量【liàng】🕣

returnret;
}

static ssize_t mem_write(struct file *filp,const char __user *buf, size_t size, loff_t *ppos)//注意:第二个【dì èr gè】💇参数和🌸read方法不【fāng fǎ bú】🚝同
{
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))//锁定互【suǒ dìng hù】斥信号🥩量【liàng】🕣
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);//解锁互😤斥信号🥩量【liàng】🕣

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;

//申请设备号【shè bèi hào】😊
dev_tdevno = MKDEV(mem_major, 0);

if(mem_major)
result= register_chrdev_region(devno, MEMDEV_NUM, "memdev");//注意静态申请♿的dev_t参数和🌸动【dòng】态💬dev_t参数的【cān shù de】区别 <

关键词【guān jiàn cí】:Linux,设备驱动【qū dòng】♐

阅读本文后您有什么感想? 已有 人给出评价!

  • 1 欢迎喜欢
  • 1 白痴
  • 1 拜托
  • 1 哇
  • 1 加油
  • 1 鄙视