|
Mon
31
Jul '06
|
Paul proposed implementing a syscall as a first exercise. I am digging a little myself and found that most online documents (including the textbook) are not up-to-date with 2.6.16. So I am trying to document a little bit of my own.
In my kernel version (2.6.16.11), the syscall table resides in file arch/i386/kernel/syscall_table.S for i386 platform. To add a system call, say, foo, we need to add it to the end of the table:
.long sys_foo
Then, we need to edit include/asm/unistd.h. Find these two lines:
#define __NR_unshare 310 #define NR_syscalls 311
Change them to:
#define __NR_unshare 310 #define __NR_foo 311 #define NR_syscalls 312
Then put the definition of sys_foo anywhere relevant. For instance, if it’s a syscall available on all platforms, it’s probably a good idea to put it in kernel/sys.c:
asmlinkage long sys_foo (void) { printk ("sys_foo() called.n"); return 0; }
Now recompile the kernel, and verify it’s in System.map (by grepping):
c01235fa T sys_foo
Then make install and reboot, and cross your fingers.
If everything works fine, you should be back running the new kernel with your shining foo system call. Now it’s time to test if it really works with this small program:
#include #define __NR_foo 311 _syscall0(long, foo) int main () { foo (); return 0; }
You need to define __NR_foo because it’s not yet in your /usr/include/linux/unistd.h. Now, compile, run, and check the syslog using dmesg | tail. You should see a line saying
sys_foo() called.
And, that’s it, simple enough. Too make it a little less boring, say, print out the PID, change the code:
asmlinkage long sys_foo (void) { printk ("sys_foo() called from process %d.n", current->tgid); return 0; }
And you will get something like this in dmesg:
sys_foo() called from process 5557.