I am trying to read and write to a char driver. When i use a C program to open the device file and read and write it gives a SEG fault. When I use a cat to the device file it goes to infinite loop.
1) What am I missing, and what is the correct implementation of read and write in file_operations?
2) I know in prototype read/write: read(struct file *fp, char *ch, size_t count, loff_t *lofft)
count refers to number of bytes read/write request. But what is the last parameter offset used for and what are the checks needs to be made for offset?
3) For multiple read calls like cat /dev/chardriver
will the offset be incremented for each read? Like 1st read call offset from 1 to 100 for count=100, in next read call will the offset go from 101? Or will it go from any random number?
Here is my code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
char kernelbuff[1024];
MODULE_LICENSE("GPL");
struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
int device_open(struct inode *inode, struct file *fp)
{
printk("device_open called");
return 0;
}
static int device_release(struct inode *inode, struct file *fp)
{
printk("device_release called");
return 0;
}
static ssize_t device_read(struct file *fp, char *ch, size_t sz, loff_t *lofft)
{
printk("device_read called");
copy_to_user(ch, kernelbuff, 1024);
return sz;
}
static ssize_t device_write(struct file *fp, const char *ch, size_t sz, loff_t *lofft)
{
printk("device_write called");
copy_from_user(kernelbuff, ch, 50);
return 1024;
}
static int hello_init(void)
{
printk("basicchardriver: module initialized");
register_chrdev(500, "chr_device", &fops);
return 0;
}
static void hello_exit(void)
{
printk("basicchardriver: module exited");
unregister_chrdev(500, "chr_device");
}
module_init(hello_init);
module_exit(hello_exit);
}
To test:
sudo mknod -m 666 /dev/chardev c 500 0
echo "Hello World">> /dev/chardev ===> Works fine
cat /dev/chardev ===> Goes to infinite loop
If i call the driver using a C program it gives SEG fault:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd;
char buff[500];
fd = open("/dev/chardev", O_RDWR);
write(fd, "Hello World", 13);
read(fd, buff, 500);
printf("Reading data from kernel: \t");
puts(buff);
return 0;
}
raj@raj-VirtualBox:~/device-driver/chardriver/read-write$ ./a.out
Reading data from kernel: Hello World
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)