打印

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

[复制链接]
159|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
张さん|  楼主 | 2018-8-22 09:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1. 对于驱动程序中有两个关键的结构体:struct file *filp:

    有一个关键的成员 -> void *private_data,用于存放用于私人的数据

inode:

    有一个关键的成员 -> unsigned int i_flags



2. 一个驱动多个设备的程序思路: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 下的设备,访问不同的用户数据



3. 程序:

char_multi_dev.c

[cpp] view plain copy

print?<img id="aimg_b5595"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_v8f00"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />



#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

print?<img id="aimg_Gep5u"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_WD7RD"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />



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

print?<img id="aimg_rYfT2"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_UPcgc"  class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />



#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

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

448

主题

464

帖子

1

粉丝