实现一个虚拟设备“自增器”,该设备把写入的数据自增1。
ganquan@debian:~/Driver/01$ cat Add.h
#ifndef _MYDRIVER_H
#define _MYDRIVER_H
#include <linux/cdev.h> /*cdev*/
#include <linux/types.h> /*ssize_t*/
/*设备对象*/
struct Add
{
struct cdev MyChrDevice; /*Char device structure*/
};
/*驱动程序要实现的函数*/
ssize_t Add_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
ssize_t Add_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
#endif /*_MYDRIVER_H*/
ganquan@debian:~/Driver/01$ cat Add.c
#include <linux/init.h> /*包含用于声明装载模块初始化和清除函数的宏*/
#include <linux/module.h> /*包含装载模块需要的符号和函数定义*/
#include <linux/kernel.h> /*printk()*/
#include <linux/fs.h> /*申请设备号函数和数据结构,file_operation*/
#include <linux/types.h> /*dev_t*/
#include <linux/kdev_t.h> /*包含获取主设备号和次设备号的宏*/
#include <linux/slab.h> /*kmalloc()*/
#include <linux/cdev.h> /*cdev,cdev_init(),cdev_add()*/
#include <asm/uaccess.h> /*copy_to_user(),copy_from_user()*/
#include "Add.h"
static int global_var = 0;
int Add_major = 0; /*主设备号*/
int Add_minor = 0; /*次设备号*/
struct Add *mydev;
struct file_operations Add_fops = {
.owner = THIS_MODULE,
.read = Add_read,
.write = Add_write,
};
ssize_t Add_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
if(copy_to_user(buf,&global_var,sizeof(int)))
{
return -EFAULT;
}
return sizeof(int);
}
ssize_t Add_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
if(copy_from_user(&global_var,buf,sizeof(int)))
{
return -EFAULT;
}
if(global_var != 0)
global_var++;
return sizeof(int);
}
static int MyDriver_init(void)
{
int ret;
int devno;
dev_t dev;
/*申请设备号*/
ret = alloc_chrdev_region(&dev,0,1,"Add");
if(ret < 0)
{
printk(KERN_ALERT "Can not get dev_t\n");
}
else
{
Add_major = MAJOR(dev); /*MAJOR in <linux/kdev_t.h>*/
Add_minor = MINOR(dev); /*MINOR in <linux/kdev_t.h>*/
}
/*申请设备号结束*/
/*分配设备内存空间*/
mydev = kmalloc(sizeof(struct Add),GFP_KERNEL);
if(!mydev)
{
printk(KERN_ALERT "kmalloc error\n");
}
/*分配内存空间结束*/
/*初始化内存空间*/
memset(mydev,0,sizeof(struct Add));
/*注册字符设备*/
devno = MKDEV(Add_major,Add_minor);
cdev_init(&mydev->MyChrDevice,&Add_fops);
mydev->MyChrDevice.owner = THIS_MODULE;
mydev->MyChrDevice.ops = &Add_fops;
ret = cdev_add(&mydev->MyChrDevice,devno,1);
if(ret)
printk(KERN_ALERT "Error %d adding Add\n",ret);
/*注册字符设备结束*/
return 0;
}
static void MyDriver_exit(void)
{
dev_t devno;
devno = MKDEV(Add_major,Add_minor);
cdev_del(&mydev->MyChrDevice);
unregister_chrdev_region(devno,1);
kfree(mydev);
}
module_init(MyDriver_init); /*声明模块加载初始化函数*/
module_exit(MyDriver_exit); /*声明模块卸载清除函数*/
MODULE_LICENSE("GPL"); /*驱动许可证协议*/
MODULE_AUTHOR("GanQuan"); /*作者*/
MODULE_VERSION("0.0.1"); /*版本号*/
不变的Makefile:
ganquan@debian:~/Driver/01$ cat Makefile
obj-m := Add.o KDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) .PHONY:clean clean: rm -f *.mod.c *.mod.o *.ko *.o *.tmp_versions
驱动加载脚本:
ganquan@debian:~/Driver/01$ cat addload
#!/bin/bash
#author ganqan
# imganquan@gmail.com
#load a module
module="Add"
device="Add"
mode="777"
/sbin/insmod ./${module}.ko || exit 1
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
mknod /dev/${module} c $major 0
chmod $mode /dev/${device}
devinfo=`ls -l /dev/${device}`
echo "insmod :$module.ko"
echo "major :$major"
echo "devinfo :$devinfo"
驱动卸载脚本:
ganquan@debian:~/Driver/01$ cat addunload
#!/bin/bash
#author ganquan
# imganquan@gmail.com
#unload a module
module="Add"
device="Add"
/sbin/rmmod $module || exit 1
rm -f /dev/${device}
很简单的测试程序:
ganquan@debian:~/Driver/01$ cat test.c
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
int fd,num;
fd = open("/dev/Add", O_RDWR, S_IRUSR | S_IWUSR);
if (fd != -1)
{
read(fd, &num, sizeof(int));
printf("The MyDevice is %d\n", num);
printf("Please input the num written to MyDevice\n");
scanf("%d", &num);
write(fd, &num, sizeof(int));
read(fd, &num, sizeof(int));
printf("The MyDevice is %d\n", num);
close(fd);
}
else
printf("Device open failure\n");
return 0;
}
测试结果:
ganquan@debian:~/Driver/01$ sudo ./addload insmod :Add.ko major :249 devinfo :crwxrwxrwx 1 root root 249, 0 2009-06-09 22:55 /dev/Add ganquan@debian:~/Driver/01$ ./test The MyDevice is 0 Please input the num written to MyDevice 7 The MyDevice is 8 ganquan@debian:~/Driver/01$ sudo ./addunload