struct file
, defined in <linux/fs.h>
, is the
second most important data structure used in device drivers. Note
that a file
has nothing to do with the FILE
s of
user-space programs. A FILE
is defined in the C library and never
appears in kernel code. A struct file
, on the other hand, is a kernel
structure that never appears in user programs.
The file
structure represents an ``open file.'' It is
created by the kernel on open and is passed to any function
that operates on the file, until close. After the file is
closed, the kernel releases the data structure. An ``open file'' is
different from a ``disk file,'' which is represented by struct inode
.
In the kernel sources, a pointer to struct file
is usually
called either file
or filp
(``file
pointer''). I’ll consistently
call the pointer filp
to prevent ambiguities with the structure
itself--filp
is a pointer (as such, it is one of the arguments to device
methods), while file
is the structure itself.
The most important fields of struct file
are shown below.
As in the previous section, the list can be skipped on a first
reading. In the next section though, when we face some real C code,
I’ll discuss some of the fields, so they are here for you to
refer back to.
mode_t f_mode;
The file mode is identified by the bits
FMODE_READ
and FMODE_WRITE
. You might want to
check this field for read/write permission in your ioctl
function, but you don’t need to check permissions for
read and write because the kernel checks
before invoking your driver. An attempt to write without
permission, for example, is rejected without the driver
even knowing about it.
loff_t f_pos;
The current reading or writing position. loff_t
is
a 64-bit value (long long
in gcc
terminology). The driver can read this value if it needs to know
the current position. The lseek method, if defined, should
update the value of f_pos
. The read and write
methods should update it when transferring data.
unsigned short f_flags;
These are the file flags, such as O_RDONLY
,
O_NONBLOCK
, and O_SYNC
. A driver needs
to check the flag for nonblocking operation, while the other
flags are seldom used. In particular, read/write permission
should be checked using f_mode
instead of
f_flags
. All the flags are defined in
the header <linux/fcntl.h>
.
struct inode *f_inode;
The inode associated with the open file. The inode
pointer is the first argument passed by the kernel to all
file operations, so you don’t usually need to access the
field in file
. In those cases when you have access only to a
struct file
, you can find the corresponding inode
here.
struct file_operations *f_op;
The operations associated with the file. The kernel
assigns the pointer at open time and then reads it
when it needs to dispatch
any operations. The value in filp->f_op
is
never saved for later reference; this means that you can
change the file operations associated with your file whenever
you want, and the new methods will be effective the next time
a method is invoked for that open file. For example, the
code for open associated with major number 1
(/dev/null
, /dev/zero
, and so on) substitutes
the operations in filp->f_op
depending on which minor
number is being opened. This practice makes it possible to
distinguish between devices with the same major number without
introducing overhead at each system call. The
ability to replace the file operations is called
``method overriding'' in object-oriented programming.
void *private_data;
The open system call sets this pointer to
NULL
before calling the open method for the
driver. The driver is free to make its own use of the field
or to ignore it. The driver can use the field to point to
allocated data, but then must clear it again in the
release method before the
file
structure is destroyed by the kernel.
private_data
is a great resource for preserving state
information across system calls and is used by most
of our sample modules.
The real structure has a few more fields, but they aren’t useful to
device drivers. We can safely ignore those fields because drivers never
fill file
structures; they only access structures created
elsewhere.
18.223.172.252