linux新增system call(for kernel 2.6)

1. Introduction

This document explains how to implement a new system call on linux 2.6. A system call is used by application (user) programs to request service from the operating system.


2. System call

A system call is used by application (user) programs to request service from the operating system. The following statements illustrate why system calls are needed. An operating system can access a system's hardware directly, but a user program is not given direct access to the hardware. This is done so that the kernel can keep the system safe and secure from malicious user programs. But often, a user program requires some information from the hardware (e.g., from a web camera to show you the picture), but it cannot get the information directly. So, it requests the operating system to supply it the information. This request is made by using an appropriate system call.

A system call executes in the kernel mode. Every system call has a number associated with it. This number is passed to the kernel and that's how the kernel knows which system call was made. When a user program issues a system call, it is actually calling a library routine. The library routine issues a trap to the Linux operating system by executing INT 0x80 assembly instruction. It also passes the system call number to the kernel using the EAX register. The arguments of the system call are also passed to the kernel using other registers (EBX, ECX, etc.). The kernel executes the system call and returns the result to the user program using a register. If the system call needs to supply the user program with large amounts of data, it will use another mechanism (e.g., copy_to_user call).


3. List of files to be modified/created

Assume that your linux source base directory is /usr/src/linux.

Kernel files to be modified are listed below:

1. /usr/src/linux/arch/i386/kernel/syscall_table.S

2. /usr/src/linux/include/asm-i386/unistd.h

3. /usr/src/linux/include/linux/syscalls.h

4. /usr/src/linux/Makefile

New kernel files/directories to be created are listed below:

1. /usr/src/linux/mycall - Directory that will contain the source file, header file and the Makefile for our system call (You can also implement your system call in an existing file).

2. /usr/src/linux/mycall/mycall.c - Source file containing our system call code.

3. /usr/src/linux/mycall/Makefile - Makefile

New user space files, to be created, to test our system call are listed below:

1. testmycall.c – Source file that will call our system call.

2. testmycall.h - Header file.


4. Kernel files to be modified


5. syscall_table.S

Full path of the file - /usr/src/linux/arch/i386/kernel/syscall_table.S

This file contains system call names.

  1. Add a line to the end of this file (Let's assume that the name of our system call is mycall).

  2. Add ".long sys_mycall" at the end of the list.


6. unistd.h

Full path of the file - /usr/src/linux/include/asm-i386/unistd.h

This file contains the system call number that is passed to the kernel through the register (EAX) when a system call is invoked.

  1. Add "#define __NR_mycall <Last_System_Call_Num + 1>" at the end of the list.

If the last system call defined here is:

"#define __NR_vmsplice316", then add:

"#define __NR_mycall317" at the end of the list.

  1. Increment the "NR_syscalls" by 1. So, if NR_syscalls is defined as:

"#define NR_syscalls 317", then change it to:

"#define NR_syscalls 318"


7. syscalls.h

Full path of the file - /usr/src/linux/include/linux/syscalls.h

This file contain the declarations for system calls.

  1. Add the following line at the end of the file:

"asmlinkage long sys_mycall(int i);"


8. Makefile

Full path of the file - /usr/src/linux/Makefile

  1. Add mycall/ to core-y (Search for regex: core-y.*+=). You will be creating this directory. This directory will contain the source file, header file and the Makefile for our system call.


9. New kernel files/directories to be created


10. mycall

Full path of the file - /usr/src/linux/mycall

  1. Create a new directory in /usr/src/linux and name it "mycall".


11. mycall.c

Full path of the file - /usr/src/linux/mycall/mycall.c

  1. Create a source file named "mycall.c" in dir "mycall". mycall.c will have the code for our system call. The definition of the system call in the source file would be asmlinkage long sys_mycall(...){...} . It should include the file linux/linkage.h So, the file "mycall.c" will look like:

/*---Start of mycall.c----*/

#include<linux/linkage.h>

asmlinkage long sys_mycall(int i)

{

return i+10;

}

/*---End of mycall.c------*/

What is asmlinkage?

Asmlinkage is used to look for the arguments on the kernel stack.


12. Makefile

Full path of the file - /usr/src/linux/mycall/Makefile

The Makefile in dir "mycall" will have only one line:

#####Makefile Start#####

obj-y := mycall.o

#####Makefile End#######


13. New user space files, to be created, to test our system call


14. testmycall.h (new user space header file to be created)

testmycall.h

  1. Create a header file called testmycall.h. This header file should be included by any program calling our system call.

  2. Add three lines to it

  1. Line 1: This is needed because we need the definition of _syscall1.

#include<linux/unistd.h>

  1. Line 2: This is needed because we need the number of our system call.

#define __NR_mycall 317

  1. Line 3: This is needed for system calls with 1 argument. It is explained in detail below.

_syscall1(long, mycall, int, i)

So, our user header file looks like:

/*---Start of header file------*/

#include<linux/unistd.h>

#define __NR_mycall 317

_syscall1(long, mycall, int, i)

/*---End of header file--------*/


15. testmycall.c (new user space source file to be created)

testmycall.c

  1. Create a C file called testmycall.c in the same directory as testmycall.h. The C file will look like:

/*---Start of C file------*/

#include<stdio.h>

#include "testmycall.h"

int main(void)

{

printf("%d\n", mycall(15));

}

/*---End of C file------*/


16. _syscallN macro

  1. _syscall0(int,mycall) indicates that:

  2. The name of the system call is mycall.

  3. It takes zero arguments.

  4. It returns an int.

  1. _syscall1(int,mycall,int,number) indicates that:

  2. The name of the system call is mycall.

  3. It takes one argument.

  4. The argument is an int named number.

  5. It returns an int.

When you expand _syscall1(long,mycall,int,i), you get the following code:

long mycall(int i)

{

return syscall(__NR_mycall, i);

}

But the definition of _syscallN macros are different in the kernel. You can look at /usr/src/linux/include/asm-i386/unistd.h for the definition.


17. Testing our new system call

  1. Step 1: Recompile and install the new kernel so that our system call becomes available to the operating system.

  2. Step 2: Compile and execute the user space C file (testmycall.c) that we created above.

  3. RESULT: You should see the output as 25. This has been tested on kernel 2.6.17.13.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章