内核层:
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;
}