2

I am new to Linux Kernel Module Programming and have written a dummy character device driver to read and write to a dummy device (it is actually a sample program given in its documentation). The program runs fine when I try it with only one device file, the problem arises when I create a second dummy device file with same major number but different minor number (in sequence i.e, 1). When I write to one file (say devfile0, major : 250, minor : 0) the data is also written to the other file (say devfile1, major : 250, minor : 1) but I just want to write to devfile0 and not to devfile1. Is it possible? What am I possibly doing wrong?

Here is the kernel module I have created:

#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);

Userspace application uses open syscall to open devfile0 and write syscall to write to devfile0.
Here is the code for that:

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);
red0ct
  • 4,840
  • 3
  • 17
  • 44
CryptoRex
  • 76
  • 1
  • 10
  • 1
    So, you need to create several underlying buffers, one per each device you allocate. [That question](http://stackoverflow.com/q/36066635/3440745) describes how differenciate devices from file operations. – Tsyvarev May 23 '16 at 07:46

1 Answers1

-1

The major number tells you which driver is used to access the hardware. Each driver is assigned a unique major number; all device files with the same major number are controlled by the same driver. All the above major numbers are 3, because they're all controlled by the same driver.

The minor number is used by the driver to distinguish between the various hardware it controls. Returning to the example above, although all three devices are handled by the same driver they have unique minor numbers because the driver sees them as being different pieces of hardware.

from The Linux Kernel Module Programming Guide,3.1.6.1. Major and Minor Numbers

23ars
  • 647
  • 3
  • 16
  • 37