Page 2 of 2
Re: Determining which driver called kernel function
Posted: Tue Jun 14, 2016 3:38 pm
by embryo2
Brendan wrote:I typically have 3 things:
- VFS
- File systems
- Storage drivers
...
a storage device is mostly a file
...
A file system is something that mounts a file.
...
You can have multiple nested file systems.
Everything after the hardware layer is a data. A component, which uses the data, should understand it. But usually there's too much noise for the component and we can use filters to squeeze just what the component needs. Then the component can understand only filtered data and it's developer can concentrate on the data usage logic instead of data extraction algorithms. It gives us the opportunity to create a system of filters interconnected in a manner that is most useful for our goal. Below is the hardware layer with it's raw bytes. Above are our components, that implement actual application logic. Filters are both - sources and consumers of the data.
An example of it.
Code: Select all
HDD driver -> bytes ->
-> partition filter -> partitions + bytes (content) ->
-> FAT32 filter -> files + directories + bytes (content) ->
-> GIF filter -> meta-data, image properties, ARGB data
or
-> NTFS filter -> files + directories + bytes (content) ->
-> stream tokenizer filter -> tokens ->
-> C++ parser filter -> AST
or
-> XML parser filter -> nodes
Re: Determining which driver called kernel function
Posted: Wed Jun 15, 2016 1:59 am
by onlyonemac
embryo2 wrote:An example of it.
Code: Select all
HDD driver -> bytes ->
-> partition filter -> partitions + bytes (content) ->
-> FAT32 filter -> files + directories + bytes (content) ->
-> GIF filter -> meta-data, image properties, ARGB data
or
-> NTFS filter -> files + directories + bytes (content) ->
-> stream tokenizer filter -> tokens ->
-> C++ parser filter -> AST
or
-> XML parser filter -> nodes
My OS isn't quite like that but funny enough I've got a surprisingly similar design.
What I'm doing is assigning each file type a "class", and then the "class" implements functions that can act on the data. So for example a GIF file might extend class "@system.classes.mime.image.gif". Class "@system.classes.mime.image.gif" might implement functions "get_meta_data", "get_metrics" (width, height, colour depth, etc.), "get_pixels", and so on.
I'm also planning on implementing native formats, so like "@system.classes.native.image" which is a class of object with attributes "width", "height", "colour depth", "pixels", "title", "timestamp", "location", and so on.
I might also add the option for a "virtual attribute" as well, which would be an attribute that hooks into a function, so for example the GIF class might also have the same attributes as the native image class (it could extend the native image class) but the "pixels" attribute actually triggers a call to "get_pixels" every time it is read.
But first I need to turn the filesystem driver that I wrote for testing a few minutes ago from something that always returns the first 16 bytes of the underlying storage device to something that actually parses a filesystem.
Re: Determining which driver called kernel function
Posted: Wed Jun 15, 2016 12:08 pm
by embryo2
onlyonemac wrote:My OS isn't quite like that but funny enough I've got a surprisingly similar design.
What I'm doing is assigning each file type a "class", and then the "class" implements functions that can act on the data. So for example a GIF file might extend class "@system.classes.mime.image.gif". Class "@system.classes.mime.image.gif" might implement functions "get_meta_data", "get_metrics" (width, height, colour depth, etc.), "get_pixels", and so on.
I'm also planning on implementing native formats, so like "@system.classes.native.image" which is a class of object with attributes "width", "height", "colour depth", "pixels", "title", "timestamp", "location", and so on.
I might also add the option for a "virtual attribute" as well, which would be an attribute that hooks into a function, so for example the GIF class might also have the same attributes as the native image class (it could extend the native image class) but the "pixels" attribute actually triggers a call to "get_pixels" every time it is read.
So, in fact it's OOP using procedural language. Why not C++?
And architecturally - converters/filters/transformers are just an encapsulation mechanism for the data structure knowledge. Such components help us to forget about details after the code is tested. But it's better not to forget about such components until there's a data in one of supported formats.
Re: Determining which driver called kernel function
Posted: Wed Jun 15, 2016 12:52 pm
by ~
onlyonemac wrote:Hi,
I've got two layers of drivers: storage device drivers, and filesystem drivers. Both drivers have a single entry point, which is passed a parameter giving the desired function (for storage device drivers, things such as "read 3 sectors at offset 5 into the specified buffer"; for filesystem drivers, things such as "get the name of the next sibling to the specified node") and a number of parameters as required for the desired function (for example, the number and offset of the sectors to read and a pointer to a buffer to read them into). (In the event that the same driver is used for multiple devices or for multiple filesystems across different devices, multiple instances are used and are treated by the kernel as completely separate drivers.)
Now I'm wanting to pass my filesystem drivers two function pointers, one that will read an arbitrary sector from the underlying storage device and one that will write an arbitrary sector to the underlying storage device. These functions will take care of passing the request to the correct storage device driver, and of adding any offset to the requested sector (so that the filesystem driver can request "sector 0" and get the first sector of the partition where the filesystem resides, instead of the first sector of the entire device). Consequently, these functions will need to have some way of knowing which filesystem driver has called them so that they know which storage device driver to pass the request to.
So the question is, what is the best way to do this? So far I have thought of a few possible methods:
- Copying a "template" function to a newly-allocated block of memory and patching it to hardcode some identifier for the storage device driver to use
- Using a single function that is given to all filesystem drivers, which when called will perform a stack backtrace to determine which filesystem driver entry point function was called
- Using a single function that is given to all filesystem drivers, and passing an additional "black box" parameter to identify the filesystem driver to the kernel and which the filesystem drivers are required to pass to the given "read" and "write" functions (this option might ultimately be the best, as the same "black box" parameter can be later used in other driver-to-kernel calls that might be added at a later time)
None of these sound particularly elegant to me. Is there an "official" way to do this? If not, which of these would be the best?
Thanks,
onlyonemac
- Write all functions, constants and variables with an ordinal prefix name like _0000000__. In this way you will also know what functions of which stage of your code development you are calling at all times. Do the same with source files (use ordinal names, an ordinal prefix and then the regular identifier name).
- You can also assign ordinals that will never ever change as in an API to your functions, constants and variables. For each subsystem you know or you can easily know which functions correspond (for example using a big wrapper or set of wrapper functions which you will always know what they are for).
With the ordinals and with the system service wrapper functions themselves knowing what they are for, you will always know what is going on. It could be mastered at a level where you could know what you are doing with wrappers for your OS even if you used drivers and libraries intended for another system like Windows or Linux From Scratch.
Re: Determining which driver called kernel function
Posted: Wed Jun 15, 2016 2:29 pm
by onlyonemac
embryo2 wrote:onlyonemac wrote:My OS isn't quite like that but funny enough I've got a surprisingly similar design.
What I'm doing is assigning each file type a "class", and then the "class" implements functions that can act on the data. So for example a GIF file might extend class "@system.classes.mime.image.gif". Class "@system.classes.mime.image.gif" might implement functions "get_meta_data", "get_metrics" (width, height, colour depth, etc.), "get_pixels", and so on.
I'm also planning on implementing native formats, so like "@system.classes.native.image" which is a class of object with attributes "width", "height", "colour depth", "pixels", "title", "timestamp", "location", and so on.
I might also add the option for a "virtual attribute" as well, which would be an attribute that hooks into a function, so for example the GIF class might also have the same attributes as the native image class (it could extend the native image class) but the "pixels" attribute actually triggers a call to "get_pixels" every time it is read.
So, in fact it's OOP using procedural language. Why not C++?
And architecturally - converters/filters/transformers are just an encapsulation mechanism for the data structure knowledge. Such components help us to forget about details after the code is tested. But it's better not to forget about such components until there's a data in one of supported formats.
It's more like OOP at the operating system level. The actual objects are made up entirely of (procedural) userspace code, which can be written in any language. There's actually very little OOP in the kernel.
Also, writing the kernel in C++ would be a lot more work from the "supporting library" point of view, when C does the job perfectly. The kernel is somewhat of a microkernel, which is responsible only for fetching and updating the objects stored in the filesystem. This is a job that can be handled quite adequately with a few data structures and pointers.
Re: Determining which driver called kernel function
Posted: Thu Jun 16, 2016 12:39 pm
by embryo2
onlyonemac wrote:Also, writing the kernel in C++ would be a lot more work from the "supporting library" point of view, when C does the job perfectly. The kernel is somewhat of a microkernel, which is responsible only for fetching and updating the objects stored in the filesystem. This is a job that can be handled quite adequately with a few data structures and pointers.
If all the kernel does is just that then may be it's OK. But what if you will find a new task for the kernel? Or 10 tasks? Then without proper architecture you'll end up with so called "spaghetti code". And architecture is very OOP friendly thing.
Re: Determining which driver called kernel function
Posted: Thu Jun 16, 2016 2:12 pm
by dseller
onlyonemac wrote:embryo2 wrote:onlyonemac wrote:My OS isn't quite like that but funny enough I've got a surprisingly similar design.
What I'm doing is assigning each file type a "class", and then the "class" implements functions that can act on the data. So for example a GIF file might extend class "@system.classes.mime.image.gif". Class "@system.classes.mime.image.gif" might implement functions "get_meta_data", "get_metrics" (width, height, colour depth, etc.), "get_pixels", and so on.
I'm also planning on implementing native formats, so like "@system.classes.native.image" which is a class of object with attributes "width", "height", "colour depth", "pixels", "title", "timestamp", "location", and so on.
I might also add the option for a "virtual attribute" as well, which would be an attribute that hooks into a function, so for example the GIF class might also have the same attributes as the native image class (it could extend the native image class) but the "pixels" attribute actually triggers a call to "get_pixels" every time it is read.
So, in fact it's OOP using procedural language. Why not C++?
And architecturally - converters/filters/transformers are just an encapsulation mechanism for the data structure knowledge. Such components help us to forget about details after the code is tested. But it's better not to forget about such components until there's a data in one of supported formats.
It's more like OOP at the operating system level. The actual objects are made up entirely of (procedural) userspace code, which can be written in any language. There's actually very little OOP in the kernel.
Also, writing the kernel in C++ would be a lot more work from the "supporting library" point of view, when C does the job perfectly. The kernel is somewhat of a microkernel, which is responsible only for fetching and updating the objects stored in the filesystem. This is a job that can be handled quite adequately with a few data structures and pointers.
My kernel is primarily written in C++, but I like the approach you have taken with the hierarchical class names. It's not as if C++ is the only way to go if you want to follow the object-oriented philosophy. Heck, I used to have structs with function pointers all over my previous kernel
.
Re: Determining which driver called kernel function
Posted: Thu Jun 16, 2016 3:53 pm
by onlyonemac
dseller wrote:My kernel is primarily written in C++, but I like the approach you have taken with the hierarchical class names.
Yes, as I say it's an "object oriented operating system". So files are objects, applications are collections of methods divided among sub-objects of a single parent object, libraries are objects with a collection of useful methods, and so on. Any object can have a class, whereupon it will inherit the attributes and methods of the class (but not the child objects) and any object can be used as the class for another object (currently, although I might add a flag to specify which objects are intended to be used as classes and which objects are intended to be used directly). When an attempt is made to access an attribute or method and an object doesn't have an attribute or method by that name, then the class object is searched for a matching attribute or method. Failing that, the class object's class is searched, and so on recursing all the way up the class tree until either a matching attribute/method is found or an object is reached that doesn't have a class specified, whereupon an error is returned (currently there is no way to detect an infinite recursion that may be caused by two or more objects specifying each other as their class objects, but this would be fairly easy to implement). When an attribute is changed that doesn't exist in an object itself but does exist in an object in the object's class tree, a new attribute with the same name is created in the object itself and its value set to the new value, thus overriding the class's attribute. When a function is called that doesn't exist in an object itself but does exist in an object in the object's class tree, that function is called as if it belonged to the object itself (in other words, functions are always passed, among other things, a pointer to the object to which they belong, and in this case the function would be passed a pointer to the object itself, not to the class object).