Adding A System Call To Linux (Fedora 9)
By Cory Hekimian-Williams on Nov.08, 2008, under Linux, Programming
Getting Started
The procedure to create a system call varies in different versions of Linux. I will provide a simple step by step guide on adding a system call to the Fedora 9 kernel. The version I used to write this document was Fedora 9 kernel 2.6.26 (i686). I originally wrote this while I was a TA for an undergraduate Operating Systems course at FSU.
When you add a system call you will have to recompile the Linux kernel, so you must have the Linux source tree installed on your system. Furthermore, compiling the kernel can take a good amount of time (depending on the system and kernel options to it can take hours), so give yourself time. There is a way to add system calls without recompiling the kernel using modules as a wrapper, but that is beyond the scope of this document.
Notes
When folders are described with source/ at the start of the path, it represents the highest level of the Linux source tree. You should have folders such as arch, configs, include, and init in this folder.
Creating the System Call Source
We will be creating a simple hello world system call. Create a file mysyscall.c and fill it with the following code.
#include <linux/kernel.h>
#include <linux/linkage.h>
asmlinkage long mysyscall(int i){
printk(KERN_DEBUG "Hello World! The number was %dn", i);
return(1);
}
Adding the System Call
1. Firstly, navigate to the root directory of your Linux source. Create a folder source/mysyscall. Next, inside of your newly created folder, add a source file mysyscall.c that contains all of your system call source code.
2. Next, create a make file within this directory. This make file only needs to contain one line that says what to compile.
Create source/mysyscall/Makefile (keep the capital ‘M’)
obj-y := mysyscall.o
3. Next we need to modify the kernel’s make file. This is located in the root folder of your kernel’s source. Find the line that adds a bunch of folders to the core-y variable and add the folder name that the system call source is in. (mysyscall in this example)
In source/Makefile, the line to change looks something like this:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
It should be changed to something like this:
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ mysyscall/
4. Now, navigate to the source/arch/x86/kernel folder. You will need to add your system call to the system call table. This is done in the file syscall_table_32.S. At the end of the file you add an entry for the new system call. Make sure to prefix your entry with “sys_”.
It should look something like this:
.long sys_mysyscall
You should notice the numbers commented out to the right of some of the entries. They tell you what number the system call is. Keep track of which number your new system call is.
5. Next navigate to the source/include/asm-x86 folder and edit unistd_32.h. Add a #define line for the new system call. Use the number that you noted in the last step.
You should add a line similar to this:
#define __NR_mysyscall 327
6. You are now ready to recompile your kernel.
Using the System Call
1. Next to use the system call we need to create a header file that exposes the new call. Create a file, mysyscall.h which will be imported into any program that wants to use the new system call.
This header file should contain the following:
#include "unistd.h"
#define __NR_mysyscall 327
long mysyscall(int i){
return syscall(__NR_mysyscall, i);
}
2. Write a program that includes your newly created header file, and then call the mysyscall (int i) function you have implemented.
Adding a Variable Shared Between a System Call and a Kernel Module
1. Using External Variables
In order to use a variable that has been declared in another file, the keyword extern must be used.
#include <linux/kernel.h>
extern int myVar;
int MyModuleFunction(){
/* Has access to myVar which is defined in a different kernel file*/
}
2. Making Variables Externally Visible
However, variables are not visible to other files by default. For a variable declared in a system call to be visible to a kernel module it must be exported. To export a variable you must use the macro EXPORT_SYMBOL. You can export functions as well using this same macro.
#include <linux/kernel.h>
int myVar;
EXPORT_SYMBOL(myVar);
static int MySystemCall(){
/* Has access to myVar */
}
Adding a system call to Linux can sometimes be a daunting task, especially the first time. I hope this document was helpful.
17 Comments for this entry
The following websites reference this page.
-
Reg : Adding a simple system call to the kernel
January 20th, 2011 on 8:37 am[...] it from here: http://tldp.org/HOWTO/Implement-Sys-…-i386/x50.html Adding a System call Tutorial http://hekimian-williams.com/?p=20 Linux Online http://www.linux.org/docs/ldp/howto/…-i386/x50.html But the Question is Why there [...]
-
Adding a new system call in Linux kernel 3.3
September 25th, 2012 on 11:03 am[...] I am very new to this kernel thing. What I want to do is just add a new system call to the kernel. I was following this guideline: http://hekimian-williams.com/?p=20. [...]
October 13th, 2009 on 10:34 pm
hey thanks for the tutorial, it helped to guide me through add a syscall on fedora 11 (i think) too.
One thing to note the mysyscall function needs to return a long in order for it to work properly.
so maybe something like this:
asmlinkage long mysyscall(int i){
printk(KERN_DEBUG “Hello World! The number was %dn”, i);
return 123213;
}
October 13th, 2009 on 10:47 pm
Glad it was helpful, thanks for the correction, I fixed the function.
October 27th, 2009 on 12:06 am
I am using linux-2.6.28.10 (Ubuntu jaunty). I am unable to locate the include/asm-x86 folder. Should i copy-paste it ? Adding a system call to i386 architecture seems to be easier but i am not sure it would work on i686 machines. Please help.
October 27th, 2009 on 2:58 pm
Hi, tutorial is really helpful, one change in mysyscall.c as
asmlinkage long mysyscall(int i){
asmlinkage long sys_mysyscall(int i){
Thanks
November 24th, 2009 on 10:00 am
I cant find entry.S file while trying to add system call..
Please suggest a way out…This is my undergraduate project
June 28th, 2010 on 3:14 pm
Awesome blog post. I have got to say though that for operating systems, I am still old school and usually go with ones that have had the bugs ironed out for a couple years, how about you?
August 8th, 2010 on 10:14 pm
can u upload a video of this entire process?
September 27th, 2010 on 4:12 am
Hi,I have done but when i have compiled i m getting “unreference mysyscall”.plz help me?thnx
October 26th, 2010 on 9:03 am
hi…
I have used this procedure but do not able to add the systemcall plz help me soon
December 1st, 2010 on 8:38 pm
I have used each step carefully but the make process i get a error saying
in table Syscalltable_32.S
undefined reference to mysyscall please help. soon..
December 14th, 2010 on 5:26 pm
hello all, I was just checkin’ out this site and I really admire the basis of the article, and have nothing to do, so if anyone would like to to have an enjoyable conversation about it, please contact me on squidoo, my name is michael pollum
January 27th, 2011 on 11:22 pm
~’” I am really thankful to this topic because it really gives useful information .~.
May 28th, 2011 on 7:05 pm
I like the valuable info you provide in your articles. I’ll bookmark your blog and check again here regularly. I’m quite certain I will learn lots of new stuff right here! Good luck for the next!
June 10th, 2011 on 11:18 am
Hello
Thanks
I have a question about your sentence : “There is a way to add system calls without recompiling the kernel using modules as a wrapper, but that is beyond the scope of this document.”
How can we do it? Can you say me the way or get me some link to other references?
Thanks
August 15th, 2011 on 5:43 am
Very good blog. I reali like it! Good 4 you;)
August 15th, 2011 on 5:44 am
Nice blog & interesting post!
September 2nd, 2011 on 8:29 am
Thanks for posting, very good website