Tags: vfs
"Interface" in C
By MD on Feb 27, 2008 | In Ease Of Use | Send feedback »
Recently, I began to study C programming language. I used to be a Java guy, but have felt like doing that to contribute to any serious device projects here in Japan.
Java is new, object oriented language. But C is old, not object oriented.
What made me surprised was that I couldn't find a way to cut a dependency. I can define a template, but they are exposed in terms of "coupling" object oriented concept.
Before diving into C world, to avoid such a "spagetti", I would like to get a gut feeling about dependency management.
Then, I have investigated Linux VFS(Virtual File System) design. A file system in Linux is well abstracted, so must have a good design in C.
"The VFS is object-oriented. A family of data structures represents the common file model. There data structures are akin to objects. Because the kernel is programmed strictly in C, without the benefit of a language directly supporting object-oriented paradigms, the data structures are represented as C structures. The structures contain both data and pointers to filesystem-implemented functions that operate on the data." - page212, Linux Kernel Development Second Edition, Robert Love
Ah-ha, a strucrue could be used like an interface... OK, let's nail down the source. Here's a code snippet from linux/fs.c.
struct super_block {
...
struct super_operations *s_op;
...
};
Methods look defined as an interface. So what about super_operations?
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);void (*read_inode) (struct inode *);
void (*dirty_inode) (struct inode *);
int (*write_inode) (struct inode *, int);
void (*put_inode) (struct inode *);
void (*drop_inode) (struct inode *);
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
void (*write_super_lockfs) (struct super_block *);
void (*unlockfs) (struct super_block *);
int (*statfs) (struct super_block *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);...
};
Mmmm, something looks strange. I wonder why they have an argument of its body, "struct super_block *" or "struct inode *".
Yes, because there is no such a thing like "instance" in C. So you can not access to an instance inside a method body, like "this" in Java. This is a bit strange, but still OK.
Yet wait, passing itself to methods mean that an interface(operations struct) depends on its concrete type! That's too bad... Its implementation can be abstracted, but not like an interface to cut dependencies.
How can I put an abstraction with an interface to cut dependencies?
I found a way to do that with a generic pointer. I am trying to test "List" interface Java design in C. Performance may matter, but still look promissing. Let's see...