There was a big book with plain red leather covers; its tall pages were now almost filled. At the beginning there were many leaves covered with Bilbo's thin wandering hand; but most of it was written in Frodo's firm flowing script. It was divided into chapters but Chapter 80 was unfinished, and after that were some blank leaves.
"Why, you have nearly finished it, Mr. Frodo!" Sam exclaimed. "Well, you have kept at it, I must say."
"I have quite finished, Sam," said Frodo. "The last pages are for you."
—The Return of the King, Book VI, Chapter 9
In this studio, you will:
Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete. We encourage you to please work in groups of 2 or 3 people on each studio (and the groups are allowed to change from studio to studio) though if you would prefer to complete any studio by yourself that is allowed.
As you work through these exercises, please record your answers, and when finished upload them along with the relevant source code to the appropriate spot on Canvas. If you work in a group with other people, only one of you should please upload the answers (and any other files requested) for the studio, and if you need to resubmit (e.g., if a studio were to be marked incomplete when we grade it) the same person who submitted the studio originally should please do that.
Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.
As the answer to the first exercise, list the names of the people who worked together on this studio.
On the Linux Lab cluster, please
create a new directory to hold your kernel modules,
cd into it. Save a copy of
simple_module.c (a simple
template for writing kernel modules in this course, based on the "Hello,
World!" module shown on pages 338 and 339 of Robert Love's Linux Kernel
Development, Third Edition) into that directory. In that directory also
create a Makefile that contains the line
obj-m := simple_module.o
and save that file. You should then build the module by issuing the commands
module add arm-rpi
LINUX_SOURCE=path to your Linux kernel source code
(note that the path above should end in something like
and finally compile via
make -C $LINUX_SOURCE ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- M=$PWD modules
which if successful should produce a kernel module file named
As the answer to this exercise, show the output that was produced by
sftpto get the
simple_module.kofile you produced in the previous exercise.
First, clear out the contents of the system log using the command
sudo dmesg --clear
and then use the
insmod utility to load your kernel module into the
kernel, as in:
sudo insmod simple_module.ko
If you recieved no error messages, then your module has been successfully loaded. To confirm this, you can check the system log by issuing the command
which prints out the system log, which now should show the message that was printed when the module loaded. As the answer to this exercise, please show the message that appears in the system log.
rmmod. When using this tool you can either specify the module name (as shown in
lsmod) or you can specify a
.kofile, as in
sudo rmmod simple_module.ko
Remove your module now, and verify its removal as before. As the answer to
this exercise, copy the output of
lsmod and the line of the system log,
which show that the module was unloaded.
One kernel variable we will talk about this semester is the
counter. This variable keeps track of how many timer interrupts
(also called ticks) have occured since system boot.
You will learn more about jiffies and timer interrupts in an upcoming class.
simple_module.c to a new file called
and modify that new file, so that the system log messages that are generated when the module
is loaded and unloaded also give the value of the
(hint: it's an
unsigned long) to the system log.
Note that although this
jiffies variable is not readily available
to userspace programs, it is available directly when in kernelspace.
Makefile, build your new kernel module and use
sftp to copy the
jiffies_module.ko file that was
produced for it, over to your Raspberry Pi.
On your Raspberry Pi, load and unload your new kernel module, and as the
answer to this exercise please copy and paste the system log message that shows
the values of the
jiffies variable when your module was loaded and
when it was unloaded, and say how many ticks occurred between those messages.
jiffies_module.cfile for the new kernel module you created.
/include/uapi/asm-generic/errno-base.h. Modify your init function to return positive and negative values, respectively. As the answer to this exercise please describe briefly what happens when you load the module, and what you see in the system logs because of that.
Kernel symbols that are available to be used in loadable modules
are called exported symbols and are identified by the
EXPORT_SYMBOL macro. You can see a list of all kernel symbols
by looking at the file /proc/kallsyms, e.g.
You might notice that this is very similar to the symbol table of a traditional
application. (Which you can print with the program
nm, if you've
never done that before. Try it on any binary!) In fact, their syntax is
identical, so you can use the command
man 1 nm to find some more information
about how to decode the contents of
Symbols that have been exported can be found in this list with the prefixes
__ksymtab_. These prefixes denote
a special kernel symbol that stores the name of the exported symbol and a
struct that stores information about the symbol, respectively. See the
EXPORT_SYMBOL to see how these are generated.
As the answer to this exercise, please list a few of those symbols that
are available for use in a kernel module.
The optional enrichment exercises in the Linux System Calls studio had you create a system call to retrieve a value directly from the Cycle Count Register (CCNT) on the Raspberry Pi's ARM CPU. Today, we will implement a kernel module to allow userspace programs to read the CCNT value without having to make a system call.
If you did not complete this enrichment exercise in the System Calls studio,
please download this driver file,
and place it in the
directory in your Linux kernel source tree.
Now, please download the kernel module code,
into the kernel modules directory you created in Exercise 2.
Follow the instructions in Exercises 2 and 3 to compile the kernel module,
transfer it to your Raspberry Pi with
and load it using
To verify that it loaded correctly, issue the command:
dmesg | tail
You should see messages written to the kernel log indicating that the Cycle Counter has been enabled, and showing a current cycle count value.
Next, retrieve the same driver file
onto your Raspberry Pi, and create a program
Have the program call the function
which has the signature:
unsigned long long pmccntr_get(void)
In particular, call this function twice to return two cycle counts in a row. As the answer to this exercise, please say how many CPU cycles it takes to run this function. If you completed the enrichment exercise in the System Calls studio, compare this cycle duration to the number of cycles it took to make the system call.