Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6501

Read and Write to Char Device in Linux

$
0
0

EDITED Previously I said it became null at device_write but it's actually device_read.

I am trying to write a simple program which read and writes to the character device. The problem I have is "top" pointer of my stack becomes null at the starting of device_read somehow even though "push" is working properly.

This is my stack declaration.

static struct Node {
    char* data;
    struct Node *next;
};

This is my full charDeviceDriver.c code


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>    
#include <charDeviceDriver.h>
#include<linux/slab.h>

MODULE_LICENSE("GPL");

/* 
 * This function is called whenever a process tries to do an ioctl on our
 * device file. We get two extra parameters (additional to the inode and file
 * structures, which all device functions get): the number of the ioctl called
 * and the parameter given to the ioctl function.
 *
 * If the ioctl is write or read/write (meaning output is returned to the
 * calling process), the ioctl call returns the output of this function.
 *
 */


DEFINE_MUTEX  (devLock);

static int counter = 0;
int size = 0;
struct Node* top;



/*
 * This function is called when the module is loaded
 */
int init_module(void)
{
    Major = register_chrdev(0, DEVICE_NAME, &fops);

    if (Major < 0) {
      printk(KERN_ALERT "Registering char device failed with %d\n", Major);
      return Major;
    }

top = NULL;

    printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
    printk(KERN_INFO "the driver, create a dev file with\n");
    printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
    printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
    printk(KERN_INFO "the device file.\n");
    printk(KERN_INFO "Remove the device file and module when done.\n");

    return SUCCESS;
}

/*
 * This function is called when the module is unloaded
 */
void cleanup_module(void)
{
    unregister_chrdev(Major, DEVICE_NAME);
}

/* 
 * Called when a process tries to open the device file, like
 * "cat /dev/mycharfile"
 */
static int device_open(struct inode *inode, struct file *file)
{

    mutex_lock (&devLock);
    if (Device_Open) {
    mutex_unlock (&devLock);
    return -EBUSY;
    }
    Device_Open++;
    mutex_unlock (&devLock);
    sprintf(msg, "I already told you %d times Hello world!\n", counter++);
    msg_Ptr = msg;
    try_module_get(THIS_MODULE);

    return SUCCESS;
}

/* Called when a process closes the device file. */
static int device_release(struct inode *inode, struct file *file)
{
    empty();
    mutex_lock (&devLock);
    Device_Open--;      /* We're now ready for our next caller */
    mutex_unlock (&devLock);
    /* 
     * Decrement the usage count, or else once you opened the file, you'll
     * never get get rid of the module. 
     */
    module_put(THIS_MODULE);

    return 0;
}

/* 
 * Called when a process, which already opened the dev file, attempts to
 * read from it.
 */
static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */
               char *buffer,    /* buffer to fill with data */
               size_t length,   /* length of the buffer     */
               loff_t * offset)
{
    printk(KERN_INFO "INSIDE DEVICE READ\n");
    char* msgTemp = (char*)kmalloc(sizeof(char)*length,GFP_USER);

    if(!top) {
        printk(KERN_INFO "TOP BEOMES NULL AT DEVICE_READ \n" );
    }

    if(size == 0) {
        printk(KERN_INFO "INSIDE DEVICE READ IF EMPTY LIST");
        return -EAGAIN;
    }
    else {
        printk(KERN_INFO "INSIDE DEVICE READ IF LIST NOT EMPTY");
        msgTemp = pop();
        printk(KERN_INFO "MESSAGE POPPED IS %s", msgTemp);
        if (copy_to_user(buffer,msgTemp,length) == 0) {
            return length;
        }
    }

    return 0;
}

/* Called when a process writes to dev file: echo "hi"> /dev/hello  */
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
    char* msgTemp = (char*)kmalloc(sizeof(char)*len,GFP_USER);

    printk(KERN_ALERT "THIS IS THE STARTING OF DEVICE WRITE.\n");


    if(len > 6144) {
        printk(KERN_ALERT "FIRST IF CONDITION.\n");
        return -EINVAL;
    }
    else if (totalSize() + len > 4 * 1024 * 1024) {
        printk(KERN_ALERT "SECOND IF CONDITION.\n");
        return -EAGAIN;
    }
    else if (copy_from_user(msgTemp,buff,len) == 0) {
        printk(KERN_ALERT "THIRD IF CONDITION.\n");
        printk(KERN_ALERT "WRITTEN MESSAGE IS %s",msgTemp);
        push(msgTemp);
        return len;
    }

    printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
    return EAGAIN;
}

void push(char* dataS)
{
    // char* tempCheck;

    struct Node* newNode = (struct Node*) kmalloc(sizeof(struct Node),GFP_USER);
    newNode->data = dataS;
    newNode->next = top;        
    top = newNode;
    size++;
    printk(KERN_ALERT "THE SIZE IS AFTER PUSHING IS %d.\n",size);
    printk(KERN_ALERT "THE MESSAGE PUSHED IS %s\n",dataS); 
}

char* pop()
{
    printk(KERN_INFO "INSIDE POP METHOD\n");
    char* dataS;
    struct Node* topNode;
    // Check stack underflow
    if (size <= 0 || !top)
    {
        printk(KERN_INFO "INSIDE POP IF METHOD ABOUT UNDERFLOW\n");
        //printf("Stack is empty.\n");

        // Throw empty stack error/exception
        // Since C does not have concept of exception
        // Hence return minimum integer value as error value
        // Later in code check if return value is INT_MIN, then
        // stack is empty
        return NULL;
    }

    topNode = top;
    dataS = top->data;
    top = top->next;
    kfree(topNode);
    size--;
    printk(KERN_INFO "THE ELEMENT THAT GOT POPPED IS %s",dataS);
    return dataS;
}


size_t totalSize()
{

    struct Node* temp;
    size_t total;
    int i;
    temp = top;

    for(i = 0;i<size;i++){
        total += sizeof(*temp->data)/sizeof(char);
        temp = temp -> next;
    }

    return total;
}

void empty()
{  
  struct Node* cur = top;
  struct Node* next;
  while (cur != NULL) {
    next = cur->next;
    kfree(cur);
    cur = next;
  }
  top = NULL;
}

These are my log messages.

log


Viewing all articles
Browse latest Browse all 6501

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>