当前位置:   article > 正文

linux内核系统调用学习5:SYSCALL_DEFINE<0-6>_syscall_define 为什么类型和参数名逗号分隔

syscall_define 为什么类型和参数名逗号分隔

 系统调用最大参数是6,由下面这个宏定义,位于文件include\linux\syscalls.h

#define SYSCALL_DEFINE_MAXARGS	6
SYSCALL_DEFINE0(fork)

fork:系统调用名。 

SYSCALL_DEFINE1(set_tid_address, int __user *, tidptr)

 set_tid_address:系统调用名

int __user *:第一个参数类型

tidptr:第一个参数。

注意参数类型和参数名之间是用逗号隔开的。后面的2-6也是如此。 

  1. COMPAT_SYSCALL_DEFINE2(stat64, const char __user *, filename,
  2. struct compat_stat64 __user *, statbuf)
  1. SYSCALL_DEFINE3(cacheflush,
  2. void __user *, addr,
  3. unsigned long, bytes,
  4. int, cache)
  1. /*
  2. * The following function implements the controller interface for
  3. * the eventpoll file that enables the insertion/removal/change of
  4. * file descriptors inside the interest set.
  5. */
  6. SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
  7. struct epoll_event __user *, event)
  1. SYSCALL_DEFINE5(fsconfig,
  2. int, fd,
  3. unsigned int, cmd,
  4. const char __user *, _key,
  5. const void __user *, _value,
  6. int, aux)
  1. SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
  2. unsigned long, prot, unsigned long, flags,
  3. unsigned long, fd, unsigned long, off)

  1. #define SYSCALL_DEFINE0(sname) \
  2. SYSCALL_METADATA(_##sname, 0); \
  3. asmlinkage long sys_##sname(void); \
  4. ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \
  5. asmlinkage long sys_##sname(void)
  1. #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
  2. #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
  3. #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
  4. #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
  5. #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
  6. #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
  1. #define SYSCALL_DEFINEx(x, sname, ...) \
  2. SYSCALL_METADATA(sname, x, __VA_ARGS__) \
  3. __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
  1. #define __SYSCALL_DEFINEx(x, name, ...) \
  2. __diag_push(); \
  3. __diag_ignore(GCC, 8, "-Wattribute-alias", \
  4. "Type aliasing is used to sanitize syscall arguments");\
  5. asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
  6. __attribute__((alias(__stringify(__se_sys##name)))); \
  7. ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
  8. static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
  9. asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
  10. asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
  11. { \
  12. long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
  13. __MAP(x,__SC_TEST,__VA_ARGS__); \
  14. __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
  15. return ret; \
  16. } \
  17. __diag_pop(); \
  18. static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))

然后看看__MAP宏系列宏

  1. /*
  2. * __MAP - apply a macro to syscall arguments
  3. * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to
  4. * m(t1, a1), m(t2, a2), ..., m(tn, an)
  5. * The first argument must be equal to the amount of type/name
  6. * pairs given. Note that this list of pairs (i.e. the arguments
  7. * of __MAP starting at the third one) is in the same format as
  8. * for SYSCALL_DEFINE<n>/COMPAT_SYSCALL_DEFINE<n>
  9. */
  10. #define __MAP0(m,...)
  11. #define __MAP1(m,t,a,...) m(t,a)
  12. #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
  13. #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
  14. #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
  15. #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
  16. #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
  17. #define __MAP(n,...) __MAP##n(__VA_ARGS__)

__PROTECT宏

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)

 asmlinkage_protect宏位于文件include\linux\linkage.h

  1. #ifndef __ASSEMBLY__
  2. #ifndef asmlinkage_protect
  3. # define asmlinkage_protect(n, ret, args...) do { } while (0)
  4. #endif
  5. #endif

SYSCALL_METADATA宏

这个宏由CONFIG_FTRACE_SYSCALLS决定,定义如下

  1. #ifdef CONFIG_FTRACE_SYSCALLS
  2. #define __SC_STR_ADECL(t, a) #a
  3. #define __SC_STR_TDECL(t, a) #t
  4. extern struct trace_event_class event_class_syscall_enter;
  5. extern struct trace_event_class event_class_syscall_exit;
  6. extern struct trace_event_functions enter_syscall_print_funcs;
  7. extern struct trace_event_functions exit_syscall_print_funcs;
  8. #define SYSCALL_TRACE_ENTER_EVENT(sname) \
  9. static struct syscall_metadata __syscall_meta_##sname; \
  10. static struct trace_event_call __used \
  11. event_enter_##sname = { \
  12. .class = &event_class_syscall_enter, \
  13. { \
  14. .name = "sys_enter"#sname, \
  15. }, \
  16. .event.funcs = &enter_syscall_print_funcs, \
  17. .data = (void *)&__syscall_meta_##sname,\
  18. .flags = TRACE_EVENT_FL_CAP_ANY, \
  19. }; \
  20. static struct trace_event_call __used \
  21. __attribute__((section("_ftrace_events"))) \
  22. *__event_enter_##sname = &event_enter_##sname;
  23. #define SYSCALL_TRACE_EXIT_EVENT(sname) \
  24. static struct syscall_metadata __syscall_meta_##sname; \
  25. static struct trace_event_call __used \
  26. event_exit_##sname = { \
  27. .class = &event_class_syscall_exit, \
  28. { \
  29. .name = "sys_exit"#sname, \
  30. }, \
  31. .event.funcs = &exit_syscall_print_funcs, \
  32. .data = (void *)&__syscall_meta_##sname,\
  33. .flags = TRACE_EVENT_FL_CAP_ANY, \
  34. }; \
  35. static struct trace_event_call __used \
  36. __attribute__((section("_ftrace_events"))) \
  37. *__event_exit_##sname = &event_exit_##sname;
  38. #define SYSCALL_METADATA(sname, nb, ...) \
  39. static const char *types_##sname[] = { \
  40. __MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \
  41. }; \
  42. static const char *args_##sname[] = { \
  43. __MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \
  44. }; \
  45. SYSCALL_TRACE_ENTER_EVENT(sname); \
  46. SYSCALL_TRACE_EXIT_EVENT(sname); \
  47. static struct syscall_metadata __used \
  48. __syscall_meta_##sname = { \
  49. .name = "sys"#sname, \
  50. .syscall_nr = -1, /* Filled in at boot */ \
  51. .nb_args = nb, \
  52. .types = nb ? types_##sname : NULL, \
  53. .args = nb ? args_##sname : NULL, \
  54. .enter_event = &event_enter_##sname, \
  55. .exit_event = &event_exit_##sname, \
  56. .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
  57. }; \
  58. static struct syscall_metadata __used \
  59. __attribute__((section("__syscalls_metadata"))) \
  60. *__p_syscall_meta_##sname = &__syscall_meta_##sname;
  61. static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
  62. {
  63. return tp_event->class == &event_class_syscall_enter ||
  64. tp_event->class == &event_class_syscall_exit;
  65. }
  66. #else
  67. #define SYSCALL_METADATA(sname, nb, ...)
  68. static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
  69. {
  70. return 0;
  71. }
  72. #endif

CONFIG_FTRACE_SYSCALLS从名字上看应该是和trace命令相关的功能。

 

 查看它对应的配置:

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/214565
推荐阅读
相关标签
  

闽ICP备14008679号