I am reading android kernel code and I'm facing this kind of data structures ,
static const struct file_operations tracing_fops = {
.open = tracing_open,
.read = seq_read,
.write = tracing_write_stub,
.llseek = tracing_seek,
.release = tracing_release,
};
can someone explain this syntax generally ? right side of equations are functions names and &tracing_fops later is passed as an argument to another function that inits debugfs file system.
Contrary to what younger developers, or people coming from C believe at first, a struct can have constructors, methods (even virtual ones), public, private and protected members, use inheritance, be templated… just like a class .
file->private_data will always return a pointer to the device. Another question related to this is the field "f_pos". The book says that the driver can read this value if it wants to know the current position in the file.
Member functions inside the structure: Structures in C cannot have member functions inside a structure but Structures in C++ can have member functions along with data members.
From what I think I've understood, task_struct is the C structure that acts as the process descriptor, holding everything the kernel might need to know about a processes. At the end of the process kernel stack lives another struct, thread_info , which has a pointer to the processes task_struct .
The assignment is an example of using Compund Literals. According to C99 Section #6.5.2.5:
A postfix expression that consists of a parenthesized type name followed by a brace- enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.
In simpler version, according to GCC docs: Compound literals:
A compound literal looks like a cast of a brace-enclosed aggregate initializer list. Its value is an object of the type specified in the cast, containing the elements specified in the initializer. Unlike the result of a cast, a compound literal is an lvalue. ISO C99 and later support compound literals. As an extension, GCC supports compound literals also in C90 mode and in C++, although as explained below, the C++ semantics are somewhat different.
An simple example:
struct foo { int x; int y; };
func() {
struct foo var = { .x = 2, .y = 3 };
...
}
In the question's example, the struct file_operations
is defined in include/linux/fs.h and tracing_fops
is in kernel/trace/trace.c file in Linux source tree.
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
...
};
The open
, read
, write
are Function Pointers which are pointers that points to a function. After dereferencing the function pointer, it can be used as normal function call. The tracing_fops
structure is file_operations
type. The values of function pointer members are assigned to the functions in the same trace.c
file using compound literals.
With compound literals, we don't have to explicitly specify/assign all members in the structure type because other members are set to zero or null. Structure objects created using compound literals can be passed to functions without depending on member order. The function parameters should be same for both side. For example, the parameters of
int (*open) (struct inode *, struct file *);
is same as
int tracing_open(struct inode *inode, struct file *file);
In object oriented programming, this idea is somewhat similar as Virtual Function Table.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With