Adding a Hello World System Call to Linux Kernel
In this blog, I’m going to tell you how to add a system call to the Linux kernel. It is like a Hello World program for System calls. :P
Q. Why write this blog?
There is already an awesome blog by tssurya on how to add system call to the linux kernel. You may find it here.
The problem is that the blog is 4 years old and has now become outdated causing problems with the modern operating systems.
I learned it the hard way by getting errors and resolving them, re-making kernel again and again until the kernel was loaded and it worked. :’)
So I have written this blog so that you don’t have to face these problems when you try it.
I am currently using ubuntu 16.04 (64 bit) system with dual cores. I currently have kernel 4.13.0–36-generic.
To know which kernel you have type on terminal
uname -r which will give your kernel version.
Pro Tip: type
sudo -s in your terminal before executing the upcoming commands so that you need not write sudo again and again in the terminal, it will give you a super user terminal session.
You may copy the commands and code directly from this blog to avoid mistakes.
1. Download the kernel source:
In your terminal type the following command:
As my kernel version was 4.13, I downloaded a kernel of higher version (4.17.4), this way the kernel gets automatically updated when you reboot the system after compiling.
Also, make sure to write appropriate v4.x or anything else based on the version series you type.
wget command : GNU Wget is a free utility for non-interactive download of files from the Web.
2. Extract the kernel source code
sudo tar -xvf linux-4.17.4.tar.xz -C/usr/src/
tar — Tar stores and extracts files from a tape or disk archive.
-x — extract files from an archive
-v — requested using the –verbose option, when extracting archives
-f — file archive; use archive file or device archive
-C — extract to the directory specified after it.(in this case /usr/src/)
Now, we’ll change the directory to where the files are extracted:
3. Define a new system call sys_hello( )
- Create a directory named
hello/and change the directory to hello/:
Create a file
hello.c using your favourite text editor:
write the following code in the editor:
printk prints to the kernel’s log file.
- Create a “Makefile” in the hello directory:
and add the following line to it:
obj-y := hello.o
This is to ensure that the hello.c file is compiled and included in the kernel source code.
Note: There is no space in between“obj-y”.
4. Adding hello/ to the kernel’s Makefile:
Go back to the parent dir i.e.
cd ../ and open “Makefile”
search for core-y in the document, you’ll find this line as the second instance of your search:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
Add ‘hello/’ to the end of this line:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ hello/
Note: There is a space between “block/” and “hello/”. (Doing such a mistake may cause errors in further steps)
This is to tell the compiler that the source files of our new system call (sys_hello()) are in present in the hello directory.
5. Add the new system call to the system call table:
If you are on a 32-bit system you’ll need to change ‘syscall_32.tbl’. For 64-bit, change ‘syscall_64.tbl’.
Run the following commands in your terminal from linux-4.17.4/ directory:
You’ll get a file like the following in your editor:
Go to the last of the document and add a new line like so:
548 64 hello sys_hello
- Here I’ve written 548 because in the previous line the number entry was 547. Remember this number it will be used in the later steps.
- Also, note that I’ve written 64 in my system because it is 64 bit. You may have to write i586 or x32. For knowing what is to be written check in this file itself in many of the lines you may find entries like so:
This will tell you whether to write i586 or something else.
Save and exit.
6. Add new system call to the system call header file:
Go to the
linux-4.17.4/ directory and type the following commands:
Add the following line to the end of the document before the #endif statement:
asmlinkage long sys_hello(void);
After this your file will look like so:
Save and exit.
This defines the prototype of the function of our system call. “asmlinkage” is a key word used to indicate that all parameters of the function would be available on the stack.
7. Compile the kernel:
Before starting to compile you need to install a few packages. Type the following commands in your terminal:
sudo apt-get install gcc
sudo apt-get install libncurses5-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libssl-dev
sudo apt-get install libelf-dev
sudo apt-get update
sudo apt-get upgrade
to configure your kernel use the following command in your
sudo make menuconfig
Once the above command is used to configure the Linux kernel, you will get a pop up window with the list of menus and you can select the items for the new configuration. If your unfamiliar with the configuration just check for the file systems menu and check whether “ext4” is chosen or not, if not select it and save the configuration.
Now to compile the kernel you can use the make command:
Pro Tip: The make command can take a lot of time in compiling, to speed up the process you can take advantage of the multiple cores that our systems have these days. Simply type,
sudo make -jn
where n is the number of cores that you have in your linux system. For example if I have a Quad core(4) processor, I’ll write:
sudo make -j4
this will speed up my make process 4x times. ;)
This might take several hours depending on your system. It took me 2–3 hours to get this compiled.
8. Install / update Kernel:
Run the following command in your terminal:
sudo make modules_install install
It will create some files under
/boot/ directory and it will automatically make a entry in your grub.cfg. To check whether it made correct entry, check the files under
/boot/ directory . If you have followed the steps without any error you will find the following files in it in addition to others.
Now to update the kernel in your system reboot the system . You can use the following command:
shutdown -r now
After rebooting you can verify the kernel version using the following command:
It will display the kernel version like so:
9. Test system call:
Go to your home(~) directory using the following commands and create a
Write the following code in this file:
Note: Remember I told you to keep in mind the number of system call that we wrote in
syscalls_64.tbl? In my case the number was 548. Write that same number in your userspace.c file as an argument in
Now, compile and run the program:
If all the steps are done correctly you’ll get an output like below:
System call sys_hello returned 0
Now, to check the message of your kernel run the following command:
This will display
Hello world at the end of the kernel’s message.
This ends the process of Adding a Hello World System Call to your Linux Kernel.
- Keep in mind that this assignment may require upto 40 GB of hard disk storage, so make sure you have that.
- In case after the completion
uname -rstill shows generic kernel version. Then you may have to manually change the kernel in your grub. To do so, you may refer to this link.
I would like to thank Tssurya for writing the blog. My blog is just an updated version of what he wrote due to the changes that happen from time to time in OS and systems. :)
Also, I would like to thank my dear friend Abhay for helping me out solve the errors while I was doing this assignment. :P