Seeking a Device
The difficult part of the chapter is over, and I’ll quickly detail the lseek method, which is useful and easy to implement. Note that the prototype of the method changed slightly in 2.1.0, as detailed in Section 17.2.1, in Chapter 17.
The lseek Implementation
I’ve already stated that if the lseek method is missing from
the device’s operations, the default implementation in the kernel
acknowledges seeks from the beginning of file and from the current
position, by modifying filp->f_pos.
If seeking relative to the end-of-file makes sense for your device, you should offer your own method, which will look like the following code:
int scull_lseek (struct inode *inode, struct file *filp,
off_t off, int whence)
{
Scull_Dev *dev = filp->private_data;
long newpos;
switch(whence) {
case 0: /* SEEK_SET */
newpos = off;
break;
case 1: /* SEEK_CUR */
newpos = filp->f_pos + off;
break;
case 2: /* SEEK_END */
newpos = dev->size + off;
break;
default: /* can't happen */
return -EINVAL;
}
if (newpos<0) return -EINVAL;
filp->f_pos = newpos;
return newpos;
}The only device-specific operation here is retrieving the file
length from the device. For the lseek system call to work
correctly, however, the read and write calls must
cooperate by updating filp->f_pos whenever data is
transferred; they should also use the f_pos field to
locate the data they transfer. The implementation of
scull includes these features, as shown in
Section 3.7 in Chapter 3.
While the implementation shown ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access