Quantcast
Channel: Active questions tagged kernel-modules - Unix & Linux Stack Exchange
Viewing all articles
Browse latest Browse all 1184

Linux character device driver won't respond to head command

$
0
0

I am writing a LKM to create a character device driver.

Linux Kernel: 4.4.0-93-generic in VirtualBox, 2GB ram and SWAP is 300Kb

Problem 1

If I write a C program that handles the fd in dev_write, it's all good, it reads as it should, but if I try to use head -n 1 < /dev/opsysmem it does not output anything.

Problem 2

If I repeatedly send a message big enough, everything is fine, my 2MiB buffer fills up and then the following messages are discarded. However, if the message is smaller (i.e 1 char each), it stops after about 10000 nodes. Is this a problem with my implementation of the linked list, a known linux problem or it's just me not observing something in my code?

When I encounter Problem 2, the vCPU throttles in sinusoidal manner

Here are my functions for read, write:

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
    Node *msg;
    int ret_val;
    char* message;
    unsigned int message_length;

    // Entering critical section
    down(&sem); //wait state

    msg = pop(&l, 0);

    // No message? No wait!
    if(!msg) {
        up(&sem);
        return -EAGAIN;
    }

    message_length = msg->length;

    // Debug only
    if(DEBUG) {
        message = (char*) kmalloc(message_length + 1, GFP_KERNEL);
        memset(message, 0, message_length + 1);
        memcpy(message, msg->string, message_length);
        if(DEBUG) {
            printk(KERN_INFO "The message is: %s", message);
        }
        kfree(message);
    }

    // Since we have a message, let's send it!
    current_size -= message_length;

    if(DEBUG) {
        printk(KERN_INFO "List size decreased by :%u (bytes); current: %d \n",  msg->length, current_size);
    }

    // copy_to_user has the format ( * to, *from, size) and returns 0 on success
    ret_val = copy_to_user(buffer, msg->string, message_length);

    if (!ret_val) {
        remove_element(&l, 0);
        up(&sem);
        return ret_val;
    } else {
        up(&sem);
        if(DEBUG) {
            printk(KERN_INFO "opsysmem: Failed to send characters to the user\n");
        }
        return -EFAULT; // Failed -- return a bad address message (i.e. -14)
    }
}


static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
    // buffer larger than 2 * 1024 bytes
    if(len > MAX_MESSAGE_SIZE) {
        return -EINVAL;
    }

    // Enter critical section
    down(&sem); //wait state

    msleep(10000);
    // buffer is larger than the total list memory (2MiB)
    if(current_size + len > MAX_LIST_SIZE) {
        down(&sem);
        return -EAGAIN;
    }

    current_size += len;
    if(DEBUG) {
        printk(KERN_INFO "Current list size %d \n", current_size);
    }
    push(&l, buffer, len);

    up(&sem);
    // Exit critical section

    return len;
}

And here is my linked list

typedef struct Node {
    unsigned int length;
    char* string;
    struct Node *next;
} Node;

typedef struct list{
    struct Node *node;
} list;

Viewing all articles
Browse latest Browse all 1184

Trending Articles



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