一、前言
最近想学一下kernel和hal,所以买了一块板子,带了个摄像头和屏幕,1100+,学习投资了。这个Android内核定一个系统调用感觉是真的麻烦,主要是有一层bionic C,一开始不熟悉的时候还是花了点时间去配置。
二、kernel修改
include/uapi/asm-generic/unistd.h
系統调用的定义里增加自己的定义,这里是直接集成到arm64了,我发现arm都没有,简单起见所以后面bionic就直接arm64生成代码了。
#define __NR_hello 449
__SYSCALL(__NR_hello, sys_helloworld)
#undef __NR_syscalls
#define __NR_syscalls 450
然后新增一个目录drivers/char/helloworld,新增以下文件,这里的配置是默认的,后面编译刷入就行,这里我不说明刷入了,只介绍代码流程。
├── Kconfig
├── Makefile
├── mysyscall.c
mysyscall.c
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE0(helloworld){
printk("Hello, world my syscall!\n");
return 0;
}
Makefile
obj-$(CONFIG_helloworld) += mysyscall.o
Kconfig
config helloworld
bool "helloworld suppore"
default y
help
helloworld
这里配置完成之后需要上一层在char目录下的kConfig和Makefile中引用这里我也贴一下,分别新增
source "drivers/char/helloworld/Kconfig"
obj-y += helloworld/
kernel刷入后可以使用命令查看系统调用是否配置在kernel中,这里看到已经有了,第一个就是。
三、bionic修改
进入Android源码目录,今日bionic文件夹,下面的路径都是这里的相对路径了。
新增一个头文件libc/include/sys/myhello.h
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
/**
* @file sys/sysinfo.h
* @brief System information.
*/
#include <sys/cdefs.h>
#include <sys/types.h>
__BEGIN_DECLS
/**
* just direct test
*/
int hello();
__END_DECLS
接下来修改libc/SYSCALLS.TXT
末尾新增
# <sys/myhello.h>
int hello() arm64
在libc/libc.map.txt新增hello,我这里直接在LIBC_P下面增加的,这里随便找的增加的,没有文档介绍,理论上到不要求版本的地方也行。这里的P也就是版本要求了。
LIBC_P { # introduced=P
global:
__freading;
__free_hook;
__fseterr;
__fwriting;
__malloc_hook;
__memalign_hook;
__realloc_hook;
aligned_alloc;
endhostent;
endnetent;
endprotoent;
epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
fgets_unlocked;
fputc_unlocked;
fputs_unlocked;
fread_unlocked;
fwrite_unlocked;
getentropy;
getnetent;
getprotoent;
getrandom;
+ hello; #arm64
...
} LIBC_O;
接下来还需要在两个头文件下面增加定义
libc/include/bits/glibc-syscalls.h
#if defined(__NR_hello)
#define SYS_hello __NR_hello
#endif
libc/kernel/uapi/asm-generic/unistd.h 这里要注意内核里定义的数字要和这里一致,剩下的两个内核里没有的直接注释
// #define __NR_futex_waitv 449
// #define __NR_set_mempolicy_home_node 450
#define __NR_hello 449
到这里修改已经结束,进入bionic目录下面,然后mma即可,这里更新so也介绍一下
进入源码目录rk3568_android13/out/target/product/topeet_rk3568/system/apex/
adb push com.android.runtime /system/apex/ 这样就整体替换了。下面开始编写测试程序
四、测试程序编写
Android源码下随便新建一个目录,添加如下文件
├── Android.bp
└── hello.cpp
Android.bp
cc_binary {
name: "hello",
srcs: ["hello.cpp"],
cflags: ["-Werror"],
product_specific: true,
}
hello.cpp
#include <cstdio>
#include <sys/myhello.h>
int main()
{
hello();
return 0;
}
写完之后make hello,我们把可执行文件push到Android目录下执行即可
topeet_rk3568:/data/local/tmp # ls
hello
topeet_rk3568:/data/local/tmp # ./hello
topeet_rk3568:/data/local/tmp #
接着查看内核日志 dmesg
可以看到日志已经成功打印,我们自定义的系统调用已经实现