### Rk3399平台下Linux系统调用的实现
#### 标题与描述解析
标题“Rk3399添加Linux系统调用”表明了本文的主要内容是在Rk3399平台上实现Linux系统层的系统调用。Rk3399是一款高性能的ARM处理器,广泛应用于嵌入式设备,特别是Android平台。描述中提到的是在基于Rk3399的Android 7.1平台上实现Linux系统层的系统调用。
#### 核心知识点详解
##### 添加系统调用步骤
1. **找到合适的Kernel C文件**
- 首先需要找到一个能够编译进内核的C文件,例如`fork.c`。这一步是为了确保所添加的系统调用可以被正确地编译并集成到内核中。
2. **添加系统调用函数**
- 在选定的C文件中,使用`SYSCALL_DEFINE0()`宏定义新的系统调用。例如,如果需要添加一个无参数的系统调用,则使用`SYSCALL_DEFINE0()`。
- 这里的`SYSCALL_DEFINE0()`宏表示定义了一个没有参数的系统调用。如果需要添加带参数的系统调用,则需使用`SYSCALL_DEFINE1()`、`SYSCALL_DEFINE2()`等。
3. **添加函数声明**
- 修改`include/linux/syscalls.h`文件,添加新系统调用的声明。这一步是为了让内核识别并处理这个新定义的系统调用。
4. **添加系统调用号**
- 修改`arch/arm64/include/asm/unistd32.h`文件,为新系统调用分配一个唯一的系统调用号。
- 同时需要更新`arch/arm64/include/asm/unistd.h`中的系统调用号总数,确保总数大于新增加的系统调用号。
5. **编译内核**
- 编译更新后的内核,并重新烧录到硬件设备上。
- 使用`arm-linux-gcc`工具链编译相应的应用程序,并将这些程序添加到Rk3399平台上运行的Android系统中。
##### 应用程序示例
示例代码`sys_call.c`展示了如何在用户空间程序中调用自定义的系统调用以及标准的`getpid()`函数。
```c
#include<stdio.h>
#include<unistd.h>
#include<sys/syscall.h>
#include<sys/types.h>
int main() {
pid_t pid;
int in = -1;
pid = syscall(20); // 调用自定义的系统调用20
printf("--->使用syscall(20):pid==%d\n", pid);
pid = getpid(); // 调用标准的getpid()函数
printf("使用getpid:pid==%d\n", pid);
in = syscall(390); // 调用自定义的系统调用390
in = syscall(391); // 调用自定义的系统调用391
return 0;
}
```
##### 系统调用实现分析
系统调用的实现主要涉及内核中的`arch/arm64/kernel/sys32.c`文件。在这个文件中,可以看到`__NR_compat_syscalls`宏定义了兼容的系统调用总数。系统调用表`compat_sys_call_table`中的每一个条目都被初始化为`sys_ni_syscall`(未实现的系统调用),然后通过包含`asm/unistd32.h`来初始化实际使用的系统调用号。
- `__NR_compat_syscalls`定义了系统调用的总数。
- `compat_sys_call_table`数组用于存储所有系统调用的地址,其中每个元素对应一个系统调用号。
- 当应用程序尝试执行某个系统调用时,内核会查找该数组中的相应位置,并调用对应的系统调用处理函数。
在Rk3399平台上实现Linux系统调用需要按照上述步骤逐步操作。这一过程不仅包括在内核级别添加新的系统调用,还需要在用户空间编写相应的应用程序来调用这些系统调用。通过这种方式,可以在Rk3399平台上扩展Linux的功能,实现更加灵活的应用场景。