After looking at others OS's i have realized that mine is not very organized, as in file location and function location, I'm asking for opinions on how this should go, like drivers -> net -> ne2000 -> ne2000.c, or drivers -> block -> ATA -> etc... and what functions should be in which files. I'm just confused as to how i should organize things to make it easy to find a function. is there a better way than the stock Linux tree look?
thx!
Organization
I don't think it's worth the trouble to think of very official organization for stuff like that. If you notice that you have some set of files which could use their own subdirectory, make such a subdirectory and dump the files there.
You probably end up with something like drivers/net/ne2k.c that way..
Too few directories and it's difficult to figure out what files are related to each other. Too many directories, and you've just added some unnecessary management overhead.
You probably end up with something like drivers/net/ne2k.c that way..
Too few directories and it's difficult to figure out what files are related to each other. Too many directories, and you've just added some unnecessary management overhead.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
also i have questions about how to do things in the OS, like when i add a driver i shouldn't just add it to my main init but mabey have something like: "bool is_hardware_avaleble();" to each device then if true run: "init_hardware();"
or i could run a detection loop and if hardware is avalabe set it up? mabey?
any advice welcome!
or i could run a detection loop and if hardware is avalabe set it up? mabey?
any advice welcome!
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
I can't really answer your question, but I can comment on organization.
At the moment, I have most of my files in a single directory. This works nicely, saves me a bit of effort. However, there are some files that need to be in folders, mainly my ATA stuff, networking stuff, vm stuff, and all my includes. If these weren't in folders I would be getting extremely confused because these cover a lot of files.
Either way, it depends on personal preference.
At the moment, I have most of my files in a single directory. This works nicely, saves me a bit of effort. However, there are some files that need to be in folders, mainly my ATA stuff, networking stuff, vm stuff, and all my includes. If these weren't in folders I would be getting extremely confused because these cover a lot of files.
Either way, it depends on personal preference.
As long as you compile all drivers into the kernel, it think it's ok to just have one big function, which calls each devices initialization in turn. Those initialization function can then detect whether the relevant hardware is present, and if so, register the relevant devices with rest of the kernel. I don't see any advantage with having a separate "detect hardware" and "initialize" functions. It's just as easy for the initialization to fail to register any devices, if none are present.
Ofcourse some drivers like those for PCI devices need not actually detect anything. They can simply register themselves with your PCI bus driver, telling it which device they can support. Your bus driver can then figure what devices are actually present. With buses like USB this approach also allows the bus driver to detect new devices and start drivers from them, if it finds a suitable driver registered.
You probably want some convention on the names though. Something like init_<driver> is probably fine, as that will make it easy to make drivers loadable in the future (you can search for a symbol in the driver that starts with init_ in the driver binary, and call that).
I think it's a good idea to avoid calling any driver functions (other than init) by their names. Instead design interfaces for each class of drivers, and have the driver register itself with some relevant kernel structure, providing some sort of object representing each device, with some sort of vtable-pointer lookalike into the methods implementing the interface. Ofcourse in C++ you can use abstract base classes as interfaces to get this for free, but it's relatively easy to do with plain C as well.
I would not make init_foo return the object representing the device, because this way you have to call it several times to support more than one device implemented by the same driver. Instead have init_foo pass each device directly to the relevant parts of kernel.
Oh, and if you are lazy and don't like the idea of maintaining the big function that calls init of each driver, you could always generated that automatically. You'll need a list of object-files to link into your kernel anyway, so you could feed that to objdump, let it list you the symbols, grep the list for init_* and have a script generate the big function for you.
That's my 0.02 euro anyway.
Ofcourse some drivers like those for PCI devices need not actually detect anything. They can simply register themselves with your PCI bus driver, telling it which device they can support. Your bus driver can then figure what devices are actually present. With buses like USB this approach also allows the bus driver to detect new devices and start drivers from them, if it finds a suitable driver registered.
You probably want some convention on the names though. Something like init_<driver> is probably fine, as that will make it easy to make drivers loadable in the future (you can search for a symbol in the driver that starts with init_ in the driver binary, and call that).
I think it's a good idea to avoid calling any driver functions (other than init) by their names. Instead design interfaces for each class of drivers, and have the driver register itself with some relevant kernel structure, providing some sort of object representing each device, with some sort of vtable-pointer lookalike into the methods implementing the interface. Ofcourse in C++ you can use abstract base classes as interfaces to get this for free, but it's relatively easy to do with plain C as well.
I would not make init_foo return the object representing the device, because this way you have to call it several times to support more than one device implemented by the same driver. Instead have init_foo pass each device directly to the relevant parts of kernel.
Oh, and if you are lazy and don't like the idea of maintaining the big function that calls init of each driver, you could always generated that automatically. You'll need a list of object-files to link into your kernel anyway, so you could feed that to objdump, let it list you the symbols, grep the list for init_* and have a script generate the big function for you.
That's my 0.02 euro anyway.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.