字符设备驱动
linux 2.6的字符驱动由cdev结构体描述,具体参考globalmem例子,代码主要分以下几部分:
1. 定义一个字符类型设备驱动的结构体
struct globalmem_dev{ struct cdev cdev; /*linux 2.6 内核表示一个字符设备结构体 */ unsigned char mem[200];};
其中cdev在cdev.h文件中定义如下:
struct cdev { struct kobject kobj; struct module *owner; struct file_operations *ops; //文件操作结构体 struct list_head list; dev_t dev; //设备号 unsigned long unsigned int count;};
2. 在驱动模块的加载、卸载函数中注册设备,同时绑定文件操作结构体
static const struct file_operations globalmem_fops = { .owner = THIS_MODULE, .llseek = globalmem_llseek, .read = globalmem_read, .write = globalmem_write, .open = globalmem_open, .release= globalmem_release};//设备驱动加载int globalmem_init(void){ int result; dev_t devno = MKDEV(200, 0); result = register_chrdev_region(devno, 1, "globalmem");//注册字符设备编号 globalmem_devp= kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL); memset(globalmem_devp, 0, sizeof(struct globalmem_dev)); cdev_init(&globalmem_devp->cdev, &globalmem_fops); globalmem_devp->cdev.owner = THIS_MODULE; int err = cdev_add(&globalmem_devp->cdev, devno, 1); return result;}
3. 实现文件操作的具体接口,以文件写为例:
static ssize_t globalmem_read(struct file *flip, char __user *buf, size_t size, loff_t *ppos){ //.... struct globalmem_dev *dev = flip->private_data; copy_to_user(buf, (void*)(dev->mem+p), count); //内核空间拷贝至用户空间 *ppos += count;
测试用应用代码如下:
#include#include #include #include void main(){ int fd,num; fd = open("/dev/globalmem", O_RDWR); if(fd != -1){ read(fd, &num, sizeof(int)); printf("the globalmem is %d\n", num); scanf("%d", &num); printf("the input is %d\n", num); write(fd, &num, sizeof(int)); read(fd, &num, sizeof(int)); printf("the new globalmem is %d/n", num); close(fd); }else{ printf("device err!"); } return;}