oo design: device drivers
oo design: device drivers
I have a working fat filesystem driver and a floppy driver. I need a way to connect these two.
My kernel is object oriented, so I have a class Floppy and a class Fat. Floppy allows for reading and writing sectors and Fat allows to find files and folders, provided a Device.
Should Fat be a member of Floppy? Does the device own the fs or the fs own the device? Or perhaps should I user other means to encapsulate both the device and the filesystem?
Thanks for any advices,
Jonathan
My kernel is object oriented, so I have a class Floppy and a class Fat. Floppy allows for reading and writing sectors and Fat allows to find files and folders, provided a Device.
Should Fat be a member of Floppy? Does the device own the fs or the fs own the device? Or perhaps should I user other means to encapsulate both the device and the filesystem?
Thanks for any advices,
Jonathan
Re:oo design: device drivers
Hi,
If done properly this would allow you to use floppies directly ("copy /dev/fd0 image.bin"), and allow normal files to be mounted ("mount image.bin /mnt/tempfloppy -t FAT").
The VFS layer would handle all File IO. For example, if the application does "open ("/mnt/floppy/readme.txt", "r")" you'd end up with:
This is just how I'd do it though - everyone has their own ideas.
Cheers,
Brendan
I'd have a "Virtual File System" layer (or VFS) and a "File IO Interface". The floppy driver would create an entry for each floppy drive in the VFS (e.g. /dev/fd0, /dev/fd1), and the FAT file system driver would mount these. The FAT driver would talk to the VFS layer using normal file IO in order to read from the floppy driver.Jonathan Mcdougall wrote: I have a working fat filesystem driver and a floppy driver. I need a way to connect these two.
If done properly this would allow you to use floppies directly ("copy /dev/fd0 image.bin"), and allow normal files to be mounted ("mount image.bin /mnt/tempfloppy -t FAT").
The VFS layer would handle all File IO. For example, if the application does "open ("/mnt/floppy/readme.txt", "r")" you'd end up with:
- Application asks VFS to open file
VFS checks if file is already open
VFS asks FAT driver for directory information
FAT driver asks VFS to read data from /dev/fd0
VFS asks floppy driver to read data
Floppy driver returns data to VFS
VFS returns data to FAT driver
FAT driver returns the directory information to VFS
VFS checks if the file exists
VFS builds data structure for the file handle being opened
VFS returns status and the new file handle to the applicaton
- Application asks VFS to open file
VFS checks if file is already open
VFS checks if the file exists
VFS builds data structure for the file handle being opened
VFS returns status and the new file handle to the applicaton
This is just how I'd do it though - everyone has their own ideas.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:oo design: device drivers
>> I have a working fat filesystem driver and a floppy driver. I
>> need a way to connect these two.
> I'd have a "Virtual File System" layer (or VFS) and a "File IO
> Interface". The floppy driver would create an entry for each
> floppy drive in the VFS (e.g. /dev/fd0, /dev/fd1), and the FAT
> file system driver would mount these. The FAT driver would
> talk to the VFS layer using normal file IO in order to read from
> the floppy driver.
What do you mean by "normal file IO"? Using the standard
library?
> If done properly this would allow you to use floppies directly
> ("copy /dev/fd0 image.bin"), and allow normal files to be
> mounted ("mount image.bin /mnt/tempfloppy -t FAT").
Ok.
> The VFS layer would handle all File IO. For example, if the
> application does "open ("/mnt/floppy/readme.txt", "r")" you'd
> end up with:
>
> Application asks VFS to open file
> VFS checks if file is already open
> VFS asks FAT driver for directory information
> FAT driver asks VFS to read data from /dev/fd0
> VFS asks floppy driver to read data
> Floppy driver returns data to VFS
> VFS returns data to FAT driver
> FAT driver returns the directory information to VFS
> VFS checks if the file exists
> VFS builds data structure for the file handle being opened
> VFS returns status and the new file handle to the applicaton
I don't really get what's a vfs. It looks like it acts both as a
filesystem (with highlevel functions such as for accessing files)
and as a device driver (such as returning sectors from a floppy).
Am I right?
(I'm thinking while I write)
If I am, could I replicate that using polymorphism: the vfs contains only high-level functions, but also gives access to a Device, which would be a base class for all devices. The Fat driver uses that Device to get its data.
So by doing "ls /dev/fd0/test", the vfs resolves "fd0" to the floppy and then calls the Fat's functions to retrieve the file, providing a reference to the Floppy, being a derived class from Device. Phew :)
What do you think?
Jonathan
>> need a way to connect these two.
> I'd have a "Virtual File System" layer (or VFS) and a "File IO
> Interface". The floppy driver would create an entry for each
> floppy drive in the VFS (e.g. /dev/fd0, /dev/fd1), and the FAT
> file system driver would mount these. The FAT driver would
> talk to the VFS layer using normal file IO in order to read from
> the floppy driver.
What do you mean by "normal file IO"? Using the standard
library?
> If done properly this would allow you to use floppies directly
> ("copy /dev/fd0 image.bin"), and allow normal files to be
> mounted ("mount image.bin /mnt/tempfloppy -t FAT").
Ok.
> The VFS layer would handle all File IO. For example, if the
> application does "open ("/mnt/floppy/readme.txt", "r")" you'd
> end up with:
>
> Application asks VFS to open file
> VFS checks if file is already open
> VFS asks FAT driver for directory information
> FAT driver asks VFS to read data from /dev/fd0
> VFS asks floppy driver to read data
> Floppy driver returns data to VFS
> VFS returns data to FAT driver
> FAT driver returns the directory information to VFS
> VFS checks if the file exists
> VFS builds data structure for the file handle being opened
> VFS returns status and the new file handle to the applicaton
I don't really get what's a vfs. It looks like it acts both as a
filesystem (with highlevel functions such as for accessing files)
and as a device driver (such as returning sectors from a floppy).
Am I right?
(I'm thinking while I write)
If I am, could I replicate that using polymorphism: the vfs contains only high-level functions, but also gives access to a Device, which would be a base class for all devices. The Fat driver uses that Device to get its data.
So by doing "ls /dev/fd0/test", the vfs resolves "fd0" to the floppy and then calls the Fat's functions to retrieve the file, providing a reference to the Floppy, being a derived class from Device. Phew :)
What do you think?
Jonathan
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:oo design: device drivers
what i'd suggest is that you have a reference to a I/O block driver (be it a floppy, an USB key or whatever) passed to the FAT object when it is created.
I guess that should translate quite straightforward to C++ using "pure virtual classes" instead of interfaces (or something alike).
Code: Select all
interface Blocks {
read(block_id, buffer, nb_blocks);
write(block_id, buffer, nb_blocks);
}
class Floppy implements Blocks {
disk_id;
setgeometry(floppy_type) {
...
}
read(...) {
...
}
write(...) {
...
}
}
class AtaHdd implements Blocks { ... }
class ScsiHdd implements Blocks { ... }
interface FileSystem {
bool mount(Blocks device);
DirectoryHandle locate(String path);
}
class FAT implements FileSystem {
...
}
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:oo design: device drivers
Upon mounting a device/partition, I create a vfs object (actually a vnode, which has the root node of the mounted fs attached to it - and a reference to the device driver object (he - just the id of the device driver as well as a kind of minor nr which identifies the actual partition.)
Every call to fs goes throu the vfs layer whch then delegates the grunt work to the fs driver thread for the fs in question. I don't really need what the low level functions for parsing the fs look like as long as they are entered correctly in the fs_driver_t structure. *gg* I've just vnode->drv->schedule(command)
which wakes up the fs driver thread, which carries out the requested task while vfs layer sets off to do something else.
usually this looks like this:
process:read() - vfs->read() - vfs->vnode->attach(command:read) - return.
then there comes:
vfs->vnode->fetch_command() - vfs->vnode->drv->do_readwrite() - vfs->vnode->drv->reply()
then the process is woken up to fetch the reply message from its post box.
Every call to fs goes throu the vfs layer whch then delegates the grunt work to the fs driver thread for the fs in question. I don't really need what the low level functions for parsing the fs look like as long as they are entered correctly in the fs_driver_t structure. *gg* I've just vnode->drv->schedule(command)
which wakes up the fs driver thread, which carries out the requested task while vfs layer sets off to do something else.
usually this looks like this:
process:read() - vfs->read() - vfs->vnode->attach(command:read) - return.
then there comes:
vfs->vnode->fetch_command() - vfs->vnode->drv->do_readwrite() - vfs->vnode->drv->reply()
then the process is woken up to fetch the reply message from its post box.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:oo design: device drivers
Hi,
http://www.linux-tutorial.info/modules. ... pageid=278
http://www.linux.it/~rubini/docs/vfs/vfs.html
http://www.cse.unsw.edu.au/~neilb/oss/l ... y/vfs.html
http://jakarta.apache.org/commons/sandbox/vfs/
Cheers,
Brendan
By "normal file IO" I mean using the same file IO interface that is common to everything that uses the VFS. The file IO interface would be a standardised way of opening/closing files, reading/writing data, getting directory information, etc. It may be closely related to the file IO functions found in C libararies, but could be something completely different (as long as it's the same for all applicable things, rather than having one interface for accessing storage devices and a different interface for accessing normal files).Jonathan Mcdougall wrote:What do you mean by "normal file IO"? Using the standard library?
Sort of - it's an abstraction layer between clients (e.g. applications) and suppliers (e.g. file system drivers and storage device drivers). It's an abstraction used by most OS's that allow a unique file to be located from it's path, regardless of which file system (or device) it actually comes from. Some links might help:Jonathan Mcdougall wrote:I don't really get what's a vfs. It looks like it acts both as a
filesystem (with highlevel functions such as for accessing files)
and as a device driver (such as returning sectors from a floppy).
Am I right?
http://www.linux-tutorial.info/modules. ... pageid=278
http://www.linux.it/~rubini/docs/vfs/vfs.html
http://www.cse.unsw.edu.au/~neilb/oss/l ... y/vfs.html
http://jakarta.apache.org/commons/sandbox/vfs/
I'm probably the wrong person to ask about OOP things - I implement everything using NASM and/or C on top of a micro-kernel, and use a seperate binary for each "object" (VFS, floppy disk controller, floppy driver, file system, etc). Most of these binaries are multi-threaded, with a thread per "instance" (for e.g. floppy driver has a thread for each floppy drive, file system has a thread for each partition, etc). Everything communicates via. messaging.Jonathan Mcdougall wrote:If I am, could I replicate that using polymorphism: the vfs contains only high-level functions, but also gives access to a Device, which would be a base class for all devices. The Fat driver uses that Device to get its data.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:oo design: device drivers
I'm not sure about what 'mounting' does exactly. That's what I'm seeing for the moment:
Does that make sense?
Jonathan
Code: Select all
// a device with its filesystem
struct Entry
{
Device *dev;
FS *fs;
};
class Vfs
{
private:
// all devices
std::vector<Entry> entries_;
public:
// registers a device in the vfs
void add(Device *d)
{
// detect() returns a polymorphic fs driver
FS *fs = FS::detect(d);
entries_.push_back(Entry(d, fs));
}
// returns the File object represented by the filename
// fn looks like "/dev/fd0/test"
File find(std::string fn)
{
// getting device (a Floppy for "fd0")
Device *d = parse_for_device(fn);
Entry e = find_entry(d);
// calls for example Fat::find()
return e.fs->find(fn);
}
};
int main()
{
// somehow calls Vfs::find()
std::ifstream ifs("/dev/fd0/test");
}
Jonathan
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:oo design: device drivers
mounting is: attaching a file system to the virtual file system tree.
I do it like this:
1. check if the user has the proper access ights to do the mount command.
2. check if the device to mount is a block device (now, mounting /dev/mouse does make sense, hm )
3. fetch the superblock of that device: check: is this a ext2fs? is this a fat12fs? is this reiserFS?
4. If found an appropriate fs and if having a driver for it at hands: insert the vnode for the fs at the desired place. init the thread for the fs with the appropriate driver functions (actually, we pass a structure fs_driver_t to it.
5. if that succeeded: fetch the root directory nodes and fill in the root directory (it is a collction of vnodes with real nodes attached to)
6. set the thread to runnable state and give it some init parms (like the device it has to talk to)
7. that's it roughly.
Unmounting the filesystem will only succeed, if there is no more reference to any of its files (ie the file system isn't busy).
Thats simply writing back inode/block data, flushing caches and dropping the whole subtree to our famous bin (free(instance)) --> I've implemented it, but it isn't yet tested, so I'm rather bragging around than talking about something I *know* to work. Take it with some grain of salt.
I do it like this:
1. check if the user has the proper access ights to do the mount command.
2. check if the device to mount is a block device (now, mounting /dev/mouse does make sense, hm )
3. fetch the superblock of that device: check: is this a ext2fs? is this a fat12fs? is this reiserFS?
4. If found an appropriate fs and if having a driver for it at hands: insert the vnode for the fs at the desired place. init the thread for the fs with the appropriate driver functions (actually, we pass a structure fs_driver_t to it.
5. if that succeeded: fetch the root directory nodes and fill in the root directory (it is a collction of vnodes with real nodes attached to)
6. set the thread to runnable state and give it some init parms (like the device it has to talk to)
7. that's it roughly.
Unmounting the filesystem will only succeed, if there is no more reference to any of its files (ie the file system isn't busy).
Thats simply writing back inode/block data, flushing caches and dropping the whole subtree to our famous bin (free(instance)) --> I've implemented it, but it isn't yet tested, so I'm rather bragging around than talking about something I *know* to work. Take it with some grain of salt.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:oo design: device drivers
Thanks to all, I worked on something along those lines and it looks good, though I don't quite think that would make the kernel modular. I'll probably be looking for better ways later on, so I may get back to you soon.
Thanks again,
Jonathan
Thanks again,
Jonathan