编写最简单的字符设备驱动

helloDev.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 BUFFER_MAX (10)
#define OK         (0)
#define ERROR      (-1)

struct cdev *gDev;
struct file_operations *gFile;
dev_t devNum;
unsigned int subDevNum = 1;
int reg_major = 232;
int reg_minor = 0;
char *buffer;
int flag = 0;

int hello_open(struct inode *p, struct file *f)
{
    printk(KERN_EMERG"hello_open\r\n");
    return 0;
}

ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)
{
    printk(KERN_EMERG"hello_write\r\n");
    return 0;
}

ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
{
    printk(KERN_EMERG"hello_read\r\n");
    return 0;
}

int hello_init(void)
{
    devNum = MKDEV(reg_major, reg_minor);       /* 将主设备号和次设备号生成一个 dev_t 类型 */
    /* 注册字符驱动 */
    if ( OK == register_chrdev_region(devNum, subDevNum, "helloworld"))
    {
        printk(KERN_EMERG"register_chrdev_region ok \n");
    }
    else
    {
        printk(KERN_EMERG"register_chrdev_region error \n");
        return ERROR;
    }
    
    printk(KERN_EMERG" hello driver init \n");
    gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
    gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
    gFile->open = hello_open;
    gFile->read = hello_read;
    gFile->write = hello_write;
    gFile->owner = THIS_MODULE;
    cdev_init(gDev, gFile);                 /* 将文件描述符和文件操作函数关联其阿里 */
    cdev_add(gDev, devNum, 1);              /* 注册一个文件描述符 */
    return 0;
}

void __exit hello_exit(void)
{
    cdev_del(gDev);
    unregister_chrdev_region(devNum, subDevNum);
    return;
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

Makefile

ifneq ($(KERNELRELEASE),)
obj-m := helloDev.o
else
PWD := $(shell pwd)
KDIR := /lib/modules/`uname -r`/build
all:
    make -C $(KDIR) M=$(PWD)
clean:
    rm -rf *.o *.ko *.mod.c *.symvers *.c~ *.~
endif
解释一下这个Makefile:
1、ifneq ($(KERNELRELEASE))   判断是否存在这个定义,第一次进入该Makefile时,该处为空
2、走到else分支,读取赋值当前的一些变量,以及内核编译的工作路径
3、make -C ... , 表示走内核对改文件进行编译
4、第二次从内核工作路径进入改文件,所以第一行判断生效,进行ko文件的编译
5、正常编译产生helloDev.ko 的驱动文件

insmod hellloDev.ko 装载驱动
rmmod helloDev.ko 卸载驱动
demsg 信息查看内核打印日志信息    

编写最简单的字符设备驱动

上一篇:界面数据结构转换存储


下一篇:阿粉带你学习设计模式之原型(Prototype)模式