• Linux内核基础


    操作系统内核模块:

    Linux内核是整体式结构,各个子系统联系紧密,作为一个大程序在内核空间运行。

    image

    Linux内核模块体系结构:

    Linux内核引入内核模块机制。通过动态加载内核模块,使得在运行过程中扩展内核的功能。不需要的时候,卸载该内核模块。

    image

    Linux内核子系统

    image

    写内核程序需要注意:

    image

    Hello模块

    /*hello.c*/

    #include<linux/kernel.h>
    #include<linux/module.h>
    #include<linux/init.h>
    static int __init hello_init(void)
    {
        printk("hello init. ");
        return 0;
    }
    static void __exit hello_exit(void)
    {
        printk("hello exit. ");
    }
    MODULE_INIT(hello_init);
    MODULE_EXIT(hello_exit);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("spron");
    MODULE_DESCRIPTION("hello world modules");

    内核模块的Makefile:
    CONFIG_HELLO_WORLD ?= m     //配置变量,用模块的方式编译
    ifneq ($(KERNELRELEASE),)       //如果这个变量是有定义的话,执行
        hello_world-objs := hello.o  a.o  b.o
        obj-$(CONFIG_HELLO_WORLD) += hello_world.o     //告诉内核要产生的文件为XXX.O
    else
        KERNELDIR = /$(your_kernel_source)/ 内核的源代码的目录     //如:KDIR=/root/LINUX
        PWD := $(shell pwd)  //执行当前目录的命令
        modules:
            $(MAKE) -C $(KERNELDIR) M=$(PWD) modules      //生成内核模块参数为内核源代码目录以及模块所在目录
    endif
    clean:
        rm –rf  *.o  *~ core  .depend .  *.cmd  *.ko  *.mod.c  .tmp_versions
    注意: your_kernel_source,是你的linux kernel源代码的目录

    编译加载/卸载:
    在hello world模块目录上
    #make
    得到hello_world.ko就是产生的内核模块,在评估板上使用 #insmod hello_world.ko 和 #rmmod hello_world 观察控制台输出的结果。

    内核模块证书和内核模块文档说明:
    2.4内核后,引入识别代码是否在GPL许可下发布的机制 。在使用非公开的源代码产品时会得到警告。通过宏MODULE_LICENSE(“GPL”),设置模块遵守GPL证书,取消警告信息。
    MODULE_DESCRIPTION()用来描述模块的用途。
    MODULE_AUTHOR()用来声明模块的作者。
    MODULE_SUPPORTED_DEVICE() 声明模块支持的设备。
    这些宏都在头文件linux/module.h定义。使用这些宏只是用来提供识别信息。

    模块参数:
    module_param(name,type,perm);
        perm是一个权限值,控制谁可以存取模块参数在 sysfs 中的表示。
        perm 被设为 0, 就根本没有 sysfs 项
    这个宏定义应当放在任何函数之外, 典型地是出现在源文件的前面。
    应该总是为变量赋初值。
    宏MODULE_PARM_DESC() 用来注解该模块可以接收的参数。该宏两个参数:变量名和一个对该变量的描述。
    模块可以用这样的命令行加载:./insmod mymodule.ko myvariable=2

    __init、__initdata和__exit、__exitdata
    对于__init、__initdata和__exit、__exitdata的定义位于<linux/init.h>,这些宏定义的作用是告诉编译器将这些函数或者数据放入相应的section中,
    而在模块加载的阶段,.ko文件中的代码和数据的加载区域是根据section来加载的。比如:如果函数的定义中带有__init,那么这个函数的所有代码会被放入.init.text的section中。如果函数的定义中带有__initdata,那么这个函数的所有代码会被放入.init.data的section中。
    之所以要使用这个宏定义,其中一个原因是标记为初始化的函数和数据,表明该函数和数据仅在初始化期间使用。
    在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。
    详细的说明见详细文档下载链接中的“__init,__initdata,__exit,__exitdata.doc文档” 。

    详细文档及代码下载链接: http://download.csdn.net/detail/klcf0220/5760109

  • 相关阅读:
    IO多路复用 IO异步
    你没听说过的协程
    事件驱动和IO操作
    堡垒机前戏——paramiko
    听说过的多进程,多线程到底是什么鬼
    socket套接字
    看见就烦的异常
    struts2值栈内部数据结构详解
    hibernate一级缓存的源码初窥
    使用自定义标签模拟jstl的<c:for each>标签
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3188894.html
Copyright © 2020-2023  润新知