Kernel Development Learning Pipeline
F0 - Specification 📐
You will conceive of an idea for a novel character driver with the objective of designing something that is creative and non-trivial and will provide for an entertaining demonstration as part of someone’s final presentation.
With the knowledge that it is one of your colleagues who will be responsible for actually implementing your idea, you will write a specification of the behavior of each syscall that is precise and detailed enough for them to implement it correctly.
To further guide your colleague in implementing a driver that complies with your creative vision, you must write a userspace program that executes a suite of tests that a correct driver should pass.
Outcomes:
- Validate your conceptual understanding of character devices
- Demonstrate your creative capacity and vision
- Simulate teamwork and communication aspects of working on a real-world coding team
- Practice clarity in technical writing by clearly specifying the intended behavior of code to colleagues
- Further develop your ability to rigorously test code
What to submit:
Procedure:
- Brainstorm some ideas with an eye for how the behavior can be implemented in a real character driver.
Some entertaining ideas may be more feasible on paper than in practice, so get started early so that you don’t have to pick the first idea you can come up with right before the due date.
As a source of inspiration, here are some categories of ideas that have proved viable in the past with examples of what previous students did.
- A cipher or code for encrypting and decrypting text e.g. Vigenère or Pig Latin.
- A simple game, like tic-tac-toe.
- A tool such as a unit converter.
- A simulator for some process e.g. ordering food at a drive-thru window, or a Tamagotchi-pet, or interpreting a simple programming language.
-
The most important system calls to figure out will be read
, write
and ioctl
. Read and write are best at handling strings of text, while if you want to process numbers, ioctl is probably a better option. Ioctl can also be a catch all way to signal that the user wishes for something to happen and different commands can be passed to indicate different actions.
-
Once you have designed the core functionality of the driver, consider how those functions will (or will not) interact with the file position value that the kernel stores for each open file and how lseek
will fit into that picture. What if any types of repositioning should be supported? How will the other functions handle a file position that might be out of bounds?
-
Finally you have to think about the life-cycle of a given file and the driver overall. Does some the state persist the whole time the driver is loaded? If so, what initial condition should it be in when the driver is first loaded. Does anything get reset or created in response to a call to open
? If so do things need to be cleaned up in release
when the file is closed?
- Write a plain-text specification for the
open
, read
, write
, close
, ioctl
, and lseek
syscalls.
- You must describe how a user can correctly invoke each syscall and what behavior or information it accepts and/or returns.
- You must describe the behavior and
errno
values returned for all possible failure modes that come to mind.
- You must describe with as much precision as possible the state of the system following a successful invocation of any of the features.
- You must test all of the system calls that your driver supports and write at least 25 tests in total. For the main system calls
read
, write
and ioctl
, you should have at least 5-7 tests.
- Be sure to write tests that cover all of the behavior you specified, including but not limited to:
- Simple tests that try to isolate a specific behavior and verify it is correct.
- More complex integration tests that verify that different system calls can work together.
- All failure modes that happen within the logic of the driver or as a result of user behavior (i.e. not ones resulting from extreme system conditions beyond the driver such as lack of resources).
- Get creative when considering the incorrect usage of your API. Come up with some exotic input data and insane parameters.
- Don’t forget to test for simple memory errors like usage of a null or invalid pointer.
- When run, the program should provide information about which tests succeeded or failed.
- If a test failed, include in the output of the testing program how the behavior differed from what was expected.
- Your test program should gracefully handle errors, e.g. it should not crash if a test fails or if the character driver’s device file cannot be found.
- Program output should be easy to understand and clear.
- You will not have a driver implementation to run your test program against, however you can still verify that it is performing the right operations by pointing it at a dummy file like
/dev/null
or /dev/zero
and verifying that it is making the right system calls with strace
.
- Be careful while writing your tests and document them well so that the person implementing the driver can understand your thinking.
- Mistakes happen, and it may be that the tests are not 100% correct. The person implementing the driver will have some leeway to fix bugs in the tests while trying not to change the spirit of what is being tested. We will not take off points for honest mistakes, but we do reserve the right to take points off if the tests are completely incoherent and prove impossible to work with.
Submission Guidelines