内核编程入门,就以最为简单的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内核编程入门知识点概览 #### 一、引言 《Linux内核编程入门》是一本专注于介绍Linux内核编程基础知识和技术的书籍。本书不仅适合初学者了解Linux内核的基本概念,也适合有一定经验的开发人员进一步深入...
### Linux内核编程知识点概述 #### 1. Hello, World - **背景**: 在学习编程时,“Hello, World”程序通常作为入门的第一个程序。对于Linux内核编程而言,也是如此。 - **基本结构**: 一个典型的内核模块至少包含...
《深入探索Linux内核编程:从“Hello, World”到高级功能》 在《Linux内核编程》一书中,作者Ori Pomerantz通过一系列详实的实例和深入的讲解,引导读者逐步掌握Linux内核编程的核心技术。本书不仅适合初学者作为...
”内核模块示例,用于介绍如何编写最基本的Linux内核模块,这是内核编程的入门起点。这个例子将展示如何构建、加载和卸载内核模块,以及如何在内核日志中打印信息。 通过这些资料,学习者可以全面了解Linux内核编程...
这通常是初学者入门内核编程的第一个练习,因为它涉及到基本的模块入口和出口函数。模块入口函数是`init_module()`,它在模块被加载到内核时执行;退出函数是`cleanup_module()`,在模块被卸载时调用。这两个函数是...
本文档“Linux操作系统下C语言编程入门.pdf”很可能是针对初学者的一份指南,旨在介绍如何在Linux环境下进行C语言的编写、编译和执行。 Linux是一个开源的操作系统,它为开发者提供了丰富的工具和自由度。使用Linux...
以一个简单的内核模块为例,我们来看一下具体的实现过程: ```c #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple module")...
通过对`hello.c`示例的学习,读者可以了解到一个简单的内核模块是如何被创建、编译并加载的。此外,还深入探讨了如何使用`printk`进行信息打印以及设备驱动的基本原理。这些内容对于初学者来说是非常宝贵的入门资料...
### C语言Linux系统编程入门知识点概述 #### 一、Linux下的C语言编程基础 ##### 1. 源程序的编译 - **GCC编译器**: 在Linux环境下,使用GCC(GNU Compiler Collection)作为主要的编译工具。GCC不仅支持C语言,还...
例如,对于一个简单的C语言源文件`hello.c`,可以通过命令`gcc -o hello hello.c`来编译生成一个名为`hello`的可执行文件。 - **Makefile的编写**:当项目中的源文件较多时,手动编译变得繁琐且容易出错。这时就...
本文档是一份关于C语言基础入门的电子书籍,由王桂林编写,主要面向完全没有编程经验的初学者。书籍内容涵盖了C语言的多个基础知识点,包括编程环境的搭建、Linux基础命令、C语言的基本语法、数据类型、变量、内存...
### Linux下C语言编程入门知识点概览 #### 1. Linux程序设计入门——基础知识 - **源程序的编译** - 在Linux环境下,C语言编程的编译工作主要依赖于GNU的`gcc`编译器。通过示例程序`hello.c`,我们可以了解编译...
本资源"Linux操作系统下C语言编程入门"旨在为初学者提供一个全面的起点。 首先,你需要了解Linux的基础操作,包括命令行界面(CLI)的使用。在Linux中,一切皆为文件,包括设备、目录和程序。学习常用的Linux命令,...
"hello模块"是一个经典的入门级驱动程序,主要用于帮助初学者理解Linux内核模块的基本工作原理和开发流程。这个压缩包文件包含了一个简单的"hello模块"Linux驱动程序及其对应的Makefile文件,用于在Fedora 14环境下...
【shell编程入门】 shell编程是Linux系统中一种强大的交互式命令解释器,它不仅用于用户与操作系统之间的交互,还能编写脚本程序实现自动化任务。在Linux环境中,shell扮演着用户界面和操作系统内核之间的桥梁角色...