Issue
I am reading the LDD3, and I would like to understand how the device driver file operations are called at the time a system call is performed.
From my understanding, when the open system call is performed, the struct file *filp
gets its f_op
attribute populated from the inode's i_fop
.
But when/where does the inode get its i_fop
attribute populated with the cdev
's ops
attribute?
My intuition is that when we call cdev_add
in the driver, our device is added to the cdev_map
with the MAJOR and MINOR numbers, but the inode is not yet linked to the character device. The inode would only be linked either when mknod
is called to create the device file in the /dev
directory, or when the device file is opened through the syscall.
Solution
The struct inode
's i_fop
member gets set to &def_chr_fops
(in "fs/char_dev.c") for character special files by the init_special_inode()
function (in "fs/inode.c"). That is called by the underlying filesystem (e.g. when it is populating its directory structures and inodes when mounted or when a new character special file is created in the filesystem by mknod()
.
When opening the file, the struct inode
's i_fop
is copied to the struct file
's f_op
member by the do_dentry_open()
function called from the vfs_open()
function (in "fs/open.c"). do_dentry_open()
calls the open
file operation handler. For character special files, the open
file operation handler from def_chr_fops
is the chrdev_open()
function (in "fs/char_dev.c").
The chrdev_open()
function looks up the struct cdev
(if any) associated with the MAJOR/MINOR device number (from the inode's i_rdev
member), copies the ops
member from the struct cdev
to the struct file
's f_op
member to replace the file operations, and calls the replacement open
handler if there is one.
Answered By - Ian Abbott Answer Checked By - Senaida (WPSolving Volunteer)