点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!
5.2.4 内核层:Xenomai系统调用的定义
为了方便对比ARM64 Linux和Xenomai,以系统调用read为例,分别总结各自的表格如下。
根据《5.1.3 内核层:ARM64 Linux系统调用函数的定义》,总结如下。
| ARM64 Linux | 位置与定义 |
| 系统调用号 | include/uapi/asm-generic/unistd.h: #define __NR_read 63 |
| 系统调用函数 | fs/read_write.c: SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) |
| 系统调用表 | arch/arm64/kernel/sys.c: const syscall_fn_t sys_call_table[__NR_syscalls] = { [0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall, #include <asm/unistd.h> }; |
| 系统调用号和系统调用函数插入系统调用表 | include/uapi/asm-generic/unistd.h: __SYSCALL(__NR_read, sys_read) |
作为对比,针对Xenomai总结如下。相比Linux多了一个系统调用模式的定义。
| ARM64 Xenomai | 定义 |
| 系统调用号 | include/xenomai/cobalt/uapi/syscall.h: #define sc_cobalt_read 81 |
| 系统调用函数 | kernel/xenomai/posix/io.c: COBALT_SYSCALL(read, handover, (int fd, void __user *buf, size_t size)) { return rtdm_fd_read(fd, buf, size); } |
| 系统调用表 | kernel/xenomai/posix/syscall.c: #include "syscall_entries.h" static const cobalt_syshand cobalt_syscalls[] = { __COBALT_CALL_NI __COBALT_CALL_ENTRIES #ifdef CONFIG_XENO_ARCH_SYS3264 #include <asm/xenomai/syscall32-table.h> #endif }; |
| 系统调用号和系统调用函数插入系统调用表 | kernel/xenomai/posix/syscall_entries.h: __COBALT_CALL_ENTRIES |
| 系统调用模式 | kernel/xenomai/posix/syscall.c: static const int cobalt_sysmodes[] = { __COBALT_CALL_NFLAGS __COBALT_CALL_MODES }; |
接下来按照表格逐项展开:
(1)系统调用号
系统调用号定义在include/xenomai/cobalt/uapi/syscall.h,文件比较长,这里分别截取头部和尾部两张图。


第21行,包含头文件cobalt/uapi/asm-generic/syscall.h,此头文件中定义了宏定义__COBALT_SYSCALL_BIT(0x10000000)。在用户层通过x8通用寄存器传递Xenomai系统调用号时,总是与__COBALT_SYSCALL_BIT做逻辑或运算。
第139行,定义了宏__NR_COBALT_SYSCALLS,表示Xenomai包含的系统调用号最大数量为128。从第137行可知,实际只用到了0~114。
(2)系统调用函数
kernel/xenomai/posix/io.c:
COBALT_SYSCALL(read, handover,
(int fd, void __user *buf, size_t size))
{
return rtdm_fd_read(fd, buf, size);
}
在kernel/xenomai/posix/io.c中,通过宏COBALT_SYSCALL来定义read系统调用的实现。
kernel/xenomai/posix/syscall.h:
/* Regular (native) syscall handler implementation. */
#define COBALT_SYSCALL(__name, __mode, __args) \
long CoBaLt_ ## __name __args
宏COBALT_SYSCALL展开后,得到函数名为CoBaLt_read。这里的前缀突然用了大小写交替的方式,不知道为什么!
(3)系统调用表
Xenomai系统调用表cobalt_syscalls[]数组的定义,与Linux的系统调用表有异曲同工之妙。

第455行,宏定义__COBALT_CALL_NI的目标,就是把cobalt_syscalls[]数组的所有元素全部初始化,指向CoBaLt_ni函数(直接return -ENOSYS)。相比Linux,系统调用表默认所有元素都指向__arm64_sys_ni_syscall函数。
第456行,宏定义__COBALT_CALL_ENTRIES从字面理解,应该是很多__COBALT_CALL_ENTRY的集合,事实也是如此。__COBALT_CALL_ENTRIES定义在第452包含的头文件syscall_entries.h中。此文件的绝对路径是kernel/xenomai/posix/syscall_entries.h。展开后就是对数组的元素进行赋值,和Linux的套路完全相同。上述宏定义展开的时候,涉及到兼容32位ABI的宏都按空处理。

备注:syscall_entries.h默认是不存在的,是在编译过程中使用脚本gen-syscall-entries.sh处理各个.c文件中的COBALT_SYSCALL宏,生成的一个头文件。
(3)系统调用模式
Xenomai的每个系统调用,都有自己对应的调用模式,定义在数组cobalt_sysmodes[],数组的索引值就是系统调用号。
所以,根据系统调用号,从cobalt_syscalls[]数组可以找到对应的系统调用函数,从cobalt_sysmodes[]数组可以找到系统调用模式。
cobalt_sysmodes[]数组同样定义在kernel/xenomai/posix/syscall.c中。

第462行,宏定义__COBALT_CALL_NFLAGS就是把cobalt_sysmodes[]数组的所有元素全部初始化0。
第463行,宏__COBALT_CALL_MODES定义在第452包含的头文件syscall_entries.h中。此文件的绝对路径是kernel/xenomai/posix/syscall_entries.h。展开后就是对数组的元素进行赋值。宏定义展开的时候,涉及到兼容32位ABI的宏都按空处理。

其中所涉及的__xn_exec_primary、__xn_exec_current等模式的定义,同样定义在kernel/xenomai/posix/syscall.c中。

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!
参考
3662

被折叠的 条评论
为什么被折叠?



