mmswe
mmswe

Reputation: 707

Simple System Call Implementation example?

Interestingly, I couldn't find any simple example on web. Can you share a simple example please? I'm trying to understand following by analyzing an example.

⦁   Typically, 
⦁   a number associated with each system call
⦁   Number used as an index to a table: System Call table
⦁   Table keeps addresses of system calls (routines)
⦁   System call runs and returns
⦁   Caller does not know system call implementation
⦁   Just knows interface

Upvotes: 2

Views: 5160

Answers (1)

mauzel
mauzel

Reputation: 1616

This depends on which architecture you want to add a system call for, or if you want to add the system call for all architectures. I will explain one way to add a system call for ARM.

  1. Pick a name for your syscall. For example, mysyscall.
  2. Choose a syscall number. In arch/arm/include/asm/unistd.h, take note of how each syscall has a specific number (__NR__SYSCALL_BASE+<number>) assigned to it. Choose an unused number for your syscall. Let us choose syscall number 223. Then add:

    #define __NR_mysyscall (__NR_SYSCALL_BASE+223

    where the index 223 would be in that header file. This assigns the number 223 to your syscall on ARM architectures.

  3. Modify architecture-specific syscall table. In linux/arch/arm/kernel/calls.S, change the line that corresponds to syscall 223 to:

    CALL(sys_mysyscall)

  4. Add your function prototype. Suppose you wanted to add a non-architecture-specific syscall. Edit the file: include/linux/syscalls.h and add your syscall's prototype:

    asmlinkage long sys_mysyscall(struct dummy_struct *buf);

    If you wanted to add it specifically for ARM, then do the following except in this file: arch/arm/kernel/sys_arm.c.

  5. Implement your syscall somewhere. Create a file whereever you please. For example, in the kernel/ directory. You need to at least have:

#include <linux/syscalls.h>
...
SYSCALL_DEFINE1(mysyscall, struct dummy_struct __user *, buf)
{
    /* Implement your syscall */
}

Note the macro, SYSCALL_DEFINE1. The number at the end should correspond to how many input parameters your syscall has. In this case, our system call only has 1 parameter, so you use SYSCALL_DEFINE1. If it had two parameters, you would use SYSCALL_DEFINE2, etc.

Don't forget to add the object (.o) file to the Makefile in the directory where you put it.

  1. Compile your new kernel and test. You haven't modified your C libraries, so you cannot invoke your syscall with mysyscall(). You need to use the syscall() function which takes a system call number as its first argument:
struct dummy_struct *buf = calloc(1, sizeof(buf));   
int res = syscall(223, buf);

Do note that this was for ARM. The process will be very similar for other architectures.

Edit: Don't forget to add your syscall file to the Makefile in kernel/.

Upvotes: 9

Related Questions