user2948075
user2948075

Reputation:

Linux device driver read write functions issue

I'm writing sample device driver to read and write using cyclic buffer, it means the last node point to the first one. I created the linked list of 10 block, each block buffer size = 5.

now on my write function, when I call write method, it write in the buffer, check if it's filled, then jump to the other one, the next write will write in the current buffer + offset defined in lnod struct . same thing for read.

when I run the echo command twice

echo 123456789 > /dev/driver
echo abcd > /dev/driver

according to the write and read function below the cat command will give123456789abcd as result since the second write will continue on the offset, so the read function will read all the size_to_read, but the cat (called 3 times)command gave me this :

cat /dev/driver 
abcd
6789
abcd

some usefull code parts:

static int BlockNumber = 10;
static int BlockSize = 5;

static int size_to_read = 0;

data buffer structure

 typedef struct dnode
 {
     int bufSize;
     char *buffer;
     struct dnode *next;
 } data_node;

liste stucture

 typedef struct  lnode
 {
     data_node *head;
     data_node *cur_write_node;
     data_node *cur_read_node;  
     int cur_read_offset;
     int cur_write_offset;
 }liste;

static liste newListe;

the create liste method is called in init function

write function

static ssize_t sample_write_liste(struct file *f, const char *buf, size_t size, loff_t *offset) 
{
    if (*(offset) == 0)  
    {
        size_to_read += size;
    }
    int size_to_copy;
    size_to_copy = MIN (size, BlockSize - newListe.cur_write_offset);
    copy_from_user(newListe.cur_write_node->buffer + newListe.cur_write_offset, buf, size_to_copy);
    *(offset) += size_to_copy;
    newListe.cur_write_offset +=  size_to_copy;
    if (newListe.cur_write_offset == BlockSize) 
    {
      newListe.cur_write_node = newListe.cur_write_node->next;
      newListe.cur_write_offset = 0;  // we erase previous things
    }
    return size_to_copy;
}

the read function

static ssize_t sample_read_liste(struct file *f, char *buf, size_t size, loff_t *offset)
{
    int size_to_copy;
    size_to_copy = MIN (size_to_read - *(offset), BlockSize - newListe.cur_read_offset);
    copy_to_user(buf, newListe.cur_read_node->buffer + newListe.cur_read_offset,size_to_copy);
    newListe.cur_read_offset += size_to_copy;
    (*offset)+=size_to_copy; 

    if (newListe.cur_read_offset == BlockSize) 
    {
        newListe.cur_read_node = newListe.cur_read_node->next;
        newListe.cur_read_offset = 0;
    }
    return size_to_copy;  
}

create linked list function

static void createlist (void) {
    data_node *newNode, *previousNode, *headNode;
    int i;
    /* new node creation  */
    newNode = (data_node *)kmalloc(sizeof (data_node), GFP_KERNEL);
    newNode->buffer = (char *)kmalloc(BlockSize*sizeof(char), GFP_KERNEL);
    newNode->next = NULL;

    newListe.head = newNode;
    headNode = newNode;
    previousNode = newNode;


    for (i = 1; i < BlockNumber; i++)
    {
        newNode = (data_node *)kmalloc(sizeof (data_node), GFP_KERNEL);
        newNode->buffer = (char *)kmalloc(BlockSize*sizeof(char), GFP_KERNEL);
        newNode->next = NULL;
        previousNode->next = newNode;
    }
    /* cyclic liste : we should tie the last element to the first one (head) */
    newNode->next = headNode;

    newListe.cur_read_node = headNode;
    newListe.cur_write_node = headNode;
    newListe.cur_read_offset = 0;
    newListe.cur_write_offset = 0;
}

Upvotes: 1

Views: 1489

Answers (1)

toyoubala
toyoubala

Reputation: 71

In the createlist() routine , in the for loop, you need to add the follwoing line to make a circular list. previousNode = newNode; Your existing createlist would create a circular list with just two nodes.

for (i = 1; i < BlockNumber; i++)
{
    newNode = (data_node *)kmalloc(sizeof (data_node), GFP_KERNEL);
    newNode->buffer = (char *)kmalloc(BlockSize*sizeof(char), GFP_KERNEL);
    newNode->next = NULL;
    previousNode->next = newNode;
    previousNode = newNode  //Please add this line to make the list circular.
}

Upvotes: 1

Related Questions