linux内核添加系统调用

来源:互联网 发布:手机信号探测软件 编辑:程序博客网 时间:2024/05/21 18:46

内核层:

1. 内核arch/x86/kernel/syscall_table_32.S

.long sys_mysyscall             /* 285 */ /* available */

2. arch/x86/include/asm/unistd_32.h

#define __NR_mysyscall  285

3. 添加函数代码

asmlinkage int sys_mysyscall(int n)
{
        printk("this is my syscall\n");
        return n;
}

用户层:

2.6.15时代unistd.h还有如下的宏:

_syscall0(type,name)

2.6.32已经废除这些宏了,改为syscall函数,使用man syscall来查看使用方法,额外需要修改sys/syscall.h,实际是bits/syscall.h中。

1. 添加#define SYS_mysyscall __NR_mysyscall,就可以使用syscall(SYS_mysyscall, ...)来调用了。

2. 在/usr/include/asm/unistd_32.h中添加#define __NR_mysyscall  285。

如果不做以上两步,就只能用syscall(285, ...)来调用。


#define _GNU_SOURCE        /* or _BSD_SOURCE or _SVID_SOURCE */
#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */

int syscall(int number, ...);



而实际在内核中系统调用是使用include/linux/syscalls.h中的SYSCALL_DEFINEx来定义的:


#ifdef CONFIG_FTRACE_SYSCALLS
#define SYSCALL_DEFINEx(x, sname, ...)                          \
        static const char *types_##sname[] = {                  \
                __SC_STR_TDECL##x(__VA_ARGS__)                  \
        };                                                      \
        static const char *args_##sname[] = {                   \
                __SC_STR_ADECL##x(__VA_ARGS__)                  \
        };                                                      \
        SYSCALL_METADATA(sname, x);                             \
        __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#else
#define SYSCALL_DEFINEx(x, sname, ...)                          \
        __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#endif

#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS

#define SYSCALL_DEFINE(name) static inline long SYSC_##name

#define __SYSCALL_DEFINEx(x, name, ...)                                 \
        asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));           \
        static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));       \
        asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))            \
        {                                                               \
                __SC_TEST##x(__VA_ARGS__);                              \
                return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));    \
        }                                                               \
        SYSCALL_ALIAS(sys##name, SyS##name);                            \
        static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */


例子:


SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
                struct timezone __user *, tz)
{
        if (likely(tv != NULL)) {
                struct timeval ktv;
                do_gettimeofday(&ktv);
                if (copy_to_user(tv, &ktv, sizeof(ktv)))
                        return -EFAULT;
        }
        if (unlikely(tz != NULL)) {
                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
                        return -EFAULT;
        }
        return 0;
}