添加系统调用
添加系统调用的头文件索引
我们要调用syscall是通过unistd提供的一系列系统接口,其中由C提供的接口需要通过修改unistd_64.h
这个文件来指定。
打开是存放内核源码的地方,进入子目录arch/x86/include/generated/uapi/asm/
比如在我的Linux里此文件是位于
/usr/src/linux-4.10.8/arch/x86/include/generated/uapi/asm/
里的
通过使用vim或者自带的gedit打开这个文件,因为打开这个文件需要管理员权限,所以需要在命令前加上sudo。在endif之前添加一个新的系统调用号:
1 #define __NR_qwq 333
333
表示系统调用号,不一定要和前面的连续,只要不重复就行啦,qwq
则是系统调用名。
修改系统调用向量表
在/usr/src/linux-4.10.8/arch/x86/entry/syscalls
中打开syscall_64.tbl
文件,向里面添加:
333 64 qwq sys_qwq
12 //以内核版本为例,我的版本是4.10.8所以是进入linux-4.10.8文件夹//此处的333与你之前添加的系统调用号一致,qwq是调用函数名,sys_qwq是实际的调用函数,这个名字和调用函数名没有关系哦。
添加调用实现
sino大佬博客里这个方法在内核版本4.0以上就不再使用了,都是使用宏定义,如果坚持使用函数声明的办法可能会出错
后就是添加通过调用号要调用到的程序了 打开/usr/src/linux-4.10.8/include/linux/syscalls.h
添加一个函数声明
12 > asmlinkage long sys_qwq(void);>
然后打开/usr/src/linux-4.10.8/kernel/sys.c
,并在结尾添加函数:
DEFINE后面的数字是传入的参数个数,
qwq
为入口地址,注意这里参数类型和参数名字之间均要用,
隔开
传入1个long型数据和一个字符串到内核空间,在内核空间打印完后返回一个1
重新编译
确定所有文件保存后,执行:
然后要重启哦!
使用系统调用
编写一个小程序
新建一个文件 test.cpp 输入以下代码
编译程序
输入命令:
等待执行完之后,程序就编译成功啦
执行程序
输入命令:
屏幕上会打印出 result is 1
因为我们的系统调用返回数字就是1
查看内核输出信息
输入命令:
即可看到内核中输出的printk信息
grep “hello” 为过滤出包含”hello”的信息
此处有坑…如果是在CB里面运行的,记得把运行弹出的shell关掉啊,不然看不到输出消息的…qwq
Printk()会依据日志级别将指定信息输出到控制台或日志文件中,其格式为:
printk(日志级别 “消息文本”);
如 printk(KERN_ALERT”hello,world\n”);
一般情况下,优先级高于控制台日志级别的消息将被打印到控制台,优先级低于控制台日志级别的消息将被打印到messages日志文件中,而在伪终端下不打印任何的信息。
加载模块后,用户可使用 dmesg 命令查看模块初始化函数中的输出信息,如使用 “ dmesg | tail -20 ” 来输出“dmesg”命令的最后 20 行日志。