`
mintelong
  • 浏览: 392343 次
  • 性别: 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编程从入门到精通.rar

    第二部分 Linux内核模块编程指南 第1章 Hello, World 第2章 字符设备文件 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 把设备文件用于输入 170 第6章 启动参数 182 第7章 系统调用 185 第8章 阻塞...

    mini2440用户手册

    友善之臂mini2440用户手册 第一章 Mini2440 开发板介绍...........................................................................................................................- 15 -  ...

    宋劲彬的嵌入式C语言一站式编程

    C语言入门 1. 程序的基本概念 1. 程序和编程语言 2. 自然语言和形式语言 3. 程序的调试 4. 第一个程序 2. 常量、变量和表达式 1. 继续Hello World 2. 常量 3. 变量 4. 赋值 5. 表达式 6. 字符类型与字符编码 3. ...

    Android 4游戏编程入门经典

     1.4.1 内核  1.4.2 运行库和dalvik虚拟机  1.4.3 系统库  1.4.4 应用程序框架  1.5 软件开发工具包  1.6 开发人员社区  1.7 设备,设备,设备  1.7.1 硬件  1.7.2 设备的范围  1.8 所有设备之间的兼容性 ...

    Linux编程从入门到精通

    linux内核编程 目 录 雷蒙序 简介 Linux文档工程小组“公告” 译者序 第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 ...

    Linux C 一站式学习

    C语言入门 C语言本质 Linux系统编程 28. 文件与I/O 1. 汇编程序的Hello world 2. C标准I/O库函数与Unbuffered I/O函数 3. open/close 4. read/write 5. lseek 6. fcntl 7. ioctl 8. mmap 29. 文件系统 1. 引言 2. ...

    android游戏编程入门

    android游戏编程入门 《Android4游戏编程入门经典》是2012年清华大学出版社出版的图书,作者是(美)策希纳(Zechner,M.),无(美)格林(Green,R.)。 第1章 Android,后起之秀 1  1.1 Android简介 1  1.2 版本分裂 3 ...

    [14本经典Android开发教程]-8-Linux内核阅读心得体会

    读核感悟 Linux内核启动 从hello world说起 3 读核感悟 Linux内核启动 BIOS 5 读核感悟 Linux内核启动 setup辅助程序 6 读核感悟 Linux内核启动 内核解压缩 8 读核感悟 Linux内核启动 开启页面映射 9 读核感悟 Linux...

    Linux从零入门实战-2019年七月Z线.txt

    知识点2: 安装Linux系统, 以Ubuntu虚拟机为例 知识点3: 购买Linux云主机,以阿里云主机为例 知识点4: Linux目录结构及常用命令 实战项目: 安装Linux虚拟机环境,配置网络及共享文件 第二讲 Linux常用操作命令 ...

    C程序设计语言(第2版·新版中文)

    我们现在见到的大量论述C语言程序设计的教材和专著均以此书为蓝本。原著第1版中介绍的C语言成为后来广泛使用的C语言版本——标准C的基础。人们熟知的“hello,world”程序就是由本书首次引入的,现在,这一程序已经...

    新版Android开发教程.rar

    ANDROID 的推出后可能影响的产业包括移动电信业,软件开发业,手机制造业,在以消费者为核心的状 态 。 对消费者的影响 � 高档手机选择面增加。 � A ndroid 在设计初期就考虑了与现其有业务的融合,改变以往从...

    vc++ 开发实例源码包

    3.为防止ping攻击,一般情况ping数据全部监控 4.监控某端口数据时,不监控ping包 5.数据超过20k将被清空 6.右边窗口停止抓包后显示十六进制数 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘...

    华清远见嵌入式linux应用程序开发技术详解下载(内部资料).rar

    第3章 Linux下的C编程基础   3.1 Linux下C语言编程概述  3.2 进入Vi  3.3 初探Emacs   3.4 Gcc编译器   3.5 Gdb调试器  3.6 Make工程管理器  3.7 使用autotools   3.8 实验内容   本章小结 ...

    黑客反汇编揭秘(第二版).part1.rar

    16.1.1 Adobe Acrobat为那些不循规蹈矩的人提供了什么 320 16.1.2 修改Adobe Acrobat 323 16.1.3 使用打印屏幕功能实施破解 324 16.1.4 尽量多懂几种语言 324 16.1.5 PDF文件结构 324 16.1.6 生成加密密钥 328 ...

    javascript入门笔记

    特点 :将 a 和 b 转换为 二进制,按位比较,对应位置的数字,至少有一位为1的话,那么该为的整体结果就为1,否则为 0 ex : 5 | 3 101 011 ======== 111 结果为 :7 适用场合:任何小数与0 做 按位或的操作...

    嵌入式Linux应用程序开发标准教程(第2版全)

    Linux基础部分从Linux基础、基本操作命令讲起,为Linux初学者能快速入门提供了保证。接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、...

    黑客反汇编揭秘(第二版).part2.rar

    16.1.1 Adobe Acrobat为那些不循规蹈矩的人提供了什么 320 16.1.2 修改Adobe Acrobat 323 16.1.3 使用打印屏幕功能实施破解 324 16.1.4 尽量多懂几种语言 324 16.1.5 PDF文件结构 324 16.1.6 生成加密密钥 328 ...

    windows环境下32位汇编语言程序设计

    本书尝试从编写应用程序的角度,从“Hello,World”这个简单的例子开始到编写多线程、注册表和网络通信等复杂的程序,通过70多个从简单到复杂的例子,逐步深入Win32汇编编程的方方面面。笔者从事汇编编程已经有十几...

    嵌入式Linux应用程序开发详解

    3.1.1 C语言简单回顾 61 3.1.2 Linux下C语言编程环境概述 62 3.2 进入Vi 63 3.2.1 Vi的模式 63 3.2.2 Vi的基本流程 63 3.2.3 Vi的各模式功能键 65 3.3 初探Emacs 66 3.3.1 Emacs的基本操作 ...

Global site tag (gtag.js) - Google Analytics