`
mintelong
  • 浏览: 396218 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

内核编程入门(以最为简单的hello.c为例)

阅读更多
内核编程入门,就以最为简单的hello.c为例。
        环境:Redhat   9.0,内核版本2.4.20-8。
        虽然现在2.6.x的内核很早就就发布了,但是毕竟很多公司还在使用2.4.x的内核。作为新手,从2.4.x的内核入手是可行的。原因有如下几条:
        (1)2.4.x比较成熟。可能你遇到的绝大多数问题,网上都有解决方案。在这个过程中,你可以节省大量的时间,同时还可以对比网上的解决方案,加深认识,总结解决问题的方法,调整自己的学习方法和思路。
        (2)事物的发展总不可能是一蹴而就的。了解发展的历程,对深入理解问题有很大的好处。所以在2.4.x的内核的基础上学习2.6.x的内核,就能够体会到2.6.x的内核在哪些方面要出色,或者为什么要采取这种改进技术。相信理论清晰了,即时2.6.x的内核也会容易上手。

        下面总结了第一个内核程序hello.c的学习过程。
(一)第一阶段:尽量简单
/*
  *   hello.c
  */

#define   MODULE
#include   <linux/module.h>

int   init_module(void)
{
                printk( "Hello   World!\n ");
                return   0;
}

void   cleanup_module(void)
{
                printk( "Goodbye!\n ");
} 

执行,出现错误一:
[root@lqm   drivers]# 
 gcc   -c   hello.c

[root@lqm   drivers]#  
insmod   hello.o

hello.o:   kernel-module   version   mismatch
                hello.o   was   compiled   for   kernel   version   2.4.20
                while   this   kernel   is   version   2.4.20-8.
        这是因为内核源代码版本和编译器版本不一致造成的。
(1)编译器版本/usr/include/linux/version.h
#define   UTS_RELEASE   "2.4.20 "
#define   LINUX_VERSION_CODE   132116
#define   KERNEL_VERSION(a,b,c)   (((a)   < <   16)   +   ((b)   < <     +   (c))

(2)内核源代码版本/usr/src/linux-2.4.20-8/include/linux/version.h
/usr/src/linux-2.4.20-8/include/linux
[root@lqm   linux]#   cat   version.h
#include   <linux/rhconfig.h>
#if   defined(__module__smp)
#define   UTS_RELEASE   "2.4.20-8smp "
#elif   defined(__module__BOOT)
#define   UTS_RELEASE   "2.4.20-8BOOT "
#elif   defined(__module__bigmem)
#define   UTS_RELEASE   "2.4.20-8bigmem "
#else
#define   UTS_RELEASE   "2.4.20-8 "
#endif
#define   LINUX_VERSION_CODE   132116
#define   KERNEL_VERSION(a,b,c)   (((a)   < <   16)   +   ((b)   < <     +   (c))
      可以采取修改编译器版本号与内核源代码版本号一致的办法来解决这个问题,即修改/usr/include/linux/version.h中   #define   UTS_RELEASE   "2.4.20 "
为   #define   UTS_RELEASE   "2.4.20-8 "
执行,出现错误二:
[root@lqm   drivers]#   gcc   -c   hello.c
[root@lqm   drivers]#   insmod   hello.o
Warning:   loading   hello.o   will   taint   the   kernel:   no   license
    See   http://www.tux.org/lkml/#export-tainted   for   information   about   tainted   modules
Module   hello   loaded,   with   warnings
[root@lqm   drivers]#   tail   -n   1   /var/log/messages
Jan   30   12:02:08   lqm   kernel:   Hello  
          也就是说出现了no   license的警告。GNU的软件需要有GPL,所以修改源代码如下:
/*
  *   hello.c
  */

#define   MODULE
#include   <linux/module.h>

MODULE_LICENSE( "GPL ");

int   init_module(void)
{
                printk( "Hello   World!\n ");
                return   0;
}

void   cleanup_module(void)
{
                printk( "Goodbye!\n ");
}


        这时没有错误了。写了一个脚本,测试流程自动化:

#!/bin/bash

gcc   -c   hello.c
sleep   1

insmod   hello.o   &&   echo   -e   "Instal   module   -   hello.o\n "
sleep   1
tail   -n   1   /var/log/messages
lsmod   |   grep   "hello "   &&   echo   -e   "Module   hello   has   instaled\n "

rmmod   hello   &&   echo   -e   "Remove   module   -   hello\n "
sleep   1
tail   -n   1   /var/log/messages
lsmod   |   grep   "hello "   ||   echo   "Module   hello   has   removed "



执行结果如下:

[root@lqm   hello]# 
 ./run


Instal   module   -   hello.o 

Jan   30   13:31:29   lqm   kernel:   Hello   World! 

hello   748   0   (unused) 

Module   hello   has   instaled 

Remove   module   -   hello 

Jan   30   13:31:30   lqm   kernel:   Goodbye! 

Module   hello   has   removed
(二)第二阶段:完善,深入一点
/*
  *   hello.c
  */
#ifndef   __KERNEL__
                #define   __KERNEL__
#endif
#ifndef   MODULE
                #define   MODULE
#endif

#include   <linux/kernel.h>   /*printk*/
#include   <linux/module.h>

MODULE_LICENSE( "GPL ");

static   int   init_module(void)
{
                printk( "Hello,   world!\n ");

                return   0;
}

static   void   cleanup_module(void)
{
                printk( "Goodbye!\n ");
}
写Makefile文件如下:
#   Kernel   Programming
#   Shanghai   University,   lhzeng

#   The   path   of   kernel   source   code
INCLUDEDIR   =   /usr/src/linux-2.4.20-8/include/

#   Compiler
CC   =   gcc

#   Options
CFLAGS   =   -D__KERNEL__   -DMODULE   -O   -Wall   -I$(INCLUDEDIR)

#   Target
OBJS   =   hello.o

all:   $(OBJS)

$(OBJS):   hello.c   /usr/include/linux/version.h
                $(CC)   $(CFLAGS)   -c   $ <

install:
                insmod   $(OBJS)

uninstall:
                rmmod   hello

.PHONY:   clean
clean:
                rm   -f   *.o
 

       
写Makefile时应该注意,不要用空格来代替 <TAB> 。否则会出现错误:missing   separator.   Stop.

修改执行脚本run:

#!/bin/bash

#   The   first   step
make   &&   make   install   &&   echo   -e   "Instal   module   -   hello.o\n "
sleep   1
tail   -n   1   /var/log/messages
lsmod   |   grep   "hello "   &&   echo   -e   "Module   hello   has   instaled\n "

#   The   second   step
make   uninstall   &&   echo   -e   "Remove   module   -   hello\n "
sleep   1
tail   -n   1   /var/log/messages
lsmod   |   grep   "hello "   ||   echo   "Module   hello   has   removed "

#   The   last   step
make   clean


执行结果如下:

[root@lqm   hello]#   ./run
gcc   -D__KERNEL__   -DMODULE   -O   -Wall   -I/usr/src/linux-2.4.20-8/include/   -c   hello.c
hello.c:18:   warning:   `init_module '   defined   but   not   used
hello.c:25:   warning:   `cleanup_module '   defined   but   not   used
insmod   hello.o
Instal   module   -   hello.o

Jan   31   13:40:23   lqm   kernel:   Hello, 
hello   728   0   (unused)
Module   hello   has   instaled

rmmod   hello
Remove   module   -   hello

Jan   31   13:40:24   lqm   kernel: 
Module   hello   has   removed
rm   -f   *.o

(三)第三阶段:总结

1、一个内核模块至少应该包括两个函数:

(1)init_module:模块插入内核时调用

(2)cleanup_module:模块移除时调用

        这个简单的程序就是只实现了这两个函数,而且只做了打印信息的工作,没有使用价值。典型情况下,init_module为内核中的某些东西注册一个句柄,相当于模块初始化的工作。cleanup_module则是撤销模块前期的处理工作,使模块得以安全卸载。

2、insmod实现动态加载模块。在当前OS上,动态加载模块以测试硬件等,避免了繁琐的工作。但是,在这种情况下,会出现版本不匹配的情况。另外,要分清楚内核源代码路径和编译器路径的不同,知道在编译时该指定那个路径。第二阶段开始出现过几个错误都是因为默认的路径是编译器路径,而不是内核源代码路径。体会内核模块化带来的好处!

3、应用Make工具来管理项目。即使小,也要训练。在2.4内核和2.6内核下,Makefile的编写会有所不同。只是语法形式的不同,先深入掌握一种,另一种注意一下应该可以避免犯错误。
分享到:
评论

相关推荐

    linux内核编程入门.pdf

    ### Linux内核编程入门知识点概览 #### 一、引言 《Linux内核编程入门》是一本专注于介绍Linux内核编程基础知识和技术的书籍。本书不仅适合初学者了解Linux内核的基本概念,也适合有一定经验的开发人员进一步深入...

    linux内核编程.pdf

    ### Linux内核编程知识点概述 #### 1. Hello, World - **背景**: 在学习编程时,“Hello, World”程序通常作为入门的第一个程序。对于Linux内核编程而言,也是如此。 - **基本结构**: 一个典型的内核模块至少包含...

    linux 内核编程

    《深入探索Linux内核编程:从“Hello, World”到高级功能》 在《Linux内核编程》一书中,作者Ori Pomerantz通过一系列详实的实例和深入的讲解,引导读者逐步掌握Linux内核编程的核心技术。本书不仅适合初学者作为...

    linux内核编程参考及实例代码

    ”内核模块示例,用于介绍如何编写最基本的Linux内核模块,这是内核编程的入门起点。这个例子将展示如何构建、加载和卸载内核模块,以及如何在内核日志中打印信息。 通过这些资料,学习者可以全面了解Linux内核编程...

    linux内核驱动模块模板之hello

    这通常是初学者入门内核编程的第一个练习,因为它涉及到基本的模块入口和出口函数。模块入口函数是`init_module()`,它在模块被加载到内核时执行;退出函数是`cleanup_module()`,在模块被卸载时调用。这两个函数是...

    Linux操作系统下C语言编程入门.pdf

    本文档“Linux操作系统下C语言编程入门.pdf”很可能是针对初学者的一份指南,旨在介绍如何在Linux环境下进行C语言的编写、编译和执行。 Linux是一个开源的操作系统,它为开发者提供了丰富的工具和自由度。使用Linux...

    LINUX内核和驱动编程

    以一个简单的内核模块为例,我们来看一下具体的实现过程: ```c #include &lt;linux/init.h&gt; #include &lt;linux/module.h&gt; MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple module")...

    Linux内核模块编程指南(经典)

    通过对`hello.c`示例的学习,读者可以了解到一个简单的内核模块是如何被创建、编译并加载的。此外,还深入探讨了如何使用`printk`进行信息打印以及设备驱动的基本原理。这些内容对于初学者来说是非常宝贵的入门资料...

    c语言linux系统编程入门

    ### C语言Linux系统编程入门知识点概述 #### 一、Linux下的C语言编程基础 ##### 1. 源程序的编译 - **GCC编译器**: 在Linux环境下,使用GCC(GNU Compiler Collection)作为主要的编译工具。GCC不仅支持C语言,还...

    Linux操作系统下C语言编程入门

    例如,对于一个简单的C语言源文件`hello.c`,可以通过命令`gcc -o hello hello.c`来编译生成一个名为`hello`的可执行文件。 - **Makefile的编写**:当项目中的源文件较多时,手动编译变得繁琐且容易出错。这时就...

    零基础入门C语言-王桂林 -v2-.pdf

    本文档是一份关于C语言基础入门的电子书籍,由王桂林编写,主要面向完全没有编程经验的初学者。书籍内容涵盖了C语言的多个基础知识点,包括编程环境的搭建、Linux基础命令、C语言的基本语法、数据类型、变量、内存...

    linux下c语言编程入门

    ### Linux下C语言编程入门知识点概览 #### 1. Linux程序设计入门——基础知识 - **源程序的编译** - 在Linux环境下,C语言编程的编译工作主要依赖于GNU的`gcc`编译器。通过示例程序`hello.c`,我们可以了解编译...

    linux操作系统下c语言编程入门

    本资源"Linux操作系统下C语言编程入门"旨在为初学者提供一个全面的起点。 首先,你需要了解Linux的基础操作,包括命令行界面(CLI)的使用。在Linux中,一切皆为文件,包括设备、目录和程序。学习常用的Linux命令,...

    hello模块驱动程序

    "hello模块"是一个经典的入门级驱动程序,主要用于帮助初学者理解Linux内核模块的基本工作原理和开发流程。这个压缩包文件包含了一个简单的"hello模块"Linux驱动程序及其对应的Makefile文件,用于在Fedora 14环境下...

    shell编程入门.doc.pdf

    【shell编程入门】 shell编程是Linux系统中一种强大的交互式命令解释器,它不仅用于用户与操作系统之间的交互,还能编写脚本程序实现自动化任务。在Linux环境中,shell扮演着用户界面和操作系统内核之间的桥梁角色...

Global site tag (gtag.js) - Google Analytics