内核是如何运行ko文件的–系统调用


文章目录

  • 内核是如何运行ko文件的--系统调用
  • 什么是系统调用
  • 系统调用的流程
  • 向系统中添加一个系统调用
    • 1.在内核源码中添加自己的服务,需要编译进入内核
    • 2.添加系统调用号
    • 3.编译烧写
    • 4.测试

现在我们己经知道insmod命令做了什么事情,当我们使用insmod命令加载ko文件的时候,会调用系统调用init_module和finit_module。那什么是系统调用呢?

什么是系统调用

系统调用是操作系统扌是供给编程人员的接囗,当编程人员写程序时,因为上层应用不能直接操作硬件,所以就要利用系统调用接囗来请求操作系统的照务,如访问硬件。系统调用是和CPU架进行绑定的。和内核版本也有关系。
回到init_module和finit_module这俩个系统调用就是应用程序调用系统调用,内核就会执行运行ko文件的操作。

系统调用的流程

以为init_module例,原型为:

#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)

syscall函数原型:

long int syscall(long int sysno,.....)

参数sysno为系统调用号,每个系统有一个唯一的系统调用号来标识对应的函数。
…是可变参数,是系统调用所以带的参数。
作用:根据系统调用号,调用相应的系统调用。
那__NR_init_module和个函数绑定了呢?打开include/uapi/asm-generic/unistd.h文件,找到以下代码:

/* kernel/module.c */
#define __NR_init_module 105
__SYSCALL(__NR_init_module, sys_init_module)
#define __NR_delete_module 106
__SYSCALL(__NR_delete_module, sys_delete_module)

__SYSCALL将系统调用号与sys_init_module函数绑定。这里有一个规律,在用户空间
我们使用xxx函数,对应的系统调用的函数就是sys_xxx;
sys_init_module函数定义在kernel/module.h文件中。sys_init_module函数定义是一个宏
定义。如下图所示

SYSCALL_DEFINE3(init_module, void __user *, umod,unsigned long, len, const char __user *, uargs)
{int err;struct load_info info = { };err = may_init_module();if (err)return err;pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",umod, len, uargs);err = copy_module_from_user(umod, len, &info);if (err)return err;return load_module(&info, uargs, 0);
}SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
{int err;struct load_info info = { };err = may_init_module();if (err)return err;pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS|MODULE_INIT_IGNORE_VERMAGIC))return -EINVAL;err = copy_module_from_fd(fd, &info);if (err)return err;return load_module(&info, uargs, flags);
}

我们来看一下这个宏定义。这个宏定义定义在:include/linux/syscall.h中。如下图所示:

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

SYSCALL_DEFlNE3宏定义中的3代表3个参数。这里一共有6个宏定义,所以我们最多可以带6个参数。

__VA_ARGS__等价于void __user *, umod,unsigned long, len, const char __user *, uargs
#define SYSCALL_DEFINE0(sname)                    \SYSCALL_METADATA(_##sname, 0);                \asmlinkage long sys_##sname(void)#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)#define SYSCALL_DEFINEx(x, sname, ...)                \SYSCALL_METADATA(sname, x, __VA_ARGS__)            \__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)                    \asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))    \__attribute__((alias(__stringify(SyS##name))));        \static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));    \asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));    \asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))    \{                                \long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));    \__MAP(x,__SC_TEST,__VA_ARGS__);                \__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));    \return ret;                        \}                                \static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

向系统中添加一个系统调用

步骤

1.在内核源码中添加自己的服务,需要编译进入内核

#include <linux/kernel.h>
#include <linux/syscall.h>
SYSCALL_DEFINE0(helloworld){printk("this is my syscall helloworld\n");return 0;}

2.添加系统调用号

修改include/uapi/asm-generic/unistd.h

vi include/uapi/asm-generic/unistd.h

加入

#define __NR_helloworld 1080
__SYSCALL(__NR_helloworld, sys_helloworld)

修改

#undef __NR_syscalls
#define __NR_syscalls (__NR_helloworld+1)

3.编译烧写

4.测试

#include <stdio.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#define __NR_helloworld 1080
int main(int argc,char *argv[]){syscall(__NR_helloworld);printf("here\n");return 0;
}

内核是如何运行ko文件的--系统调用相关推荐

  1. 内核是如何运行ko文件的--insmod命令

    内核是如何运行ko文件的–insmod命令 文章目录 内核是如何运行ko文件的--insmod命令 insmod详细分析 在正点原子阿尔法开发板中查看insmod使用什么方法: 使用finit_mod ...

  2. 7.荔枝派 zero(全志V3S)-编译内核驱动,生成KO文件

    上面是我的微信和QQ群,欢迎新朋友的加入. 在网上溜了一大圈,发现竟然没人写过荔枝派编译内核驱动的帖子. 或许是我输入的关键字不对 今天特意做了一下这个事情. 1.改kernel makefile 当 ...

  3. kali2022编译Linux内核驱动ko文件

    在Linux环境下编译.ko内核驱动文件(运行于本linux系统,非嵌入式),需要保证/lib/modules/xxx的版本与内核版本保持一致,否则编译后的驱动无法运行! 1.更新内核版本及heade ...

  4. 不同的内核源码编译出来的ko文件,区别到底是什么?

    之前一直在考虑,不同的内核源码编译出来的ko文件,区别到底是什么? 能不能不编译内核加载内核模块呢?最近逆向分析了linux内核ko模块的结构,事实证明,是可以的. 我在这里给大家分享一些我的心得. ...

  5. linux 修改 ko文件内核版本号

    当需要一个ko在一个内核下编译,insmod到另一个内核时, 1.include/config/kernel.release文件中为内核版本号,将其改为所需版本. 2.include/generate ...

  6. linux编译ko文件(不同内核源码版本)

    最近编译内核驱动程序遇到了一些困难,网上下载与我的linux系统相同的版本,编译的时候过不去(每次都是编译到sound文件夹下时提示找不到xxx.c文件),后来经过多次的实验后便把内核换了别的版本作为 ...

  7. Android 编译内核的ko文件

    在开发过程中,我们需要编译android工程的内核KO文件, 一种方法是修改对应模块的Makefile,编译为ko文件,需要指定 make -C 内核源码路径. KSRC := /home/xxx/i ...

  8. ko文件卸载 linux_Linux驱动06 | 为什么使用内核模块?

    一.为什么使用内核模块. 宏内核:简单来说,就是把很多东西都集成进内核,例如linux内核,除了最基本的进程.线程管理.内存管理外,文件系统,驱动,网络协议等等都在内核里面.优点是效率高.缺点是稳定性 ...

  9. linux 提取ko文件,Linux获取so/ko文件版本号教程

    一.需要获取版本号的原因 从使用角度而言,有时只有特定版本的库才支持某些功能,所以我们需要确定库文件版本号. 从安全加固角度而言,有些版本存在漏洞有些版本不存在漏洞,所以我们需要获取版本号以确定当前使 ...

最新文章

  1. keystone连接mysql_3、KeyStone服务部署与验证
  2. 乐峰VS聚美,明星也要吃咸盐
  3. 关于企业应用架构中前置机的作用
  4. springboot获取ApplicationContext的三种方式
  5. 测试dali协议的软件,基于DALI协议的数字照明控制软件的研发
  6. python中的json_python中json的使用
  7. delphi中利用Indy的TIdFtp控件实现FTP协议
  8. 23个Python爬虫开源项目代码Python爬虫开源项目代码
  9. .net api reference中文_在macOS上使用.NET SDK编译 .NET 通用中间语言
  10. python tkinter滚动条不起作用_求助:tkinter中滚动条为什么不能用
  11. Jmeter新手频犯错误之一(登录)
  12. JAVA延迟执行(thread方式和timer方式)
  13. [转载] Python 字典(Dictionary) get()方法
  14. struts 标签logic:iterate用法详解
  15. 护照扫描仪的应用环境解读 SDK数据
  16. 一个故事轻松记忆常见252个英语字根(1~30)
  17. (论文阅读)实例分割之PolarMask
  18. 解决黑苹果无法自动更新的问题,
  19. Python jieba库的介绍与使用
  20. 【附源码】计算机毕业设计JAVA东理咨询交流论坛

热门文章

  1. Android 浏览器插件开发-插件库
  2. 神一样的CAP理论在微服务中是如何应用的?
  3. 【每日一练】原生js仿淘宝主图放大镜功能,附学习源码
  4. drawimage的用法 java_Java Graphics.drawImage方法代码示例
  5. Flex AIR应用的启动闪屏(必须)
  6. 品优购项目记录:day17
  7. 6月27日服务器例行维护公告,2019年06月27日维护公告
  8. c语言宏替换作用,C语言中,宏替换的替换规则
  9. Scrum 中的大项目管理
  10. javascript研发唯美表白神器,程序猿不做单身狗!