精华内容
下载资源
问答
  • 静态编译即为将驱动直接编译内核,动态编译即为将驱动编译模块。 而动态编译又分为两种: a -- 内部编译  在内核源码目录内编译 b -- 外部编译  在内核源码的目录外编译 二、具体编译过程分析  ...

    一、模块的编译

           我们在前面内核编译中驱动移植那块,讲到驱动编译分为静态编译动态编译静态编译即为将驱动直接编译进内核,动态编译即为将驱动编译成模块

    而动态编译又分为两种:

    a -- 内部编译

           在内核源码目录内编译

    b -- 外部编译

           在内核源码的目录外编译


    二、具体编译过程分析   

            注:本次编译是外部编译,使用的内核源码是Ubuntu 的源代码,而非开发板所用linux 3.14内核源码,运行平台为X86。

            对于一个普通的linux设备驱动模块,以下是一个经典的makefile代码,使用下面这个makefile可以完成大部分驱动的编译,使用时只需要修改一下要编译生成的驱动名称即可。只需修改obj-m的值。

    ifneq  ($(KERNELRELEASE),)
    obj-m:=hello.o
    else
    KDIR := /lib/modules/$(shell uname -r)/build
    PWD:=$(shell pwd)
    all:
        make -C $(KDIR) M=$(PWD) modules
    clean:
        rm -f *.ko *.o *.symvers *.cmd *.cmd.o
    endif


    1、makefile 中的变量

        先说明以下makefile中一些变量意义:

    (1)KERNELRELEASE           在linux内核源代码中的顶层makefile中有定义

    (2)shell pwd                             取得当前工作路径

    (3)shell uname -r                    取得当前内核的版本号

    (4)KDIR                                     当前内核的源代码目录。

    关于linux源码的目录有两个,分别为

     "/lib/modules/$(shell uname -r)/build"

    "/usr/src/linux-header-$(shell uname -r)/"

           但如果编译过内核就会知道,usr目录下那个源代码一般是我们自己下载后解压的,而lib目录下的则是在编译时自动copy过去的,两者的文件结构完全一样,因此有时也将内核源码目录设置成/usr/src/linux-header-$(shell uname -r)/。关于内核源码目录可以根据自己的存放位置进行修改。

    (5)make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

    这就是编译模块了:

    a -- 首先改变目录到-C选项指定的位置(即内核源代码目录),其中保存有内核的顶层makefile;

    b -- M=选项让该makefile在构造modules目标之前返回到模块源代码目录;然后,modueles目标指向obj-m变量中设定的模块;在上面的例子中,我们将该变量设置成了hello.o。


    2、make 的的执行步骤

    a -- 第一次进来的时候,宏“KERNELRELEASE”未定义,因此进入 else;

    b -- 记录内核路径,记录当前路径;

           由于make 后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行。默认执行all这个规则

    c -- make -C $(KDIR) M=$(PWD) modules

         -C 进入到内核的目录执行Makefile ,在执行的时候KERNELRELEASE就会被赋值,M=$(PWD)表示返回当前目录,再次执行makefile,modules 编译成模块的意思

         所以这里实际运行的是

         make -C /lib/modules/2.6.13-study/build M=/home/fs/code/1/module/hello/ modules

    d -- 再次执行该makefile,KERNELRELEASE就有值了,就会执行obj-m:=hello.o

         obj-m:表示把hello.o 和其他的目标文件链接成hello.ko模块文件,编译的时候还要先把hello.c编译成hello.o文件


    可以看出make在这里一共调用了3次

       1)-- make
       2)-- linux内核源码树的顶层makedile调用,产生。o文件
       3)-- linux内核源码树makefile调用,把.o文件链接成ko文件


    3、编译多文件

    若有多个源文件,则采用如下方法:

    obj-m := hello.o

    hello-objs := file1.o file2.o file3.o


    三、内部编译简单说明

            如果把hello模块移动到内核源代码中。例如放到/usr/src/linux/driver/中, KERNELRELEASE就有定义了。

         在/usr/src/linux/Makefile中有KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)。

    这时候,hello模块也不再是单独用make编译,而是在内核中用make modules进行编译,此时驱动模块便和内核编译在一起。

    展开全文
  • 转载地址:...静态编译即为将驱动直接编译内核,动态编译即为将驱动编译模块。而动态编译又分为两种:a -- 内部编译 在内核源码目录内编译b -- 外部编译 在内核源...

    转载地址:https://blog.csdn.net/zqixiao_09/article/details/50838043

    一、模块的编译

           我们在前面内核编译中驱动移植那块,讲到驱动编译分为静态编译动态编译静态编译即为将驱动直接编译进内核,动态编译即为将驱动编译成模块

    而动态编译又分为两种:

    a -- 内部编译

           在内核源码目录内编译

    b -- 外部编译

           在内核源码的目录外编译


    二、具体编译过程分析   

            注:本次编译是外部编译,使用的内核源码是Ubuntu 的源代码,而非开发板所用linux 3.14内核源码,运行平台为X86。

            对于一个普通的linux设备驱动模块,以下是一个经典的makefile代码,使用下面这个makefile可以完成大部分驱动的编译,使用时只需要修改一下要编译生成的驱动名称即可。只需修改obj-m的值。

    ifneq  ($(KERNELRELEASE),)
    obj-m:=hello.o
    else
    KDIR := /lib/modules/$(shell uname -r)/build
    PWD:=$(shell pwd)
    all:
        make -C $(KDIR) M=$(PWD) modules
    clean:
        rm -f *.ko *.o *.symvers *.cmd *.cmd.o
    endif


    1、makefile 中的变量

        先说明以下makefile中一些变量意义:

    (1)KERNELRELEASE           在linux内核源代码中的顶层makefile中有定义

    (2)shell pwd                             取得当前工作路径

    (3)shell uname -r                    取得当前内核的版本号

    (4)KDIR                                     当前内核的源代码目录。

    关于linux源码的目录有两个,分别为

     "/lib/modules/$(shell uname -r)/build"

    "/usr/src/linux-header-$(shell uname -r)/"

           但如果编译过内核就会知道,usr目录下那个源代码一般是我们自己下载后解压的,而lib目录下的则是在编译时自动copy过去的,两者的文件结构完全一样,因此有时也将内核源码目录设置成/usr/src/linux-header-$(shell uname -r)/。关于内核源码目录可以根据自己的存放位置进行修改。

    (5)make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

    这就是编译模块了:

    a -- 首先改变目录到-C选项指定的位置(即内核源代码目录),其中保存有内核的顶层makefile;

    b -- M=选项让该makefile在构造modules目标之前返回到模块源代码目录;然后,modueles目标指向obj-m变量中设定的模块;在上面的例子中,我们将该变量设置成了hello.o。


    2、make 的的执行步骤

    a -- 第一次进来的时候,宏“KERNELRELEASE”未定义,因此进入 else;

    b -- 记录内核路径,记录当前路径;

           由于make 后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行。默认执行all这个规则

    c -- make -C $(KDIR) M=$(PWD) modules

         -C 进入到内核的目录执行Makefile ,在执行的时候KERNELRELEASE就会被赋值,M=$(PWD)表示返回当前目录,再次执行makefile,modules 编译成模块的意思

         所以这里实际运行的是

         make -C /lib/modules/2.6.13-study/build M=/home/fs/code/1/module/hello/ modules

    d -- 再次执行该makefile,KERNELRELEASE就有值了,就会执行obj-m:=hello.o

         obj-m:表示把hello.o 和其他的目标文件链接成hello.ko模块文件,编译的时候还要先把hello.c编译成hello.o文件


    可以看出make在这里一共调用了3次

       1)-- make
       2)-- linux内核源码树的顶层makedile调用,产生。o文件
       3)-- linux内核源码树makefile调用,把.o文件链接成ko文件


    3、编译多文件

    若有多个源文件,则采用如下方法:

    obj-m := hello.o

    hello-objs := file1.o file2.o file3.o


    三、内部编译简单说明

            如果把hello模块移动到内核源代码中。例如放到/usr/src/linux/driver/中, KERNELRELEASE就有定义了。

         在/usr/src/linux/Makefile中有KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)。

    这时候,hello模块也不再是单独用make编译,而是在内核中用make modules进行编译,此时驱动模块便和内核编译在一起。



    展开全文
  • linux kernel 的内核模块进行编译开发的时候,很容易会遇到一个问题就是模块代码使用的内核版本和当前系统的内核版本不一致。 而我们进行开发时导入#include <linux/*.h> #include *.h> #include *.h>具体就是...

    1。对linux kernel 的内核模块进行编译开发的时候,很容易会遇到一个问题就是模块代码使用的内核版本和当前系统的内核版本不一致。
    而我们进行开发时导入

    #include  <linux/*.h>   
    #include  <asm/*.h> 
    #include  <scsi/*.h>

    具体就是导入的就是/usr/src/kernel/版本号/include/下的
    linux,
    asm,
    scsi,
    这三个文件夹下的文件。所以当我们遇到模块代码使用的函数版本和当前的内核版本不一致时。可以下载模板代码对应的内核源代码。放到/usr/src/文件夹下,然后在/usr/src/kernel/版本号/include/下建立几个软链接,例如:

    ln -s /usr/src/linux-3.12.6/include/asm-generic myasm
    ln -s /usr/src/linux-3.12.6/include/linux mylinux
    ln -s /usr/src/linux-3.12.6/include/scsi myscsi

    然后在模块代码中导入:

    #include  <mylinux/*.h>   
    #include  <myasm/*.h> 
    #include  <myscsi/*.h>

    这样就可以解决内核版本不一致的问题了。

    2.编译模块后,进行insmod操作,会提示insmod: ERROR: could not insert module *.ko: Unknown symbol in module 类似的错误提示,这时候可以用dmesg查看更加详细的信息。

    展开全文
  • 开发内核驱动和文件系统的人来说,经常需要编译某个内核模块。 当然从编译角度,有built-in kernel module和external kernel module之分。 怎么编译一个外部内核模块,google一下“hello world kernel module ...

    对开发内核驱动和文件系统的人来说,经常需要编译某个内核模块。 当然从编译角度,有built-in kernel module和external kernel module之分。 怎么编译一个外部内核模块,google一下“hello world kernel module Makefile”吧。 这里我说下编译内核自带模块的坑... 我用的是SUSE Linux

    安装源代码包和开发包 #zypper in kernel-source kernel-devel

    开发包里面放的是头文件和Makefile文件,用RPM命令来查看下: # rpm -qa|grep kernel-devel

    kernel-devel-4.1.27-27.1.noarch

    # rpm -ql kernel-devel-4.1.27-24.1.noarch|more

    /usr/share/doc/packages/kernel-source-4.1.27-24

    /usr/share/doc/packages/kernel-source-4.1.27-24/README.SUSE

    /usr/share/doc/packages/kernel-source-4.1.27-24/config-options.changes.txt

    /usr/src/linux

    /usr/src/linux-4.1.27-24

    /usr/src/linux-4.1.27-24/Documentation

    /usr/src/linux-4.1.27-24/Documentation/DocBook

    /usr/src/linux-4.1.27-24/Documentation/DocBook/Makefile

    ....

    重要参考文件

    #ls -l /usr/src/linux/README.SUSE

    lrwxrwxrwx 1 root root 61 Dec 31 10:41 /usr/src/linux/README.SUSE -> ../../share/doc/packages/kernel-source-3.12.49-11/README.SUSE

    这个文档介绍编译内核以及模块所需的软件包,概念,方法和步骤。 基本上也适用于其他Linux发型版。

    贴出相关的一段:

    The second method involves the following steps:

    (1)  Install the kernel-devel package.

    (2)  Install the kernel-$FLAVOR-devel package. This is necessary for

    symbol version information (CONFIG_MODVERSIONS).

    (3)  Compile the module(s) by changing into the module source directory

    and typing ``make -C /usr/src/linux-obj/$ARCH/$FLAVOR M=$(pwd)''.

    Substitute $ARCH and $FLAVOR with the architecture and flavor

    for which to build the module(s).

    If the installed kernel sources match the running kernel, you

    can build modules for the running kernel by using the path

    /lib/modules/$(uname -r)/build as the -C option in the above

    command. (build is a symlink to /usr/src/linux-obj/$ARCH/$FLAVOR).

    (4)  Install the module(s) with

    ``make -C /usr/src/linux-obj/$ARCH/$FLAVOR M=$(pwd) modules_install''.

    3.坑

    但是按照上面的步骤总是编译不出来.ko内核模块, 原因是当前的发行版默认没有打开ocfs2模块编译选项:

    eric1211:/usr/src/linux/fs/ocfs2 # make -C /lib/modules/3.12.49-11-default/build M=`pwd` modules

    make: Entering directory '/usr/src/linux-3.12.49-11-obj/x86_64/default'

    make[1]: Entering directory `/usr/src/linux-3.12.49-11-obj/x86_64/default'

    Building modules, stage 2.

    MODPOST 0 modules

    make: Leaving directory '/usr/src/linux-3.12.49-11-obj/x86_64/default'

    原因是配置文件默认没有选择OCFS2,所以要手动make menuconfig,把ocfs2选上, 再试就可以了。具体步骤:

    cd /usr/src/linux

    make menuconfig 选择ocfs2

    cd /usr/src/linux/fs/ocfs2

    make -C /lib/modules/`uname -r`/build M=`pwd` modules

    展开全文
  • 编译linux内核模块

    2011-09-06 20:10:00
    开发内核模块往往第一步的编译环境设置最容易出错,需要安装的主要有build-essential, 对应版本的linux-header。 然后就是Makefile的写法 1 obj-m := hello.o2 # 网上很多是自己下载源码,然后用的是3 # KDIR :=...
  • 静态编译即为将驱动直接编译内核,动态编译即为将驱动编译模块。 而动态编译又分为两种: a -- 内部编译 在内核源码目录内编译 b -- 外部编译 在内核源码的目录外编译 二、具体编译过程分析 注:本次...
  • 如果预设核心忘记加入某个功能,而且该功能可以编译成为模块,不过, 预设核心却也没有将该项功能编译成为模块,不能使用时,该如何是好?如果 Linux 核心原始码并...本文将为大家解析Linux系统单一内核模块编译过程。
  • 1.编译内核模块的编译器 \qquad编译器:gcc 交叉编译器 2.编写编译内核模块的Makefile \qquad内部编译内核模块的源文件放在内核源码中进行编译,需要修改内核中的kconfig,Makefile,make menuconfig \qquad静态...
  • I'm trying to configure Eclipse for developing Linux Kernel Modules under Ubuntu. So far I've added to Properties > Paths and Symbols > Includes > GNU C headers from directory /usr/src/'uname...
  • 主要从模块开发中的常用指令、内核模块程序的结构、模块使用计数以及模块的编译等角度对内核模块进行介绍。在Linux系统开发过程中,以模块的形式开发其重要性不言自明,而在嵌入式设备驱动开发中将驱动程序以模块的...
  • linux内核模块编译

    千次阅读 2014-05-14 09:47:44
    linux内核模块编译引言 为了清晰的编译Linux内核,内核编译系统使用Kbuild规则对编译的过程以及依赖进行规约。在内核模块编译中,为了保持与内核源码的兼容以及传递编译链接选项给GCC,也使用Kbuild规则。 ...
  • 本篇文章中只讨论linux内核模块编译的makefile,linux内核makefile总览可以参考另一篇博客:linux内核makefile概览 本篇博客参考官方文档。 linux内核使用的是kbuild编译系统,在编译可加载模块时,其makefile的风格...
  • Linux内核支持动态加载或卸载模块。这种机制使得不用重新编译内核就可以方便地扩展内核功能,也减小了内核镜像...本文通过一个”hello world”级别的内核模块,来展示内核模块如何开发。 首先,来看内核模块的操作命
  • 配置交叉编译环境见《Android内核开发 Goldfish Linux Kernel编译及安卓虚拟机测试》 Makefile文件 注意Linux kernel源码目录需要提前编译,否则内核模块编译出错。
  • linux内核模块开发

    2017-04-02 21:55:58
    linux内核模块开发 什么是内核模块?  linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用需要的组件呢?  方法一:把所有的组件编译进内核文件,但这样会导致生成的内核文件过大和调整组件不方便。...
  • 内核模块编译: 如果内核是加载到主机上的Linux系统中,即使用主机上的内核编译,Makefile文件为: ifneq ($(KERNELRELEASE),) obj-m:=hello.o else KDIR := /lib/modules/$(shell uname -r)/build PWD:=$...
  • Ubuntu上开发编译内核模块以及调试内核模块,并查看printk打印的消息   前言:在开发中,为了方便,其实我们是可以先在ubuntu运行和测试内核模块,测试好了再用交叉编译到ARM设备上运行。下面就介绍一下方法和...
  • Linux内核模块开发

    2019-06-03 21:38:51
    1.LINUX内核模块基础 1.1 什么是内核模块Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢?方法1:把所有的组件都编译进内核文件,即:zImage或bzImage,但这样会导致一个问题:占用...
  • 前不久导师要求交叉编译一个基于arm平台开发内核模块来练手,在网上查了很多资料才弄出来,于是将这些零散的信息综合起来给和我一样的入门人员了解。水平有限,请谅解~1.安装arm-none-linux-gnueabi交叉编译器很多...
  • 编写Java程序调用内核模块 功能为向内核模块虚拟设备写字符串,再从内核模块虚拟设备读出字符串长度。 编译加载内核模块 见《 Android内核开发 Linux C编程调用内核模块设备驱动》
  • 答:linux是由用户空间和内核空间组成的 为什么要划分用户空间和内核空间? 答:有关CPU体系结构,各处理器可以有多种模式,而LInux这样的划分是考虑到系统的 安全性,比如X86可以有4种模式RING0~RING3 RING0...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 794
精华内容 317
关键字:

linux编译开发内核模块

linux 订阅