一个驱动程序对应多个设备

版权声明:本文为博主原创文章,欢迎转载,请尊重原创,转载注明链接。 https://blog.csdn.net/qqliyunpeng/article/details/52387525
目录(?)[+]
1. 对于驱动程序中有两个关键的结构体:

struct file *filp:
有一个关键的成员 -> void *private_data,用于存放用于私人的数据
inode:
有一个关键的成员 -> unsigned int i_flags

  1. 一个驱动多个设备的程序思路:

1个驱动程序,
1个struct file_operations 结构体
2个用户结构体数据(包含 struct cdev 结构体)
在 struct file_operation 结构体的 open 方法中根据 inode 结构体中的 i_cdev 成员找到 包含 cdev 的整个结构体,从而能在read/write中能够操作这个结构体的其他成员,具体如下:
在 open 中 将得到的 cdev 通过 struct file 结构体中的private_data 传递给 read/write 方法:
filp->private_data = dev;
当然设备号和设备节点都是两个,通过访问不同的 /dev 下的设备,访问不同的用户数据

  1. 程序:
char_multi_dev.c
[cpp] view plain copy
#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/init.h>  
#include <linux/fs.h>  
#include <linux/cdev.h>  
#include <asm/uaccess.h>  
#include <linux/device.h>  

MODULE_LICENSE ("GPL");  

int hello_major       = 250;  
int hello_minor       = 0;  
int number_of_devices = 2;  
struct class *my_class;  

struct hello_device  
{  
    char data[128];  
    struct cdev cdev;  

} hello_device[2];  


static int hello_open (struct inode *inode, struct file *filp)  
{  
    struct hello_device *dev = container_of(inode->i_cdev, struct hello_device, cdev);   

    filp->private_data = dev;  
    printk (KERN_INFO "Hey! device opened\n");  

    return 0;  
}  

static int hello_release (struct inode *inode, struct file *filp)  
{  
    printk (KERN_INFO "Hmmm... device closed\n");  

    return 0;  
}  

ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp)  
{  
    ssize_t result = 0;  
    struct hello_device *dev = filp->private_data;  

    if (count < 0) return -EINVAL;  
    if (count > 127) count = 127;  
    if (copy_to_user (buff, dev->data, count))   
    {  
        result = -EFAULT;  
    }  
    else  
    {  
        printk (KERN_INFO "wrote %d bytes\n", (int)count);  
        result = count;  
    }  

    return result;  
}  

/* 
 *ssize_t hello_write (struct file *filp, const char  *buf, size_t count, 
 *        loff_t *f_pos) 
 *{ 
 *    ssize_t ret = 0; 
 * 
 *    printk (KERN_INFO "Writing %d bytes\n", count); 
 *    if (count > 127) return -ENOMEM; 
 *    if (count < 0) return -EINVAL; 
 *    if (copy_from_user (data, buf, count)) { 
 *        ret = -EFAULT; 
 *    } 
 *    else { 
 *        data[count] = '\0'; 
 *        printk (KERN_INFO"Received: %s\n", data); 
 *        ret = count; 
 *    } 
 * 
 *    return ret; 
 *} 
 */  


struct file_operations hello_fops = {  
    .owner = THIS_MODULE,  
    .open  = hello_open,  
    .release = hello_release,  
    .read  = hello_read,  
    /*  .write = hello_write */  
};  

static void char_reg_setup_cdev (struct cdev *cdev, dev_t devno)  
{  
    int error;  

    cdev_init (cdev, &hello_fops);  
    cdev->owner = THIS_MODULE;  
    error = cdev_add (cdev, devno , 1);  
    if (error)  
        printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);  
}  

static int __init hello_2_init (void)  
{  
    int result;  
    dev_t devno;  

    devno = MKDEV (hello_major, hello_minor);  
    result = register_chrdev_region (devno, number_of_devices, "hello_multi");  

    if (result < 0) {  
        printk (KERN_WARNING "hello: can't get major number %d\n", hello_major);  
        return result;  
    }  
    my_class = class_create(THIS_MODULE,"multi_dev_class");  
    if(IS_ERR(my_class))   
    {  
        printk("Err: failed in creating class.\n");  
        return -1;   
    }  
    device_create(my_class,NULL, devno, NULL, "multi_dev0");  
    device_create(my_class,NULL, devno + 1, NULL, "multi_dev1");  

    char_reg_setup_cdev (&hello_device[0].cdev, devno);  
    char_reg_setup_cdev (&hello_device[1].cdev, devno+1);  
    printk (KERN_INFO "char device registered\n");  
    strcpy(hello_device[0].data, "0000000000000000000");  
    strcpy(hello_device[1].data, "1111111111111111111");  

    return 0;  
}  

static void __exit hello_2_exit (void)  
{  
    dev_t devno = MKDEV (hello_major, hello_minor);  

    cdev_del (&hello_device[0].cdev);  
    cdev_del (&hello_device[1].cdev);  

    device_destroy(my_class, devno);         // delete device node under /dev//必须先删除设备,再删除class类  
    device_destroy(my_class, devno + 1);     // delete device node under /dev//必须先删除设备,再删除class类  
    class_destroy(my_class);                 // delete class created by us  
    unregister_chrdev_region (devno, number_of_devices);  
    printk("char device exited\n");  
}  

module_init (hello_2_init);  
module_exit (hello_2_exit);  
关键点是 96行 和 98行
对 container_of 函数的理解请看:http://blog.csdn.net/boygrass/article/details/9962161?locationNum=1

Makefile
[python] view plain copy
ifeq ($(KERNELRELEASE),)  

KERNELDIR ?= /lib/modules/$(shell uname -r)/build   
#KERNELDIR ?= ~/wor_lip/linux-3.4.112  
PWD := $(shell pwd)  

modules:  
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  

modules_install:  
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install  

clean:  
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules* Module*  

.PHONY: modules modules_install clean  

else  
    obj-m := char_multi_dev.o  
endif  

test.c
[cpp] view plain copy
#include <stdio.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  

int main (void)   
{  
    int fd1, fd2;  
    char buf[64];  

    if ((fd1 = open ("/dev/multi_dev0",O_RDONLY)) < 0)  
    {  
        perror("fail to open");  
        return -1;  
    }  
    if ((fd2 = open ("/dev/multi_dev1",O_RDONLY)) < 0)  
    {  
        perror("fail to open");  
        return -1;  
    }  

    read(fd1, buf, 64);  
    printf("read from device0 : %s\n", buf);  
    read(fd2, buf, 64);  
    printf("read from device1 : %s\n", buf);  

    return 0;  
}  

结果:
>sudo insmod char_multi_dev.ko 
>sudo ./a.out 
read from device0 : 0000000000000000000
read from device1 : 1111111111111111111
>sudo rmmod char_multi_dev
>dmesg
[11074.012373] char device registered
[11087.349961] Hey! device opened
[11087.349965] Hey! device opened
[11087.349967] wrote 64 bytes
[11087.350021] wrote 64 bytes
[11087.350055] Hmmm... device closed
[11087.350057] Hmmm... device closed
[11115.543117] char device exited
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值