Linux 编写简单驱动并测试

字符驱动编写

  1. 编写一个字符驱动
    在 driver/char/ 目录下新建一个 hello_dev.c 文件,用来编写一个字符驱动
    代码如下:

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/slab.h>

#define MAX_BUF_SZ (20)

struct cdev *hello_dev;
struct file_operations *hello_fops;
dev_t dev_num;
int reg_major = 520;
int reg_minor = 0;
char kernel_buffer[MAX_BUF_SZ];

static int hello_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG “[Linux kernel] enter hello_open.\n”);
return 0;
}

static ssize_t hello_read(struct file *file, char __user *buf, size_t count, loff_t *offp)
{
int len = (count < MAX_BUF_SZ) ? count : MAX_BUF_SZ;
printk(KERN_EMERG “[Linux kernel] enter hello_read.\n”);
if (copy_to_user(buf, kernel_buffer, len)) {
return -1;
}
return 0;
}

static ssize_t hello_write(struct file *file, const char __user *buf, size_t count, loff_t *offp)
{
int len = (count < MAX_BUF_SZ) ? count : MAX_BUF_SZ;
printk(KERN_EMERG “[Linux kernel] enter hello_write.\n”);
if (copy_from_user(kernel_buffer, buf, len)) {
return -1;
}
return len;
}

static int hello_init(void)
{
printk(KERN_EMERG “[Linux kernel] enter hello_init.\n”);
dev_num = MKDEV(reg_major, reg_minor);
if (!register_chrdev_region(dev_num, 1, “hello world”)) {
printk(KERN_EMERG “register_chrdev_region error.\n”);
return -1;
}

hello_dev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
hello_fops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);

hello_fops->open = hello_open;
hello_fops->read = hello_read;
hello_fops->write = hello_write;
hello_fops->owner = THIS_MODULE;

cdev_init(hello_dev, hello_fops);
cdev_add(hello_dev, dev_num, 3);
return 0;

}

static void __exit hello_exit(void)
{
printk(KERN_EMERG “[Linux kernel] enter hello_exit.\n”);
cdev_del(hello_dev);
unregister_chrdev_region(dev_num, 1);
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE(“GPL”);

  1. 修改编译文件 Makefile
    修改 driver/char/Makefile 文件,新增如下内容:

obj-$(CONFIG_HELLO) += hello_dev.o
1
3. 修改Kconfig文件
修改 driver/char/Kconfig 文件,该部分的修改,主要用来在编译内核时开启对应的驱动选项
在 Kconfig 文件中添加如下内容:

config HELLO
tristate “hello device”
default m
help
hello device
1
2
3
4
5
这里放个图,展示一下,使用 menuconfig 可以看到的编译内容吧:

默认配置为 M,这是因为我们一会还要得到对应生产的 ko 文件进行测试
在这里插入图片描述

字符驱动测试

  1. 编写测试驱动程序
    我们新建一个 test.c 用来测试该驱动程序(该程序是用户态执行的代码)

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>

#define DATA_NUM (20)

int main(int argc, char *argv[])
{
int fd;
int len;
char buf[DATA_NUM] = “hello world”;

fd = open("/dev/hello", O_RDWR);
if (fd == -1) {
	perror("open file error.\n");
	return -1;
}

printf("open file success, fd = %d.\n", fd);

len = write(fd, buf, DATA_NUM);
printf("write info = %s, len = %d.\n", buf, len);

memset(buf, 0, DATA_NUM);

len = read(fd, buf, DATA_NUM);
printf("read info = %s, len = %d.\n", buf, len);

close(fd);
return 0;

}

该测试程序主要对驱动程序进行打开、读写、关闭,虽然简单,但是麻雀虽小五脏俱全
编写好对应的测试程序后,进行编译

gcc test.c -o test --static
1
2. 将驱动程序和测试程序放入到环境中
我们需要将编译好的 hello_dev.ko 和 test 可执行文件,放入到 qemu 的运行环境中,才能进行下一步的测试
放好后,是这个样子:
在这里插入图片描述

  1. 测试环节
    先将驱动程序进行加载

/ # insmod hello_dev.ko
[ 21.168929] [Linux kernel] enter hello_init.
[ 21.169381] CHRDEV “hello world” major requested (520) is greater than the maximum (511)
/ #
1
2
3
4
创建对应的驱动文件

mknod /dev/hello c 520 0
1
执行测试程序

/ # ./test
[ 88.997694] [Linux kernel] enter hello_open.
open file success, fd = 3.
[ 89.002685] [Linux kernel] enter hello_write.
write info = hello world, len = 20.
[ 89.003895] [Linux kernel] enter hello_read.
read info = hello world, len = 0.
[ 89.006303] test (87) used greatest stack depth: 13472 bytes left
/ #
1
2
3
4
5
6
7
8
9
这些就是全部的内容了,感谢浏览!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

android framework

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值