支持udev的字符驱动。
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/fs.h>
-
#include <linux/cdev.h>
-
#include <linux/device.h>
-
-
static int major = 232; //静态设备节点方式的默认值
-
static int minor = 0; //静态设备节点方式的默认值
-
module_param(major, int, S_IRUGO);
-
module_param(minor, int, S_IRUGO);
-
-
struct cdev *char_cdev; //cdev数据结构
-
static dev_t devno; //设备编号
-
static struct class *char_cdev_class;
-
-
#define DEVICE_NAME "charcdev"
-
-
static int char_cdev_open(struct inode *inode, struct file *file )
-
{
-
try_module_get(THIS_MODULE);
-
printk(KERN_INFO DEVICE_NAME "opened!\n");
-
-
return 0;
-
}
-
-
static int char_cdev_release(struct inode *inode, struct file *file )
-
{
-
printk(KERN_INFO DEVICE_NAME "closed!\n");
-
-
module_put(THIS_MODULE);
-
return 0;
-
}
-
-
-
static ssize_t char_cdev_read(struct file *file, char *buf,size_t count, loff_t *f_pos)
-
{
-
printk(KERN_INFO DEVICE_NAME "read method!\n");
-
-
return count;
-
}
-
-
static ssize_t char_cdev_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
-
{
-
printk(KERN_INFO DEVICE_NAME "write method!\n");
-
-
return count;
-
}
-
-
static int char_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-
{
-
printk(KERN_INFO DEVICE_NAME "ioctl method!\n");
-
-
return 0;
-
}
-
-
struct file_operations char_cdev_fops = {
-
.owner = THIS_MODULE,
-
.read = char_cdev_read,
-
.write = char_cdev_write,
-
.open = char_cdev_open,
-
.release = char_cdev_release,
-
.ioctl = char_cdev_ioctl
-
};
-
-
-
static int __init char_cdev_init(void)
-
{
-
int ret;
-
-
if (major > 0) { //静态设备节点
-
devno = MKDEV(major, minor);
-
ret = register_chrdev_region(devno, 1, "char_cdev");
-
} else { //动态设备节点
-
ret = alloc_chrdev_region(&devno, minor, 1, "char_cdev"); //从系统获取主设备号
-
major = MAJOR(devno);
-
-
}
-
if (ret < 0) {
-
printk(KERN_ERR "cannot get major %d \n", major);
-
return -1;
-
}
-
-
char_cdev = cdev_alloc(); //分配char_cdev结构
-
if (char_cdev != NULL) {
-
cdev_init(char_cdev, &char_cdev_fops); //初始化char_cdev结构
-
//char_cdev->ops = &char_cdev_fops; //可以不要
-
char_cdev->owner = THIS_MODULE;
-
if (cdev_add(char_cdev, devno, 1) != 0) { //增加char_cdev到系统中
-
printk(KERN_ERR "add cdev error!\n");
-
goto error1;
-
}
-
-
} else {
-
printk(KERN_ERR "cdev_alloc error!\n");
-
goto error2;
-
}
-
-
char_cdev_class = class_create(THIS_MODULE, "char_cdev_class"); //在/sys/class/下创建char_cdev_class目录
-
if (IS_ERR(char_cdev_class)) {
-
printk(KERN_INFO "create class error\n");
-
return -1;
-
}
-
//device_create(char_cdev_class, NULL, devno, NULL, "char_cdev" "%d", MINOR(devno)); //将创建/dev/char_cdev0文件
-
device_create(char_cdev_class, NULL, devno, NULL, "char_cdev", NULL); //将创建/dev/char_cdev文件
-
-
return 0;
-
-
error1:
-
unregister_chrdev_region(devno, 1); //释放已经获得的设备号
-
error2:
-
return ret;
-
}
-
-
static void __exit char_cdev_exit(void)
-
{
-
device_destroy(char_cdev_class, devno);
-
class_destroy(char_cdev_class);
-
cdev_del(char_cdev); //移除字符设备
-
unregister_chrdev_region(devno, 1); //释放设备号
-
}
-
-
module_init(char_cdev_init);
-
module_exit(char_cdev_exit);
-
-
MODULE_LICENSE("GPL");
-
MODULE_AUTHOR("Chenxibing,hibrian.chen@gmail.com");
使用方法:
支持静态/动态设备节点,自动创建设备节点。
#insmod char_cdev.ko
# cat /proc/devices
232 char_cdev
#ls /dev/char_cdev -l
crw------- 1 root root 232, 0 2011-01-16 20:43 /dev/char_cdev
#ls /sys/class/char_cdev_class/char_cdev -la
lrwxrwxrwx 1 root root 0 2011-01-16 20:58 /sys/class/char_cdev_class/char_cdev -> ../../devices/virtual/char_cdev_class/char_cdev
测试程序:
-
1 #include <stdio.h>
-
2 #include <stdlib.h>
-
3 #include <unistd.h>
-
4 #include <sys/ioctl.h>
-
5 #include <errno.h>
-
6 #include <fcntl.h>
-
7
-
8 #define DEV_NAME "/dev/char_cdev"
-
9
-
10 int main(int argc, char *argv[])
-
11 {
-
12 int i;
-
13 int fd = 0;
-
14 int dat = 0;
-
15
-
16 fd = open (DEV_NAME, O_RDWR);
-
17 if (fd < 0) {
-
18 perror("Open "DEV_NAME" Failed!\n");
-
19 exit(1);
-
20 }
-
21
-
22 i = read(fd, &dat, 1);
-
23 if (!i) {
-
24 perror("read "DEV_NAME" Failed!\n");
-
25 exit(1);
-
26 }
-
27
-
28 dat = 0;
-
29 i = write(fd, &dat, 1);
-
30 if (!i) {
-
31 perror("write "DEV_NAME" Failed!\n");
-
32 exit(1);
-
33 }
-
34
-
35 i = ioctl(fd, NULL, NULL);
-
36 if (!!i) {
-
37 perror("ioctl "DEV_NAME" Failed!\n");
-
38 exit(1);
-
39 }
-
40
-
41 close(fd);
-
42 return 0;
-
43 }
阅读(2202) | 评论(0) | 转发(0) |