#include
#include
#include
#include
#define HELLO_MAJOR 0
#define HELLO_NR_DEVS 2
int hello_major = HELLO_MAJOR;
int hello_minor = 0;
//高12位是主设备号,低20位是次设备号
dev_t devt;
int hello_nr_devs = HELLO_NR_DEVS;
module_param(hello_major, int, S_IRUGO);
module_param(hello_minor, int, S_IRUGO);
module_param(hello_nr_devs, int, S_IRUGO);
/*实际的字符设备结构*/
struct hello_char_dev {
struct cdev cdev; /*类似于面向对象的继承*/
char c;
};
struct hello_char_dev *hc_devp;
int hc_open(struct inode *inode, struct file *filp) {
printk(KERN_INFO "open hc_dev%d %d\n",iminor(inode),MINOR(inode->i_cdev->dev));
return 0;
}
ssize_t hc_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos) {
printk(KERN_INFO "read hc_dev\n");
return 0;
}
ssize_t hc_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) {
printk(KERN_INFO "write hc_dev\n");
/*不能返回0,否则会不停的写*/
return count;
}
int hc_release(struct inode *inode, struct file *filp) {
printk(KERN_INFO "release hc_dev\n");
return 0;
}
/*字符设备的操作函数*/
struct file_operations hc_fops = {
.owner = THIS_MODULE,
.read = hc_read,
.write = hc_write,
.open = hc_open,
.release = hc_release,
};
static int __init hello_init(void) {
int ret,i;
if(hello_major) {
devt = MKDEV(hello_major,hello_minor);
ret = register_chrdev_region(devt,hello_nr_devs,"hello_chr");
}
else {
ret = alloc_chrdev_region(&devt,hello_minor,hello_nr_devs,"hello_chr");
hello_major = MAJOR(devt);
}
if (ret < 0) {
printk(KERN_WARNING "hello: can't get major %d\n", hello_major);
goto fail;
}
hc_devp = kzalloc(sizeof(struct hello_char_dev)*hello_nr_devs,GFP_KERNEL);
if(!hc_devp) {
printk(KERN_WARNING "alloc mem failed");
ret = -ENOMEM;
goto failure_kzalloc;
}
for(i = 0; i < hello_nr_devs; i++) {
cdev_init(&hc_devp[i].cdev,&hc_fops);
hc_devp[i].cdev.owner = THIS_MODULE;
ret = cdev_add(&hc_devp[i].cdev,MKDEV(hello_major,hello_minor+i),1);
if(ret) {
printk(KERN_WARNING"fail add hc_dev%d",i);
}
}
return 0;
failure_kzalloc:
unregister_chrdev_region(devt,hello_nr_devs);
fail:
return ret;
}
static void __exit hello_exit(void) {
int i;
for(i=0;i<hello_nr_devs;i++)
cdev_del(&hc_devp[i].cdev);
kfree(hc_devp);
unregister_chrdev_region(devt,hello_nr_devs);
printk(KERN_INFO "GOODBYE LINUX\n");
}
module_init(hello_init);
module_exit(hello_exit);
//描述性定义
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("KGZ");
MODULE_VERSION("V1.0");
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m :=hello_chr.o
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.mod *.order *.symvers
模块只有一些打印,省略了具体的操作,一些读写函数里面和初始化函数里面的操作比较固定。
程序当中没有使用相关的api来创建设备文件,这里的话,可以使用命令进行创建,
后续可以使用cat命令和echo进行读和写,然后观察驱动程序的输出。