2.最简单的hello驱动

写驱动最快的方法就是抄内核中的其他驱动,这里选择的是/Linux-4.9.88/drivers/char/mem.c
第一步新建一个hello_drv.c,把mem.c中的头文件都复制过来

#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>

#include <linux/uaccess.h>

第二步参考mem.c中的port_fops 来填充我们自己的file_operations结构体。owner通常都是设置为THIS_MODULE。

/*构建file_operations结构体*/
static const struct file_operations hello_fops = {
    .owner      = THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
    .release    = hello_release,
};

第三步实现这些read,write等函数。点到file_operations结构体定义的地方,把函数原型复制过来,例如read函数,改写一下成hello_read,依次把write,open,release函数补上,这里不操作任何东西,添加一些打印即可。

//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//参数含义依次为 要读取的文件指针 用户保存数据的buf 读取数据大小 文件内容的偏移量
static ssize_t hello_read (struct file * filp, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return size;
}

//ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//参数含义依次为 要写入的文件指针 用户要写入的数据buf 写入数据大小 文件内容的偏移量
static ssize_t hello_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return size;
}

//int (*open) (struct inode *, struct file *);
//参数含义依次为 文件索引节点 文件指针
static int hello_open (struct inode *node, struct file *filp)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}

//int (*release) (struct inode *, struct file *);
//参数含义依次为 文件索引节点 文件指针
static int hello_release (struct inode *node, struct file *filp)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0; 
}

第四步实现init和exit函数,这里我参考的是/Linux-4.9.88/drivers/char/mbcs.c中的init和exit。

/*init函数,实现register_chrdev*/
static int __init hello_init(void)
{
    //数含义依次为 主设备号,如果为0,内核会自动分配一个可用的。设备名称,会在/proc/devices中显示。 file_operations结构体
    major = register_chrdev(0, DEVICE_NAME, &hello_fops);
    return 0;
}

/*exit函数unregister_chrdev*/
static void __exit hello_exit(void)
{
    unregister_chrdev(0, DEVICE_NAME);
}

module_init(hello_init);
module_exit(hello_exit);

完整代码如下:

#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
#include <linux/module.h>

#include <linux/uaccess.h>

#define DEVICE_NAME "hello_device"
static int major;

//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//参数含义依次为 要读取的文件指针 用户保存数据的buf 读取数据大小 文件内容的偏移量
static ssize_t hello_read (struct file * filp, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return size;
}

//ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//参数含义依次为 要写入的文件指针 用户要写入的数据buf 写入数据大小 文件内容的偏移量
static ssize_t hello_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return size;
}

//int (*open) (struct inode *, struct file *);
//参数含义依次为 文件索引节点 文件指针
static int hello_open (struct inode *node, struct file *filp)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}

//int (*release) (struct inode *, struct file *);
//参数含义依次为 文件索引节点 文件指针
static int hello_release (struct inode *node, struct file *filp)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0; 
}

/*构建file_operations结构体*/
static const struct file_operations hello_fops = {
    .owner      = THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
    .release    = hello_release,
};

/*init函数,实现register_chrdev*/
static int __init hello_init(void)
{
    //数含义依次为 主设备号,如果为0,内核会自动分配一个可用的。设备名,会在/proc/devices中显示。 file_operations结构体
    //注册成功就返回主设备号
    major = register_chrdev(0, DEVICE_NAME, &hello_fops);
    return 0;
}

/*exit函数unregister_chrdev*/
static void __exit hello_exit(void)
{
    //数含义依次为 主设备号 设备名
    unregister_chrdev(major, DEVICE_NAME);
}

module_init(hello_init);
module_exit(hello_exit);
//遵循GPL协议
MODULE_LICENSE("GPL");

编译成功生成hello_drv.ko

在板子上insmod这个驱动后,cat /proc/deivers成功显示

dmesg也成功打印驱动insmod和rmmod的信息

[ 7011.402403] /home/book/nfs_rootfs/drivers_projects/01_hello_drv/hello_drv.c hello_init 75
[ 7015.647851] /home/book/nfs_rootfs/drivers_projects/01_hello_drv/hello_drv.c hello_exit 84


 

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值