I'm designing a device driver that simply reads and writes to a character buffer. My question is however regarding the two functions in the file_operations
structure read
and write
. I don't truly understand what loff_t *offp
really is. I know that for both the read and write operations that *offp
is the file offset meaning the current reading/writing position of the file, however I'm not even sure what it means to write or read to/from a device file.
From what I gathered, and this is how I am writing and reading from my device is that I create a structure which represents my device which I call my_char_struct
which is shown bellow.
struct my_char_structure{
struct cdev my_cdev;
struct semaphore sem;
char *data;
ssize_t data_size;
unsigned int access_key;
unsigned long size;
};
This is a static structure that is initialized and pointed to when my driver is insmod
as such.
static dev_t dev_num;
static struct my_char_structure Dev;
int start_mod(void){
//Because we are dealing with a fictitious device, I want
//the driver to create my two devices with arbitrarily
//assigned major numbers.
struct my_char_structure *my_dev = &Dev;
int err;
alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);
sema_init(&(my_dev->sem),1);
cdev_init(&(my_dev->my_cdev), &fops);
my_dev->my_cdev.owner = THIS_MODULE;
my_dev->my_cdev.ops = &fops;// fops is my file operations struct
err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);
if(err<0)
printk(KERN_ALERT "There was an error %d.",err);
printk(KERN_ALERT " insmod to major number %d",MAJOR(dev_num));
return 0;
}
module_init(start_mod);
When my device is open, I just make a pointer for the file open to point to that static structure that I've set up during module_init(start_mod)
as such ...
int dev_open(struct inode *in_node, struct file *filp){
static struct my_char_structure *my_dev;
my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);
printk(KERN_ALERT "The device number is %d",iminor(in_node));
if(!my_dev)
printk(KERN_ALERT "something didn't work. my_dev not initialized.");
filp->private_data = my_dev;
return 0;
}
What my read and write methods do is modify that initial structure Dev, that I've pointed to with my open files. Whatever I copy_to_user
from my structure is what the user considers been written to the device and whatever I copy_from_user
the user thinks they're writing. But beyond changing my initial structure Dev, the idea of file position or offset doesn't make sense unless it refers to a pointer to buffered memory within the kernel for some arbitrary structure or type. Thats the only interpretation that I have for the file offset ... is this correct? Is that what the loff_t *offp
here refers to?
write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
(given my understanding is correct) When some file_operation such as read/write is called and I hadn't set *offp
personally, what is loff_t *offp initially set to?
If in the last file_operation offp = some_arbitrary_address(because I told it so), is that what the offp would be set to when this operation is called again?
What happens if I have other file_opens operations running, will it set to what the last file_operation left it as, or will it keep a tab of which file_open operation it used and replace *offp to what the file_open had it at?
The concept of a char device is too abstract for me when it seems that the device itself doesn't even store the information like a file should, but rather its the driver that saves the information. I hope I've explained my fogginess and I'll clear up anything that I seem ambiguous about.
See Question&Answers more detail:
os