目标:实现一个简单的字符设备驱动,实现读写字符串功能。
驱动程序:
#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>
#define MIN(a,b) (a<b?a:b)
#define DEVICE_NAME "hello_alon"
static int major = 0;
static struct class *hello_class;
static char kernel_buf[1024];
static int hello_drv_open(struct inode *node, struct file *file)
{
printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
return 0;
}
static ssize_t hello_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
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 *offset)
{
int err;
printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
err = copy_from_user(kernel_buf,buf,MIN(1024,size));
return MIN(1024,size);
}
static int hello_drv_close(struct inode *node, struct file *file)
{
printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
return 0;
}
static struct file_operations hello_drv = {
.owner = THIS_MODULE,
.open = hello_drv_open,
.read = hello_drv_read,
.write = hello_drv_write,
.release = hello_drv_close,
};
static int __init hello_init(void)
{
int err;
printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
major = register_chrdev(0,"hello_chr",&hello_drv);
hello_class = class_create(THIS_MODULE,"hello_class");
err = PTR_ERR(hello_class);
if(IS_ERR(hello_class))
{
printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
unregister_chrdev(major,DEVICE_NAME);
return -1;
}
device_create(hello_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);
return 0;
}
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,DEVICE_NAME);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
测试程序:
#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
*/
#define DEVICE_NAME "/dev/hello_alon"
int main(int argc, char **argv)
{
int fd;
char buf[1024];
int len;
if(argc < 2)
{
printf("Usage: %s -w <string>\n",argv[0]);
printf(" %s -r\n",argv[0]);
return -1;
}
fd = open(DEVICE_NAME,O_RDWR);
if(fd == -1)
{
printf("cannot open %s \n",DEVICE_NAME);
return -1;
}
if(0 == strcmp(argv[1],"-w") && 3 == argc)
{
len = strlen(argv[2]) + 1;
len = len<1024?len:1024;
write(fd,argv[2],len);
}else{
len = read(fd,buf,1024);
buf[1023] = '\0';
printf("APP read: %s\n",buf);
}
close(fd);
return 0;
}
Makefile:
KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88
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
测试结果:
[root@100ask:/mnt/drv_code_of_Alon/01_hello_drv]# ./hello_drv_test -w abc123
[root@100ask:/mnt/drv_code_of_Alon/01_hello_drv]# ./hello_drv_test -r
APP read: abc123