版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/
什么是系统调用 (syscall)
系统调用是操作系统提供给应用程序的一组接口,允许用户空间程序与内核进行交互。
在 Android(基于 Linux 内核)中,系统调用由 软中断 实现,通常通过 svc 指令(在 ARM 架构中)触发。系统调用会将 CPU 从用户模式切换到内核模式,使得程序可以执行更高权限的操作。
Android 使用的 C 库是 Bionic,它是为移动设备优化的轻量级 C 库。对应的模块为 libc.so。
Bionic 提供了对系统调用的封装。大多数标准库函数(如 printf、malloc、pthread_create)都通过 Bionic 实现,底层调用了相应的系统调用。
在 NDK 目录中可以找到相关的系统调用号定义头文件。例如
<NDK_PATH>\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include\asm-generic\unistd.h

搜索 bionic 模块 可以找到不同CPU架构下的 syscall 实现

在 bionic/libc/arch-arm64/syscalls/ 可以找到 Android 中所有系统调用的汇编代码文件
syscall 在 Android 上的应用场景
系统工具和调试:如 strace、lsof 等工具,通过 syscall 获取系统状态。
安全与反调试:某些安全检测和反调试技术会直接使用 syscall 绕过标准的 libc 函数,以防止被 hook。
嵌入式开发:在一些嵌入式系统中,开发者需要直接控制硬件,这时通常会使用 syscall。
如何在 Android 中使用 syscall
假设我们希望通过 syscall 直接读取文件内容,编写 native 方法代码如下
// 引入必要的头文件
#include <jni.h>
#include <string>
#include <fcntl.h> // 文件控制定义(如 O_RDONLY)
#include <unistd.h> // 系统调用号(如 __NR_openat)
#include <sys/syscall.h> // 系统调用函数
#include <android/log.h>
#define LOG_TAG "syscall-lib.cpp"
// 定义 Android 日志宏,用于输出信息级别日志
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
// 使用 extern "C" 告诉编译器按照 C 语言的方式来编译和链接这个函数
extern "C"
JNIEXPORT jstring JNICALL
Java_com_cyrus_example_syscall_SyscallActivity_readFileWithSyscall(JNIEnv *env, jobject,
jstring path) {
// 将 Java 字符串 (jstring) 转换为 C 字符串 (const char *)
const char *filePath = env->GetStringUTFChars(path, nullptr);
// 使用 syscall 系统调用打开文件
// __NR_openat 是 openat() 系统调用的调用号
// AT_FDCWD 表示使用当前工作目录
//


最低0.47元/天 解锁文章
986

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



