hello驱动程序

一、hello驱动程序

编程过程当中,注意参考内核的历程。


#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>


/*1、确定主设备号*/
static int major = 0;
static char kernel_buf[1024];
static struct class *hello_class;
#define MIN(a,b) (a < b ? a : b)


static ssize_t hello_drv_read (struct file *, char __user *, size_t, loff_t *);
static ssize_t hello_drv_write (struct file *, const char __user *, size_t, loff_t *);
static int hello_drv_open (struct inode *, struct file *);
static int hello_drv_close (struct inode *, struct file *);


/*2、定义自己的file_operations结构体*/
static const struct file_operations hello_drv_fops = {
	.owner		= THIS_MODULE,
	.open		= hello_drv_open,
	.read		= hello_drv_read,
	.write		= hello_drv_write,
	.release	= hello_drv_close,
};
	

/*3、实现对应的open、read、write等函数,填入file_operations结构体内*/

static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *off)
{
	int err;
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	err = copy_to_user(buf, kernel_buf, MIN(1024, size));
	return MIN(1024, size);
}

static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *off)
{
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	copy_from_user(kernel_buf, buf, MIN(1024, size));
	return MIN(1024, size);
}

static int hello_drv_open (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	return 0;

}
static int hello_drv_close (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	return 0;
}



/*4、吧file_operations结构体告诉内核:注册驱动程序*/

/*5、谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数*/
static int __init hello_init(void)
{
	int err;
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	major = register_chrdev(0, "hello", &hello_drv_fops);

	//自动创建设备节点
	hello_class = class_create(THIS_MODULE, "hello_class");
	err = PTR_ERR(hello_class);
	if (IS_ERR(hello_class))
	{
		unregister_chrdev(major,"hello");
		return -1;
	}

	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");// /dev/hello
	return 0;
}


/*6、有入口函数就有出口函数:卸载驱动时就会去调用这个出口函数*/
static void __exit hello_exit(void)
{
	printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
	device_destroy(hello_class, MKDEV(major, 0));
	class_destroy(hello_class);
	unregister_chrdev( major, "hello");
}



/*7、其它完善:提供设备信息,自动创建设备节点*/

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tanzhenwen");

二、测试程序

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

/*
 * ./hello_drv_test -w abc
 * ./hello_drv_test -r
 */
 int main(int argc, char *argv[])
{
	int fd;
	char buf[1024];
	int len;

	/*1、判断参数*/
	if(argc < 2)
	{
		printf("Usage: %s -w <string>\n",argv[0]);
		printf("       %s -r\n",argv[0]);
		return -1;
	}

	/*2、打开文件 */
	fd = open("/dev/hello", O_RDWR);	//可读可写
	if(fd == -1)
	{
		printf("can not open file /dev/hello\n");
		return -1;
	}

	/* 写文件或者读文件 */
	if((0 == strcmp(argv[1],"-w")) && (argc == 3))
	{
		len = strlen(argv[2]) + 1;
		len = len < 1024 ? len : 1024;
		write(fd, argv[2], len);
	}
	else
	{
		len = read(fd,buf,1024);
		buf[1023] = '\0';
		//
		flush();
		printf("APP read: %s\n", buf);
		flush();
	}
	close(fd);
	return 0;
}

三、Makefile编写

KERN_DIR = /home/book/100ask_stm32mp157_pro-sdk/Linux-5.4

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	$(CROSS_COMPILE)gcc -o hello_drv_test hello_drv_test.c
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order  
	rm -f hello_drv_test
obj-m        += hello_drv.o

四、测试

开发板IP:192.168.124.29;虚拟机IP:192.168.124.30

在虚拟机上设置nfs共享目录/home/book/nfs_rootfs,将驱动程序及测试程序拷贝至该目录下。

开发板上执行挂载命令:

mount -t nfs -o nolock 192.168.124.30:/home/book/nfs_rootfs /mnt

在开发板上执行

insmod insmod hello_drv.ko
./hello_drv_test -w testtesttesttest
./hello_drv_test -r

在开发板上通过cat /proc/device可以查看所有设备的设备号;lsmod可以查看相关驱动装载信息;ls /dev/hello -al 可以查看hello设备的设备号等信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值