文章目录
前言
本文记录的是第一个驱动程序的全过程,笔记来源是韦老师的视频内容。
1 编写第一个驱动程序流程
1.1 写出open、write函数
通过在linux内核的工程里面搜索关键字:open和write,找到了相应的函数模板
1.2 告诉内核有这些open 、wite驱动函数
定义一个结构体file_operations
找到file_operations例子,通过在linux内核的工程里面搜索关键字:file_operations
linux内核工程文件的file_operations使用例子
这个是file_operations的结构体成员
/*
* NOTE:
* read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl
* can be called without the big kernel lock held in all filesystems.
*/
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};
里面的成员都是指向一个函数。
1.3 定义一个file_operations结构体
static const struct file_operations first_drv_fops = {
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
1.4 注册驱动程序register_chrdev
int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
通俗易懂的来说:注册,告诉内核
参数:
①主设备号 ②名字 ③file_operations结构体名字
主设备号:第一,我们的应用程序
次设备号:
1.5 编写驱动的入口函数
通俗易懂的来说:谁来调用register_chrdev,谁就是驱动的入口函数
int first_drv_init(void)
{
register_chrdev(major, "first_drv", &first_drv_fops);
}
1.6 修饰驱动入口函数和出口函数
驱动的入口函数有非常多,有first_drv_init、second_drv_init
通俗易懂来说:告诉内核对应的驱动入口函数
出入口函数,就有出口函数first_drv_exit
2 整体框架
3 代码
3.1 驱动程序first_drv.c
first_drv.c代码如下(示例):
#include <sound/driver.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
#include <asm/io.h>
static int first_drv_open(struct inode *inode, struct file *file)
{
printk("first_drv_open\n");
return 0;
}
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
printk("first_drv_write\n");
return 0;
}
static const struct file_operations first_drv_fops = {
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
int first_drv_init(void)
{
register_chrdev(111, "first_drv", &first_drv_fops); //注册,告诉内核 主设备号是111
return 0;
}
void first_drv_exit(void)
{
unregister_chrdev(111, "first_drv"); //卸载字符设备驱动
return ;
}
module_init(first_drv_init);
module_exit(first_drv_exit);
3.2 Makefile
KERN_DIR = /home/book/work/system/linux-2.6.22.6
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += first_drv.o
3.3 测试程序firstdrvtest.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/xyz", O_RDWR);
if (fd < 0)
printf("can't open!\n");
write(fd, &val, 4);
return 0;
}
4 结果
①将make好的驱动程序放入到开发板系统
②insmod firstdrv.ko
③通过交叉编译链工具,将编译好的测试程序放入到开发板系统
④创建设备节点:mknod /dev/xyz c 111 0
⑤执行测试程序:./firstdrvtest
结果