【12】Linux-自己动手写驱动

Linux-自己动手写驱动

流程图:

 

代码模块化:

#include <linux/module.h>

#include <linux/init.h>

struct cdev mdev;

dev_t devno;

 

loff_t mem_lseek(struct file *file, loff_t ppos, int whence)

{

}

ssize_t mem_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)

{

/*1.获得设备的基地址*/

/*2.将设备中指定位置的内容输出到用户空间中*/

/*3.移动ppos*/

}

ssize_t mem_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)

{

/*1.获得设备的基地址*/

/*2.将用户空间的数据写入到设备指定位置中*/

/*3.移动ppos*/

}

int mem_close(struct inode *inode, struct file *file)

{

}

int mem_open(struct inode *inode, struct file *file)

{

/*1.标明设备号*/

/*2.识别次设备号*/

/*3.启动设备*/

}

struct file_operations f_ops ={

.llseek = mem_lseek,

.read = mem_read,

.write = mem_write,

.release = mem_close,

.open = mem_open,

};

static int mem_init(void)

{

/*1.初始化mdev*/

/*2.分配设备号以及注册mdev*/

}

static void mem_exit(void)

{

/*1.注销设备*/

/*2.注销设备号*/

}

module_init(mem_init);

module_exit(mem_exit);

实际代码:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
 
struct cdev mdev;
dev_t devno;
 
int dev1_register[5];
int dev2_register[5];
 
loff_t mem_lseek(struct file *file, loff_t ppos, int whence)
{
unsigned newpos = 0;
 
/*1.根据whence来获得偏移量*/
switch(whence){
case SEEK_SET:
newpos = ppos;
break;
case SEEK_CUR:
newpos = file->f_pos + ppos;
break;
 
case SEEK_END:
newpos = 5*sizeof(int) -1 + ppos;
break;
 
default:
break;
}
file->f_pos = newpos;
 
return newpos;
}
 
ssize_t mem_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
unsigned p = *ppos;
 
/*1.获得设备的基地址*/
int *register_addr = file->private_data;
 
/*2.将设备中指定位置的内容输出到用户空间中*/
copy_to_user(buf, register_addr + p, size);
 
/*3.移动ppos*/
file->f_pos += size;
 
return size;
}
 
ssize_t mem_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
{
unsigned p = *ppos;
 
/*1.获得设备的基地址*/
int *register_addr = file->private_data;
 
/*2.将用户空间的数据写入到设备指定位置中*/
copy_from_user(register_addr + p, buf, size);
 
/*3.移动ppos*/
file->f_pos += size;
 
return size;
}
 
int mem_close(struct inode *inode, struct file *file)
{
/*由于此处是虚拟设备,故返回0即可*/
return 0;
}
 
int mem_open(struct inode *inode, struct file *file)
{
/*1.标明设备号*/
int num = MINOR(inode->i_rdev);
 
/*2.识别次设备号*/
if(num == 0)
{
file->private_data = dev1_register;
}else if(num == 1)
{
file->private_data = dev2_register;
}else{
return 0;
}
/*3.启动设备,由于此处是虚拟设备,故不需要*/
return 0;
}
 
 
struct file_operations f_ops ={
.llseek = mem_lseek,
.read = mem_read,
.write = mem_write,
.release = mem_close,
.open = mem_open,
};
 
static int mem_init(void)
{
/*1.初始化mdev*/
cdev_init(&mdev, &f_ops);
 
/*2.分配设备号以及注册mdev*/
alloc_chrdev_region(&devno, 0, 2, "oujiayu_memdev");
cdev_add(&mdev, devno, 2);
 
return 0;
}
 
static void mem_exit(void)
{
/*1.注销设备*/
cdev_del(&mdev);
 
/*2.注销设备号*/
unregister_chrdev_region(devno, 2);
 
}
 
module_init(mem_init);
module_exit(mem_exit);


Tips:

1.struct file_operations f_ops ={.llseek = xxx,};是对结构体变量f_ops进行初始化,类似于C++中的列表初始化,其中.llseek是C99的扩展,可以使用.成员来对结构体中的指定成员进行初始化。

2.当应用程序对设备文件进行读写等操作的时候,内核会将相应的参数传入到驱动程序的相应函数中作为形参,从而实现驱动功能的实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值