Reputation: 53
I'm trying to implement a char device driver in Linux driver. When I try to echo strings into my driver, the result is very weird.
My code to store the strings I input:
int max_size = 1;
char store[1] = {0};
char message[100] = {0};
ssize_t hello_write(struct *filep, const char *buffer, size_t length, loff_t *position)
{
if(length> max_size)
length = max_size;
if(copy_from_user(message, buffer, length))
return -EFAULT;
strncpy(store, message, max_size);
printk(KERN_INFO "Actually stored in kernel:%s", store);
return max_size;
}
ssize_t hello_read(struct file *filep, char *buffer, size_t length, loff_t *postion)
{
int error_count = 0;
error_count = copy_to_user(buffer, store, max_size);
if(error==0){
printk(KERN_INFO "read message from kernel: %s", store);
return 0;
}
else{
printk(KERN_INFO "failed to send %d chars to user", error_count);
return -EFAULT;
}
}
Test:
echo ginger > /dev/test cat /dev/test
I intend to store only the first letter of each input string, anything with the function strncpy
?
Upvotes: 0
Views: 477
Reputation: 65928
Value returned by write
syscall is interpreted as number of bytes processed.
Like other standard output utilities echo
calls write()
syscall repeatedly until it processes all input bytes.
So, when you want to store only single byte of the input, you need to return input's full length for mark it as processed.
More correct implementation of .write
would be:
ssize_t hello_write(struct *filep, const char * __user buffer, size_t length, loff_t *position)
{
if((*position == 0) && (length > 0)) {
// Store the first byte of the first input string.
if(copy_from_user(message, buffer, 1))
return -EFAULT;
strncpy(store, message, 1);
}
printk(KERN_INFO "Actually stored in kernel:%s", store);
// But mark the whole string as processed
*position += length;
return length;
}
Upvotes: 2