Linux字符设备驱动

来源:互联网 发布:淘宝关键词top100 编辑:程序博客网 时间:2024/06/06 08:51

一、函数解析

1、int register_chrdev_region(dev_t first, unsigned int count, char *name)
为一个字符驱动获取一个或多个设备编号
     参数解析
first:是你要分配的起始设备编号.,first 的次编号部分常常是 0。使用MKDEV(major, 0) 来获取dev_t类型的设备编号
count是你请求的连续设备编号的总数
  name:是应当连接到这个编号范围的设备的名字; 它会出现在 /proc/devices 和 sysfs 中
      返回值:  如果分配成功进行, register_chrdev_region 的返回值是 0
2、int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name)
动态分配设备编号
参数解析
dev:动态分配的设备编号保存在dev上
firstminor:第一个次设备号(一般为0)
count:是你请求的连续设备编号的总数
   name:是应当连接到这个编号范围的设备的名字; 它会出现在 /proc/devices 和 sysfs 中
3、void cdev_init(struct cdev *cdev, const struct file_operations *fops)
静态初始化一个cdev结构体变量,内核中每个字符设备都对应一个 cdev 结构的变量
参数解析
cdev:struct cdev结构体指针,初始化该结构体
fops: struct file_operations结构体指针,已经赋值了对应的函数
4、int cdev_add(struct cdev *p, dev_t dev, unsigned count)
把cdev添加到系统中去
参数解析
p:struct cdev结构体指针
dev: dev_t类型的设备编号
count: 连续次设备号数
5、void cdev_del(struct cdev *p)
从系统移除cdev
参数解析
p:struct cdev结构体指针

二、例程

/*******************************************使用linux3.2.81内核********************************************/#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/cdev.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>/* 1. 确定主设备号 */static int major;static int hello_open(struct inode *inode, struct file *file){printk("hello_open\n");return 0;}static int hello2_open(struct inode *inode, struct file *file){printk("hello2_open\n");return 0;}/* 2. 构造file_operations */static struct file_operations hello_fops = {.owner = THIS_MODULE,.open  = hello_open,};static struct file_operations hello2_fops = {.owner = THIS_MODULE,.open  = hello2_open,};#define HELLO_CNT   2static struct cdev hello_cdev;static struct cdev hello2_cdev;static struct class *cls;static int hello_init(void){dev_t devid;/* 3. 告诉内核 */if (major) {devid = MKDEV(major, 0);    //返回dev_t类型的设备编号register_chrdev_region(devid, HELLO_CNT, "hello");  /* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */} else {alloc_chrdev_region(&devid, 0, HELLO_CNT, "hello"); /* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */major = MAJOR(devid);   //获取主设备号                  }cdev_init(&hello_cdev, &hello_fops); //静态初始化一个cdev结构体变量,内核中每个字符设备都对应一个 cdev 结构的变量cdev_add(&hello_cdev, devid, HELLO_CNT); //把cdev添加到系统中去devid = MKDEV(major, 2);register_chrdev_region(devid, 1, "hello2");cdev_init(&hello2_cdev, &hello2_fops);cdev_add(&hello2_cdev, devid, 1);cls = class_create(THIS_MODULE, "hello");device_create(cls, NULL, MKDEV(major, 0), NULL, "hello0"); /* /dev/hello0 */device_create(cls, NULL, MKDEV(major, 1), NULL, "hello1"); /* /dev/hello1 */device_create(cls, NULL, MKDEV(major, 2), NULL, "hello2"); /* /dev/hello2 */device_create(cls, NULL, MKDEV(major, 3), NULL, "hello3"); /* /dev/hello3 */return 0;}static void hello_exit(void){device_destroy(cls, MKDEV(major, 0));device_destroy(cls, MKDEV(major, 1));device_destroy(cls, MKDEV(major, 2));device_destroy(cls, MKDEV(major, 3));class_destroy(cls);cdev_del(&hello_cdev);  //从系统中删除cdevunregister_chrdev_region(MKDEV(major, 0), HELLO_CNT);cdev_del(&hello2_cdev);unregister_chrdev_region(MKDEV(major, 2), 1);}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");

测试程序
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>/*  * hello_test /dev/hello0 */void print_usage(char *file){printf("%s <dev>\n", file);}int main(int argc, char **argv){int fd;if (argc != 2){print_usage(argv[0]);return 0;}fd = open(argv[1], O_RDWR);if (fd < 0)printf("can't open %s\n", argv[1]);elseprintf("can open %s\n", argv[1]);return 0;}





0 0
原创粉丝点击