精华内容
下载资源
问答
  • linux内核模块设计.pptx

    2020-02-28 01:53:41
    内核模块概述Linux内核是整体式结构各个子系统联系紧密作为一个大程序在内核空间运行内核模块概述太多的设备驱动和内核功能集成在内核中内核...卸载该内核模块内核模块概述什么是内核模块内核模块是一种没有经过链接
  • Linux内核模块编译

    千次阅读 2018-07-25 19:12:52
    Linux内核模块是一种可被动态加载和卸载的可执行程序。通过内核模块可以扩展内核功能,内核模块通常用于设备驱动、文件系统等。如果没有内核模块,需要向内核添加功能就需要自发代码、重新编译内核、安装新内核等...

    Linux内核模块是一种可被动态加载和卸载的可执行程序。通过内核模块可以扩展内核功能,内核模块通常用于设备驱动、文件系统等。如果没有内核模块,需要向内核添加功能就需要自发代码、重新编译内核、安装新内核等步骤。

    内核空间中不止一个程序试图访问驱动程序模块,导致一个内核块在没有被调用完毕之前又被其他程序调用,这称之炒代码的重入。因此在设计驱动模块的数据结构时要考虑数据结构在多线程环境下不被其他线程破坏,对于共享的数据应该采取加锁的方法保护。

    可以把内核比喻成一个很长的火车,每个车厢就是一个内核模块,内核在运行这个火车就会一直在开动,但是我们想在火车开动的情况下增加新的车厢,这个时候就需要insmod,意思就是往这个长长的火车车厢增加一个内核模块。

     

    1. 下载当前版本的Linux源代码

    #uname -a

     

    apt-cache search linux-source 命令对应的linux内核版本

    apt-get install linux-source-4.4.0 下载对应的linux内核源码

    下载的源码在  /usr/src/

    tar -jxv -f linux-source-4.4.0.tar.bz2 -C /data/weiqifa/

    把源码解压到我的用户目录下

     

    2、编写模块的Makefile和内核模块代码

    ifneq ($(KERNELRELEASE),)  
      
    obj-m :=hello.o  
      
    else  
    KDIR:= /lib/modules/4.4.0-62-generic/build/  
      
    all:  
        make -C $(KDIR) M=$(PWD) modules   
    clean:  
        rm -f *.ko *.o *.mod.o *.mod.c .symvers  
      
    endif
    
    
    hello.c代码
    
    #include <linux/module.h>  
    #include <linux/init.h>  
      
    MODULE_LICENSE("GPL");  
    MODULE_AUTHOR("DAVID");  
    MODULE_DESCRIPTION("Hello world module");  
      
    static int __init hello_init(void)  
    {  
        printk(KERN_ERR "hello world!\n");  
        return 0;  
    }  
    static void __exit hello_exit(void)  
    {  
        printk(KERN_EMERG "hello exit!\n");  
    }  
      
    module_init(hello_init);  
    module_exit(hello_exit); 

    3、编译

    编译后生成如下文件

     

    4、执行命令

     

    5、日志打印

             输入dmesg可以看到内核日志

    喜欢可以关注微信公众号:嵌入式Linux

     
    展开全文
  • 内核模块基础

    2015-12-07 09:37:00
    1. 内核模块是一种没有经过链接,不能独立运行的目标文件,实在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号(函数和变量) 2. 内核模块可以让操作系统内核在需要时载入...

    l  什么是内核模块?

    1. 内核模块是一种没有经过链接,不能独立运行的目标文件,实在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号(函数和变量)

    2. 内核模块可以让操作系统内核在需要时载入和执行,在不需要的时候由操作系统卸载。它们扩展了操作系统内核的功能却不需要重新启动系统

    3. 如果没有内核模块,我们不得不一次又一次重新编译生成单内核操作系统的内核镜像来加入新的功能,这还意味着一个臃肿的内核。

     

    l  模块机制的优缺点

    优点:1.减小内核映像尺寸,增加系统灵活性

          2.节省开发时间;修改内核,不必重新编译整个内核

          3.模块的目标代码一旦被链入内核,作用和静态链接的内核目标代码完全等价

    缺点:1.对系统性能有一定的损失

        2.使用不当会导致系统崩溃

      

    Hello world模块

    #include <linux/init.h>

    #include <linux/module.h>

    #include <linux/kernel.h>

     

    static int __init hello_init(void)

    {

          printk("<1>hello world\n");

          return 0;

    }

     

    static void __exit hello_exit(void)

    {

          printk(KERN_ALERT "hello module exit\n");

    }

     

    module_init(hello_init);

    module_exit(hello_exit);

     

    MODULE_LICENSE("GPL");

    MODULE_AUTHOR("luzheng");

    MODULE_DESCRIPTION("this is my first module");

     

    l  __init和__exit宏

    1.如果该模块被编译进内核,而不是动态加载,则__init的使用会在模块初始化完成后丢弃该函数并回收所占内存

    2.如果该模块被编译进内核,__exit宏将忽略“清理收尾”的函数

    3.这些宏在头文件Linux/init.h定义,用来释放内核占用的内存。例如在启动时看到的信息“Freeint unused kernel memory:236k freed”,正是内核释放这些函数所占用空间时的打印信息。

     

    l  Makefile

    ifneq ($(KERNELRELEASE),)

          obj-m += hello.o

    #     obj-m += startstop.o

    #     startstop-objs := start.o stop.o      /*把两个文件编译成一个模块 */

    else

    KERNELDIR ?= /lib/modules/$(shell uname -r)/build  /*定义内核路径*/

    PWD := $(shell pwd)      /*表示在当前目录下编译*/

    default:

          $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

    endif

    clean:

          rm hello.ko hello.mod.c hello.mod.o hello.o Module.symvers -rf

     

    l  printk

    内核通过 printk() 输出的信息具有日志级别,日志级别是通过在 printk() 输出的字符串前加一个带尖括号的整数来控制的,如 printk("<6>Hello, world!/n");。内核中共提供了八种不同的日志级别,在 linux/kernel.h 中有相应的宏对应。

    #define KERN_EMERG    "<0>"    /* system is unusable紧急事件消息,系统崩溃之前提示,表示系统不可用 */
    #define KERN_ALERT    "<1>"    /* action must be taken immediately报告消息,表示必须立即采取措施 */
    #define KERN_CRIT     "<2>"    /* critical conditions 临界条件,通常涉及严重的硬件或软件操作失败*/
    #define KERN_ERR      "<3>"    /* error conditions 错误条件,驱动程序常用这个来报告硬件的错误*/
    #define KERN_WARNING  "<4>"    /* warning conditions 警告条件,对可能出现问题的情况进行警告*/
    #define KERN_NOTICE   "<5>"    /* normal but significant 正常但又重要的条件,用于提醒*/
    #define KERN_INFO     "<6>"    /* informational 提示信息,如驱动程序启动时,打印硬件信息*/
    #define KERN_DEBUG    "<7>"    /* debug-level messages 调试级别的消息*/

    所以 printk() 可以这样用:printk(KERN_INFO "Hello, world!/n");。

    未指定日志级别的 printk() 采用的默认级别是 DEFAULT_MESSAGE_LOGLEVEL,这个宏在 kernel/printk.c 中被定义为整数 4,即对应KERN_WARNING。

    在 /proc/sys/kernel/printk 会显示4个数值(可由 echo 修改),分别表示当前控制台日志级别、未明确指定日志级别的默认消息日志级别、最小(最高)允许设置的控制台日志级别、引导时默认的日志级别。当 printk() 中的消息日志级别小于当前控制台日志级别时,printk 的信息(要有/n符)就会在控制台上显示。但无论当前控制台日志级别是何值,通过 /proc/kmsg (或使用dmesg)总能查看。另外如果配置好并运行了 syslogd 或 klogd,没有在控制台上显示的 printk 的信息也会追加到 /var/log/messages.log 中。

    char myname[] = "chinacodec/n";
    printk(KERN_INFO "Hello, world %s!/n", myname);

     

    l  写内核程序需要注意

    1. 内核编程时不能访问C库

    2. 内核编程时必须使用GUN C

    3. 内核编程时缺乏像用户空间那样的内存保护机制

    4. 内核编程时浮点数很难使用

    5. 内核只有一个很小的定长堆栈

    6. 由于内核支持异步中断、抢占和SMP,因此必须时刻注意同步和并发

    7. 要考虑可移植性的重要性

     

    l  内核模块参数

    Linux2.6允许用户insmod的时候往内核模块里面传递参数,它主要使用module_param宏定义来实现这一功能。

    module_param的定义可以在include/linux/moduleparam.h文件里面查看到,它的原型为:

    module_param(name, type, perm);

    module_param_array(name, type, nump, perm);

    其中module_param是用来传递变量参数的,module_param_array是用来传递数组参数的。

    name是在模块中定义的变量名称,type是变量的类型,perm是权限掩码,用来做一个辅助的sysfs入口。

    nump是传入数组的数目,是一个int指针。

     

    module_param支持传递的参数类型有:

    bool:布尔型
    invbool:一个布尔型( true 或者 false)值(相关的变量应当是 int 类型). invbool 类型颠倒了值, 所以真值变成 false, 反之亦然.
    charp :一个字符指针值. 内存为用户提供的字串分配, 指针因此设置.
    int:整形
    long:长整形
    short:短整形
    uint:无符号整形
    ulong:无符号长整形
    ushort:无符号短整形
    基本的变长整型值. 以 u 开头的是无符号值. 

     

    perm 字段是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。你应当使用 <linux/stat.h> 中定义的值. 这个值控制谁可以存取这些模块参数在 sysfs 中的表示.当perm为0时,表示此参数不存在 sysfs文件系统下对应的文件节点。 否则, 模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录, 带有给定的权限.。

    权限在include/linux/stat.h中有定义
    比如:
    #define S_IRWXU 00700
    #define S_IRUSR 00400
    #define S_IWUSR 00200
    #define S_IXUSR 00100
    #define S_IRWXG 00070
    #define S_IRGRP 00040
    #define S_IWGRP 00020
    #define S_IXGRP 00010
    #define S_IRWXO 00007
    #define S_IROTH 00004
    #define S_IWOTH 00002
    #define S_IXOTH 00001
    使用 S_IRUGO 参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR 允许 root 来改变参数. 注意, 如果一个参数被 sysfs 修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知. 你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应.

      

    下面看一下实验的例子:

    #include <linux/init.h>  

    #include <linux/module.h>  

    #include <linux/moduleparam.h>  

    ///  

    MODULE_LICENSE("Dual BSD/GPL");  

    char *msg_buf = "Hello world!";  

    int n_arr[] = {1,2,3,4,5};  

    int n = 7;  

    //module_param(n, int, S_IRUSR);  

    module_param_array(n_arr, int, &n, S_IRUSR);  

    module_param(msg_buf, charp, S_IRUSR);  

    ///  

    static __init int hello_init(void)  

    {  

        int i;      

        printk("%s/n", msg_buf);  

        for (i=0; i<n; i++)  

        {  

            printk("n_arr[%d]=%d/n", i, n_arr[i]);  

        }  

        return 0;  

    }  

    ///  

    static __exit void hello_exit(void)  

    {  

        printk("Goodbye, kernel!/n");  

    }  

    module_init(hello_init);  

    module_exit(hello_exit); 

    运行命令:

     sudo insmod hello.ko msg_buf=veryCD

    然后使用dmesg可以查看到printk的输出:

    [35983.685059] veryCD

    [35983.685067] n_arr[0]=1

    [35983.685072] n_arr[1]=2

    [35983.685075] n_arr[2]=3

    [35983.685079] n_arr[3]=4

    [35983.685083] n_arr[4]=5

    [35983.685087] n_arr[5]=7

    [35983.685091] n_arr[6]=1

    可以看出,实现n_arr的长度应该为5,而n为7,驱动里面并没有检测出,n_arr[5],n_arr[6]已经越界了,,,

    但是insmod的时候却是会检测n_arr的长度的,,

    输入命令:

    sudo insmod hello.ko msg_buf=veryCD n_arr=1,2,3,4,5,6

    但是提示出错了,:

    insmod: error inserting 'hello.ko': -1 Invalid parameters

    因为n_arr的数组长度为5,当输入的数组长度小于等于5的时候,insmod可以加载模块成功,

    sudo insmod hello.ko msg_buf=veryCD n_arr=1,2,3

    [36315.732903] veryCD

    [36315.732908] n_arr[0]=1

    [36315.732909] n_arr[1]=2

    [36315.732911] n_arr[2]=3

    可以看出,module_param_array中的nump的值为实际的输入数组参数长度。

    然后当使用insmod加载内核模块,并传递数据参数的时候,系统会自动检测数组的长度,当输入的数组长度小于模块的数组长度时,insmod才会成功。

     

    l  内核模块静态编译

    1. 将.c文件拷贝到/drivers/char/下
    2. 修改/drivers/char下的Kconfig文件
      在Kconfig中增加如下代码:

     

    1. 回到内核根目录下面make menuconfig,发现已经添加进去

     

    编译成模块的话选择<M>或者在下一步写成obj-m += hello.o

    1. 修改/drivers/char下的Makefile文件,增加如下
      obj-$(CONFIG_HELLO)        += hello.o
      当然前提是你的hello.c必须放在当前的目录了
    2. 编译内核

     

    转载于:https://www.cnblogs.com/losing-1216/p/5025259.html

    展开全文
  • 本章导读Linux设备驱动会以内核模块的...一种方法把所有需要的功能都编译到Linux内核中。这会导致两个问题,一生成的内核会很大,二如果要在现有的内核中新增或删除功能,将不得不重新编译内核。有没有另一...
    本章导读

    Linux设备驱动会以内核模块的形式出现,学会编写Linux内核模块编程是学习Linux设备驱动的先决条件。

    4.1 Linux内核模块简介

    Linux内核的整体架构非常庞大,其包含的组件也非常多。怎样把需要的部分都包含在内核中呢?

    一种方法是把所有需要的功能都编译到Linux内核中。这会导致两个问题,一是生成的内核会很大,二是如果要在现有的内核中新增或删除功能,将不得不重新编译内核。

    有没有另一种机制可使得编译出的内核本身并不需要包含所有功能,而在这些功能需要被使用的时候,其对应的代码被动态地加载到内核中呢?

    Linux提供了这样的机制,这种机制被称为模块(Module)。模块具有如下的特点:

    模块本身不被编译入内核映像,从而控制了内核的大小。

    模块一旦被加载,它就和内核中的其他部分完全一样。

    为了使读者初步建立对模块的感性认识,先来看一个最简单的内核模块“Hello World”,如代码清单4.1所示,源代码文件:

    #include <linux/init.h>  

    #include <linux/module.h> 


    #define DRIVER_AUTHOR "xz@vi-chip.com.cn"
    #define DRIVER_DESC   "A sample driver" 

    static int __init hello_init(void)
    {
        printk(KERN_INFO "----hello_init----\n");
        return 0;
    }

    static void __exit hello_exit(void)
    {
        printk(KERN_INFO "----hello_exit----\n");
    }

    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_VERSION("v1.0");
    MODULE_LICENSE("GPL v2");
    MODULE_AUTHOR(DRIVER_AUTHOR);
    MODULE_DESCRIPTION(DRIVER_DESC);

    MODULE_ALIAS(DRIVER_DESC);

    Makefile文件:

    ifeq ($(KERNELRELEASE),)
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
    all:                               
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    clean:                                             
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    else
        obj-m := hello_world.o

    endif

        这个最简单的内核模块只包含内核模块加载函数、卸载函数和对GPL v2许可权限的声明以及一些描述信息,编译它会产生
    hello_world.ko目标文件,通过“sudo insmod hello_world.ko”命令可以加载它,通过“sudo rmmod hello_world”命令可以卸载它,加载时输出“----hello_init----”,卸载时输出“----hello_exit----”。

        内核模块中用于输出的函数是内核空间的printk()而不是用户空间的printf(),printk()的用法和printf()基本相似,但前者可定义输出级别。printk()可作为一种最基本的内核调试手段。

    在Linux中,使用lsmod命令可以获得系统中已加载的所有模块以及模块之间的依赖关系,例如:

    Module                  Size  Used by
    hello_world            16384  0
    intel_rapl             20480  0
    x86_pkg_temp_thermal    16384  0
    intel_powerclamp       16384  0
    coretemp               16384  0
    kvm_intel             172032  0
    joydev                 20480  0
    input_leds             16384  0
    kvm                   548864  1 kvm_intel

    lsmod命令实际上是读取并分析“/proc/modules”文件,与上述lsmod命令结果对应的“/proc/modules”文件如下:

    $ cat /proc/modules

    hello_world 16384 0 - Live 0x0000000000000000 (OE)
    intel_rapl 20480 0 - Live 0x0000000000000000
    x86_pkg_temp_thermal 16384 0 - Live 0x0000000000000000
    intel_powerclamp 16384 0 - Live 0x0000000000000000
    coretemp 16384 0 - Live 0x0000000000000000
    kvm_intel 172032 0 - Live 0x0000000000000000
    joydev 20480 0 - Live 0x0000000000000000
    input_leds 16384 0 - Live 0x0000000000000000
    kvm 548864 1 kvm_intel, Live 0x0000000000000000

    内核中已加载模块的信息也存在于/sys/module目录下,加载hello_world.ko后,内核中将包含/sys/module/hello_world目录,该目录下又有一个refcnt(引用计数)文件和v和一个sections(段)目录,如下:

    ubuntu@ubuntu2018:/sys/module/hello_world$ cd sections/
    ubuntu@ubuntu2018:/sys/module/hello_world/sections$ ls -al
    total 0
    drwxr-xr-x 2 root root    0 May 14 14:03 .
    drwxr-xr-x 5 root root    0 May 14 14:00 ..
    -r--r--r-- 1 root root 4096 May 14 14:03 .exit.text
    -r--r--r-- 1 root root 4096 May 14 14:03 .gnu.linkonce.this_module
    -r--r--r-- 1 root root 4096 May 14 14:03 .init.text
    -r--r--r-- 1 root root 4096 May 14 14:03 .note.gnu.build-id
    -r--r--r-- 1 root root 4096 May 14 14:03 .rodata.str1.1
    -r--r--r-- 1 root root 4096 May 14 14:03 .strtab
    -r--r--r-- 1 root root 4096 May 14 14:03 .symtab

    在/sys/module/hello_world目录下运行“tree–a”可得到如下目录树:

    xiezhi@ubuntu2018:/sys/module/hello_world$ tree -a
    .
    ├── coresize
    ├── holders
    ├── initsize
    ├── initstate
    ├── notes
    │   └── .note.gnu.build-id
    ├── refcnt
    ├── sections
    │   ├── .exit.text
    │   ├── .gnu.linkonce.this_module
    │   ├── .init.text
    │   ├── .note.gnu.build-id
    │   ├── .rodata.str1.1
    │   ├── .strtab
    │   └── .symtab
    ├── srcversion
    ├── taint
    ├── uevent

    └── version

    3 directories, 16 files

    使用modinfo<模块名>命令可以获得模块的信息,包括模块作者、模块的说明、模块所支持的参数以及vermagic:

    modinfo hello_world.ko

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$ modinfo hello_world.ko
    filename:       /home/ubuntu/share/my_work/linux_drivers/three/hello_world.ko
    alias:          A sample driver
    description:    A sample driver
    author:         xz@vi-chip.com.cn
    license:        GPL v2
    version:        v1.0
    srcversion:     C630BE3949B6861A20E54C0
    depends:        
    vermagic:       4.4.0-116-generic SMP mod_unload modversions retpoline 

    modprobe命令比insmod命令要强大,它在加载某模块时,会同时加载该模块所依赖的其他模块。使用modprobe命令加载的模块若以“modprobe -r filename”的方式卸载,将同时卸载其依赖的模块。模块之间的依赖关系存放在根文件系统的/lib/modules/<kernel-version>/modules.dep文件中,实际上是在整体编译内核的时候由depmod工具生成的,它的格式非常简单:

    kernel/lib/cpu-notifier-error-inject.ko: kernel/lib/notifier-error-inject.ko
    kernel/lib/pm-notifier-error-inject.ko: kernel/lib/notifier-error-inject.ko
    kernel/lib/lru_cache.ko:
    kernel/lib/cordic.ko:
    kernel/lib/rbtree_test.ko:
    kernel/lib/interval_tree_test.ko:
    updates/dkms/vboxvideo.ko: kernel/drivers/gpu/drm/drm.ko

    备注:

    使用modprobe命令注意事项:

    要想使用modprobe必须将ko模块文件拷贝到/lib/moudels/uname -r/kernel目录中,然后执行depmod -A,否则无法使用modprobe加载模块。

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$sudo cp hello_world.ko /lib/modules/4.4.0-116-generic/kernel/

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$sudo depmod -A

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$sudo modprobe hello_world(加载内核模块)

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$lsmod | grep hello_world

    hello_world            16384  0

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$ sudo modprobe -r hello_world(卸载内核模块)

    ubuntu@ubuntu2018:~/share/my_work/linux_drivers/three$lsmod | grep hello_world

    展开全文
  • Linux内核是整体性结构,各个子系统紧密联系,上接用户控件,下接硬件,作为一个大程序在内核控件运行。 如果将所有的设备驱动和内核功能都集成在内核中,...①内核模块是一种没有经过链接,不能独立运行的目标文件...

    Linux内核是整体性结构,各个子系统紧密联系,上接用户控件,下接硬件,作为一个大程序在内核控件运行。

    如果将所有的设备驱动和内核功能都集成在内核中,则内核会不断的庞大,对我们的内核裁剪也会带来更大的挑战,为了解决这个问题,Linux内核引入内核模块机制,通过动态加载内核模块,从而实现在运行过程中扩展内核的功能。

    内核模块是什么?

    ①  内核模块是一种没有经过链接,不能独立运行的目标文件,是在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号(函数和变量)。

    ②  内核模块可以让操作系统内核在需要时载入和执行,在不需要时由操作系统卸载。它们扩展了操作系统内核的功能却不需要重新启动系统。

    ③  如果没有内核模块,我们不得不一次又一次重新编译生成单内核操作系统的内核镜像来加入新的功能。这还意味着一个臃肿的内核。

     

    模块机制的优点:

    ①  减小内核映像尺寸,增加系统灵活性;

    ②  节省开发时间;修改内核,不必重新编译整个内核。

    ③  模块的目标代码一旦被链入内核,作用和静态链接的内核目标代码完全等价。

     

    模块机制的缺点:

    ①  对系统性能有一定损失;

    ②  使用不当时会导致系统崩溃;

     

    接下来通过<hello world模块>介绍一下内核模块的实现:

    首先先附上模块的代码(hello_world.c)

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
     
    static int hello_init(void)
    {
        printk("hello world module!\n");
        return 0;
    }
    
    static void hello_exit(void)
    {
        printk("good bye module!\n");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
     
    MODULE_LICENSE("GPL");

    内核模块至少包含两个函数:

    入口函数->初始化函数(xxx_init()):模块加载时,被调用

    出口函数->卸载函数(xxx_exit()):模块卸载时,被调用

    模块的入口函数名和出口函数名可以任意命名,通过宏module_init()申明入口函数,通过宏module_exit()申明出口函数。模块需要包含头文件:#include <linux/module.h>

     

    内核模块证书:2.4内核后,引入识别代码是否在GPL许可下发布的机制。在使用非公开的源代码产品时会得到警告。通过宏MODULE_LICENSE(“GPL”),设置模块遵守GPL证书,取消警告信息。

     

    内核模块的构建:

    管理模块源码方法:①模块源码加入到内核源码树中。② 模块源码饭仔内核源码树之外。

    注:本文介绍的是放在内核源码树外编译。

     

    接下来是Makefile的实现:

           首先附上Makefile的源码:

    KERNEL_DIR = /home/FAN/linux-kernel
     
    all:
        make -C $(KERNEL_DIR) M=`pwd` modules
    
    clean:
        make -C $(KERNEL_DIR) M=`pwd` modules clean
        rm -rf modules.order Module.symvers
    
    obj-m += hello_world.o

    其中:

    1、KERNEL_DIR:参数,赋值内核的位置,例如我的内核源码的路径:/home/fan/linux-kernrl

    2、当终端执行make时,会运行make -C $(KERNEL_DIR) M=`pwd` modules,其中M=`pwd`指向是模块所在的路径。

    3、当终端执行make clean时,会运行下面两条命令,将编译生成的文件删除

    make -C $(KERNEL_DIR) M=`pwd` modules clean

        rm -rfmodules.order Module.symvers

     

    4、obj-m += hello_world.o:

         其中 –m 表示将hello_world.c编译成模块

                         –y 表示将hello_world.c编译进内核镜像中

     

    编译生成文件:

    在终端运行make,则会生成hello_world.ko文件.

    将hello_world.ko发送到板子上,

    然后在板子上运行insmod hello_world.ko,会调用hello_init()函数

                         运行rmmod hello_world.ko,会调用hello_exit()函数

     

    下图为运行结果:

    展开全文
  • 内核模块是一些可以让操作系统内核在需要时载入和执行的代码,同时在不需要的时候可以卸载。这是一个好的功能,扩展了操作系统的内核功能,却不需要重新启动系统,是一种动态加载的技术。 特点:动态加载,随时载入...
  • 内核模块概述

    2009-09-28 11:09:00
     内核模块是一种没有经过链接,不能独立运行的目标文件,是在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号(函数和变量)。内核模块可以让操作系统内核在需要时载入和...
  • 一、简介: Linux内核是一个整体结构,但是通过内核模块的...Linux内核模块是一种可以被内核动态加载和卸载的可执行程序。通过内核模块可以扩展内核的功能,通常内核模块被用于设备驱动、文件系统等。如果没有内核...
  • 概念: 通过在系统运行期间,...内核模块采用ELF(Executableand Linkable Format )格式作为文件的数据组织格式,更具体的讲,内核模块是一种普通的可重定位目标文件。 上图忽略了驱动程序模块中不会用到了program
  • 在目前,内核的设计中,有两种不同的趋势,一种是单内核,另外一种是微内核,简单而言 - 单内核就是一个很大的进程,在运行的时候,是一个单独的二进制映像,模块之间的通信是通过函数调用来实现
  • 什么是内核模块

    2016-04-18 14:52:47
    1、什么是内核模块 Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢? 方法1:把所有组件都编译进内核文件,即zImage或bzImage。 这样会导致一个问题:占用内存过多。   有没有一种...
  • 编译内核模块及交叉编译内核模块

    千次阅读 2020-01-19 12:02:36
    编译内核模块,可以用两种方法. 1. 常规方法,通过make menuconfig 去设置对应的项,将功能编进内核或编成module. 2. 利用内核环境直接从模块源代码编出module 第一种方法菜单操作,不易出错. 第二种方法更简单,实质....
  • Linux内核模块简介 Linux内核的整体结构已经非常庞大,而其包含的组件也非常多。我们怎样把需要的部分都包含在内核中呢? 一种方法把所有需要的功能都编译到Linux内核。这会导致两个问题,一生成的内核会很大...
  • 一种Linux内核模块的单元测试方法【技术领域】[0001]本发明涉及计算机系统...[0003]现有技术的Linux内核模块的单元测试方法通常是利用用户态的单元测试框架完成的,而Linux内核模块是在内核空间运行的,因此,当利用...
  • 编写一个简单的内核模块 (一)实验目的 Linux 操作系统的内核是单一体系结构(monolithic kernel)的,也就是说,整个内核是一个单独的非常大的程序。这样,系统的速度和性能都很好,但是可扩展性和维护性就相对比较...
  • 内核模块

    2012-11-05 23:54:25
    如前所述,Linux内核是一个整体结构,而模块是插入到内核中的插件。尽管内核不是一个可安装模块,但为了方便起见,Linux把内核也看作一个模块。那么模块与模块之间如何进行交互呢,一种常用的方法就是共享变量和函数...
  • Linux内核模块

    2019-04-17 22:09:00
    Linux本身宏内核(单内核),但是又提供了模块这样一种机制,构成了Linux独有的模块特性。 Linux内核模块的特点: (1)模块本身不被编译入内核镜像,从而控制了内核的大小。 (2)模块一旦被加载,它就和内核...
  • linux内核模块

    2017-07-07 09:25:39
    一个模块,可能是一个协议,一个文件系统,一个驱动,一种具体的应用,等等任何东西。也可能是多种东西的组合。内核在运行时,通过动态加载/卸载内核模块,可以动态扩展/删减内核的功能。每个模块在编译时(假设模块...
  • 2.驱动程序是一种内核模块,通常是直接访问硬件的模块 3.应用程序无法直接访问底层,只能进行系统调用。 4.内核模块中不能调用c库函数,只能调用其他内核模块导出的函数。 比如:printk(),在头文件<linux/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,543
精华内容 1,017
关键字:

内核模块是一种