系统调用
因为之前有很多人都直接写要怎么操作,但是没人告诉我怎么找到的这个思路啊,好离谱,人与人的差距怎么这么大。
因此我把找到思路的摸索过程记录下来,给自己一个激励,同时也给学习鸿蒙操作系统没有头绪的同志们提供一个摸索的思路。
想要添加一个系统调用,首先知道要做的由两部分,就是.h文件和.c文件肯定都跑不掉,那鸿蒙还算给力,系统调用部分的名字比较好理解:带syscall的就都是了。
那添加一个系统调用要怎么做呢?
首先,系统调用有两种调用方式:用户层面和系统内核层面。
把openharmony整个文件夹打包下来解压,然后用windows编辑器打开来看,主要是为了可以使用跳转不用自己费劲找。
如果查找syscall.h,会发现有好多同名的,但是,有很多的内容都是这样的
或者,是这样的
一看就是不是正经内容,那正经内容在哪里呢?继续按跳转键就行,直到找到有大段内容的部分。
有两种:一种不知道在干啥:
和另一种一看就……你看,找啥来着,这不就来了吗,自定义系统调用部分注释都告诉我了
总结一下,一共有两个文件需要操作:
/home/book/openharmony/prebuits/lite/sysroot/usr/include/arm-liteos/bits/syscall.h
和
/openharmony/third_party/musl/kernel/obj/include/bits/syscall.h
好的,那既然如此,照猫画虎,开始写一下试试吧。
直接C+V
这里除了把添加了#define __NR_wzsyscall (__NR_OHOS_BEGIN + 21)
还把原来的21给顶下去了为啥啊?
这是因为,__NR_syscallend表示的是自定义系统调用的结束,因此这个必须得是最后一个,也就是,不管你加多少系统调用,这句话只能不断往后排。
然后你发现,这俩有啥需别啊,怎么长得既像又不像的。
实际上,功能差不多,就是一个是内核调用的写法,一个是用户调用的写法。
好的,系统调用号给了,那咋实现呢?得给个接口吧
这就来了。
首先,我们先区分开两种东西:用户自己写的函数和系统内部的函数。
这个需要自己体会了,简单来说就是,用户自己写的是需要调用系统给的接口才能真正有用。
那这个系统给的在哪里呢?就是kernel 文件夹了,这部分是操作系统提供的,如果你只是开发个小程序那是不用改的,直接调用就行,但是咱们加了系统调用,相当于给操作系统添加功能了,所以很显然,得改内核代码:
home/book/openharmony/kernel/liteos_a/syscall/los_syscall.h
解释:
前面的路径home/book/openharmony取决于你把内核代码下载到哪里了
Kernel表示这里是内核代码的实现部分
Liteos_a表示这里是鸿蒙嵌入式内核代码部分,因为我使用开发板做的验证,所以选用这个文件
Syscall/los_syscall.h比较好理解,就是系统调用部分的内核代码的所在地
好了,现在开始写一个自己喜欢的函数名在.h文件里面为自己正名吧:
extern void WzSysCall(UINT32 size);
上面的定义和平时写代码一个c文件搭配一个h文件一样,但这里还有一处,看起来是个类似于查找目录的东西,也有自定义系统调用部分:
home/book/openharmony/kernel/liteos_a/syscall/syscall_lookup.h
对比发现,其实是上面定义的函数整理一下告诉系统,这个我收了,可以用了,该写啥写啥就行。
SYSCALL_HAND_DEF(__NR_wzsyscall, WzSysCall, void, ARG_NUM_1)
好的,.h约定好了接口名,下面就得实现内容了,如果你仔细观察,发现,los_syscall.h里面的函数实现都在同级目录下面的文件夹里面,好的,自己建一个就行。
touch wzsyscall.c
写点什么吧
#include "los_syscall.h"
#include "los_memory.h"
#include "los_printf.h"
void WzSysCall(UINT32 size)
{
UINT32 *memory = 0;
PRINTK("start to allocate memory...... size:%d\n",size);
memory=(UINT32*)LOS_MemAlloc(m_aucSysMem0,size);
if(memory==NULL)
PRINTK("failed!\n");
else
PRINTK("success!\n");
return ;
}
好的,系统内部就改完了,下面编写测试函数
这里我是在openharmony外部自己新建了一个文件夹wzsyscall,为了避免和鸿蒙内核代码混淆。
记得要写Makefile(这个部分后面的博客会讲,这里不是重点,不做赘述)
#include<stdio.h>
#include<syscall.h>
int main()
{
for(int i=1;i<6;i++)
{
syscall(SYS_wzsyscall,20*i);
syscall(SYS_wzsyscall,200*i);
}
return 0;
}
mysyscall: memorytest.c
clang -target arm-liteos --sysroot=/home/book/openharmony/prebuilts/lite/sysroot/ -o $@ $^
clean:
rm -f *.o memorytest
执行make
下面就可以根据需要编译运行和测试啦!
如果把开辟空间时候的数字改大一点:
#include<stdio.h>
#include<syscall.h>
int main()
{
for(int i=1;i<6;i++)
{
syscall(SYS_wzsyscall,20*i);
syscall(SYS_wzsyscall,2000000*i);
}
return 0;
}