【问题标题】:Handling multiple device files having same major number but unique minor number处理具有相同主编号但唯一次编号的多个设备文件
【发布时间】:2016-05-22 22:09:50
【问题描述】:

我是 Linux 内核模块编程的新手,并且已经编写了一个虚拟字符设备驱动程序来读取和写入虚拟设备(它实际上是其文档中给出的示例程序)。当我只用一个设备文件尝试它时程序运行良好,当我创建第二个具有相同主编号但不同次编号的虚拟设备文件时出现问题(按顺序,即1)。当我写入一个文件(比如 devfile0、major : 250minor : 0)时,数据也会写入另一个文件(比如 devfile1、major : 250minor : 1),但我只想写入 devfile0 不要 devfile1。是否可以?我可能做错了什么?

这是我创建的内核模块:

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/cdev.h>
#include<linux/fs.h>
#include<linux/semaphore.h>
#include<asm/uaccess.h>
#include<linux/kmod.h>

struct cdev *newDev;
int maj_no;
int ret;
dev_t crdev;
#define DEVICE_NAME "CryptoDevCHARDEVDRVR" 
struct dummy{
    char string[100];
    int length;
    struct semaphore sem;
    }device;

int device_open(struct inode *node,struct file *fp)
{
    printk(KERN_ALERT "Atempting to open device file\n");
    if(down_interruptible(&device.sem) != 0)
    {
        printk(KERN_ALERT "%s : Unable to Lock file while open\n",DEVICE_NAME);
        return -1;
    }
    printk(KERN_ALERT "File open operation Complete\n");
    return 0;
}

ssize_t device_read(struct file* fp,char* buffer, size_t bufsize, loff_t* buffoff)
{
    printk(KERN_ALERT "Reading from the device...\n");
    ret = copy_to_user(buffer,device.string,bufsize);
    device.length = bufsize;
    return ret;
}

ssize_t device_write(struct file* fp,const char* buffer, size_t bufsize, loff_t* buffoff)
{
    printk(KERN_ALERT "Writing to the device...\n");
    ret = copy_from_user(device.string,buffer,bufsize);
    printk(KERN_ALERT "%s\n",device.string);
    printk(KERN_ALERT "Written\n");
    device.length = bufsize;
    return ret;
}

int device_close(struct inode* node, struct file* fp)
{
    printk(KERN_ALERT "Closing Device File");
    up(&device.sem);
    printk(KERN_ALERT "Device Close Successfully");
    return 0;
}

struct file_operations fop = {
    .owner = THIS_MODULE,
    .open = device_open,
    .release = device_close,
    .read = device_read,
    .write = device_write
};


static int hello_init(void)
{
    ret = alloc_chrdev_region(&crdev,0,50,DEVICE_NAME);
    if(ret < 0)
    {
        printk(KERN_ALERT "\n%s : Unable to assign Character Device Driver Region",DEVICE_NAME);
        return ret;
    }
    maj_no = MAJOR(crdev);
    printk(KERN_ALERT "%s : Major Number:%d\n",DEVICE_NAME,maj_no);
    newDev = cdev_alloc();
    newDev->ops = &fop;
    newDev->owner = THIS_MODULE;
    ret = cdev_add(newDev,crdev,50);
    if(ret < 0)
    {
        printk(KERN_ALERT "%s : Unable to Register Device Driver\n",DEVICE_NAME);
    }
    sema_init(&device.sem,1);
    printk(KERN_ALERT "Successfully Initialised Device Driver\n");
    printk(KERN_ALERT "Test caller");
    return 0;
}

static void hello_destroy(void)
{
    printk(KERN_ALERT "Killing Hello-Start.c ... Byeeee\n");
    cdev_del(newDev);
    unregister_chrdev_region(crdev,50);
    printk(KERN_ALERT "%s : Successfully Unregistered Driver\n",DEVICE_NAME);
    printk(KERN_ALERT "Done");
}

module_init(hello_init);
module_exit(hello_destroy);

用户空间应用程序使用open syscall 打开devfile0 和write syscall 写入devfile0。
这是代码:

fp = open(DEVICE , O_RDWR);
if(fp == -1)
{
    printf("%s cann't be accessed right now try after sometime\n",DEVICE);
    exit(-1);
}

printf("Enter any Character String to transmit to Device:");
            fgets(buff,100,stdin);
            write(fp,buff,sizeof(buff));
            printf("\nWritten: %s\n",buff);

【问题讨论】:

  • 因此,您需要创建多个底层缓冲区,每个您分配的设备一个。 That question 描述了如何区分设备和文件操作。

标签: c linux linux-kernel kernel-module


【解决方案1】:

主设备号告诉您使用哪个驱动程序访问 硬件。每个驱动程序都分配有一个唯一的主要编号;所有设备 具有相同主编号的文件由相同的驱动程序控制。 以上所有主要数字都是3,因为它们都被控制 同一个司机。

驱动程序使用次要编号来区分 它控制的各种硬件。回到上面的例子,虽然 所有三个设备都由它们具有唯一性的相同驱动程序处理 次要数字,因为驾驶员将它们视为不同的部分 硬件。

来自The Linux Kernel Module Programming Guide,3.1.6.1。主要和次要数字

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 2010-12-21
    • 2020-04-16
    • 2016-08-30
    • 2020-07-21
    相关资源
    最近更新 更多