美文网首页
实现Linux中的可加载的内核模块(包含一个内核线程)

实现Linux中的可加载的内核模块(包含一个内核线程)

作者: TsushimaAlice | 来源:发表于2018-04-07 22:44 被阅读0次

操作系统课上老师只用了一页ppt讲了三个kthread的api, 就出了如标题的这么一个问题
顺手就当做之前理论学习的上手实践了(逃


首先给出一段非百分百原创的代码

#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/init.h>

static struct task_struct *test_task;

int threadfuc(void)
{
    int i = 0;
    while(1)
    {
        set_current_state(TASK_UNINTERRUPTIBLE);
        if (kthread_should_stop()) break;
        if (1)
        {
            printk(KERN_INFO "i = %d\n", i);
            i++;
        }
        schedule_timeout(HZ);
    }

    return 0;
}

static int test_init(void)
{
    test_task = kthread_run(threadfuc, NULL, "test_task");
    printk(KERN_INFO"module enter");
    return 0;
}

static void test_cleanup(void)
{
    if(test_task)
    {
        kthread_stop(test_task);
        test_task = NULL;
        printk(KERN_INFO"module remove");
    }
}

module_init(test_init);
module_exit(test_cleanup);

1. 首先是module程序的编写与加载

module程序使用c语言编写
这个程序不需要main入口
module程序使用insmod和rmmod两个命令加载
(加载编译出来的 .ko文件, 下文会提到如何编译
在加载insmod命令的时候

module_init(test_init);

test_init这个函数名作为参数传入, 并且模块程序从test_init处开始运行
同理, 在rmmod的时候

module_exit(test_cleanup);

中的test_cleanup函数执行, 进行清理善后工作.

2. 内核模块程序的编译

同样先给出makefile(完全非原创)(逃
(是可以直接使用的, 可移植性蛮好的(强行

KVERS = $(shell uname -r)
obj-m := task_test.o
build: kernel_modules
kernel_modules:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

姑且先把它当成一个模板来用(真不负责
要改的地方大概只有obj-m 后面的文件名了,改成自己的就可以了
小小的解释一下:

/lib/modules/$(KVERS)/build 指定到已经编译的内核的目录
M=$(CURDIR) 要编译的源文件的目录

具体的解释以后挖个坑以后慢慢填,坑++

3. 内核模块程序的交互

不像命令行程序, 内核模块的交互并不通过printf在命令行里输出结果
在这里介绍一下printf的孪生姐妹printk(太太和小姨子)

printk与printf的差异,是什么导致一个运行在内核态而另一个运行用户态?其实这两个函数几乎是相同的,出现这种差异是因为tty_write函数需要使用fs指向的被显示的字符串,而fs是专门用于存放用户态段选择符的,因此,在内核态时,为了配合tty_write函数,printk会把fs修改为内核态数据段选择符ds中的值,这样才能正确指向内核的数据缓冲区,当然这个操作会先对fs进行压栈保存,调用tty_write完毕后再出栈恢复。总结说来,printk与printf的差异是由fs造成的,所以差异也是围绕对fs的处理。

来源于百度百科

对于上面这个程序, printk的输出可以使用dmesg命令查看, 当然对于这种工具使用管道( | )配合上文字处理工具(tail, more, grep等)来使用就非常舒服了
比如 dmesg | tail -3 就可以查看最后三条记录

当然 , 使用ps auxtop加上grep也是可以的


雷区预警

  • 代码函数中的void不能省略
  • 由于网页上编码格式等问题, 复制下来的代码最好重新抄码一遍

相关文章

  • 1. Linux - 内核模块

    一、什么是内核模块 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable ...

  • Linux驱动之内核模块

    一、Linux内核模块简介 1.1 Linux内核模块介绍 Linux内核的整体结构已经非常庞大,而其包含的组件也...

  • 实现Linux中的可加载的内核模块(包含一个内核线程)

    操作系统课上老师只用了一页ppt讲了三个kthread的api, 就出了如标题的这么一个问题顺手就当做之前理论学习...

  • Linux命令学习手册-insmod

    功能 一个将内核模块加载入内核的简单工具。 描述 insmod 是一个可以将内核模块加载到内核中的轻量级程序,如果...

  • RockPI 4A Linux内核模块

    Linux内核模块除代码实现部分外还需关注:模块定义、链接位置、模块加载和模块优先级。 一、模块定义 Linux内...

  • 编写Linux驱动程序 - 1 简单内核模块

    大多数的Linux驱动程序,都以内核模块的形式,运行在Linux内核中。 内核模块可以通过insmod/rmmod...

  • 如何防止别人卸载内核模块

    1.防卸载内核模块 不论是Windows还是Linux,当我们开发完一个内核模块的时候,内核模块中往往都承担这至关...

  • linux高级命令

    lsmod:查看已加载内核模块 modprobe:加载内核模块;   -a --all :载入所有模块   -c ...

  • 编写一个简单的Linux内核模块

    为了在运行时动态增加和删除某个功能,Linux内核引入了内核模块这一机制,可在内核运行时加载一组目标代码来实现某个...

  • 一个简单的内核模块实现

    一个简单的内核模块实现 前言 这几天因为某些原因,需要学习下Linux内核模块相关的知识,今天刚刚好学习完模块的简...

网友评论

      本文标题:实现Linux中的可加载的内核模块(包含一个内核线程)

      本文链接:https://www.haomeiwen.com/subject/oljuhftx.html