linux内核之旅---"hello world"模块
来源:互联网 发布:位图制作软件 编辑:程序博客网 时间:2024/06/05 16:27
hello world模块
0,模块代码
#include<linux/init.h>
#include<linux/module.h>
//指定代码所使用的许可证
MODULE_LICENSE("Dual BSD/GPL"); //模块采用自由许可证
/* 内核能够识别的许可证
**Dual BSD/DPL BSD/DPL双重许可证
*/
static int hello_init( void ) //模块被装载到内核时调用
{
printk(KERN_ALERT "hello kernel!\n");
return 0;
}
static void hello_exit( void ) //模块被移除内核时调用
{
printk(KERN_ALERT "Goodbye, kernel!");
}
module_init(hello_init); //特殊宏
module_exit(hello_exit);
保存以上代码为 hello.c 文件
1,makefile
makefile文件参考书籍《linux设备驱动程序》
//如果已经定义KERNELRELEASE,则表明是从内核构造系统调用的
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
2,查看效果
$:sudo insmod hello.ko //加载hello.ko到内核
不会有任何东西出现在终端
//记得12.04是有的,一朋友在redhat 6.5上面测试也是有的
$:lsmod | grep hello //查看当前所有的驱动模块
$:remmod hello //移除hello模块
前面说了不会在终端上看见任何东西
查看系统日志
$: cat /var/log/message | grep hello
在终端上显示:
ubuntu kernel: [12299.447211] hello kernel!
或者
$:dmseg | grep hello
在终端上显示:
ubuntu kernel: [12299.447211] hello kernel!
3,谈一谈我遇到的问题
当我保存makefile文件的名字为 makefile时 编译报错!
当改为Makefile 时正确
这是一个疑问
如下文章是我安装编译时参考的:
驱动程序和用户程序可不一样,它是作为一个模块连接到内核模块来运行的,运行在内核空间里面。
所以要运行我们自己构造的模块,需要自己的系统已经配置好内核树,然后把目标模块和内核树连接起来运行!
可以查看一下自己的电脑有没有配置内核树,可以到 /lib/modules/2.6.35-22-generic目录下面,看看有没有build这个文件夹,如果有,说明你已经有内核树了,如果没有,就自己构建内核树吧。
内核树构建过程
安装编译内核所需要的软件(也可不装,除非你要用 make menuconfig,用make oldconfig不要)
sudo apt-get install build-essential kernel-package libncurses5-dev fakeroot
下载内核源码
先查看linux内核版本:$uname -r
网上说用apt-cache search linux-source命令, 会列出一些可选源码包,对准你的内核版本号,选择“with Ubuntu patche”的那个
最后用apt-get install linux-source-2.6.35下载之。解压缩源码包,进入解压后的源码目录。
可是我试了,搜不到,但是还是可以直接用上面的apt-get 命令下载的,但是我下载,也可以直接到这个网址下源代码,这里面有各个版本的内核,从1.0到2.6的,都有。
http://www.at.kernel.org/pub/linux/kernel/
在编译之前我们需要Ubuntu原来内核的一个配置文件,这是我/usr/src目录下的文件预览:ls -al
drwxr-xr-x 4 root root 4096 2010-09-04 21:31 fglrx-8.723.1
drwxr-xr-x 24 root root 4096 2010-09-04 20:35 linux-headers-2.6.35-22
drwxr-xr-x 7 root root 4096 2010-09-04 20:35 linux-headers-2.6.35-22-generic
drwxr-xr-x 25 root root 4096 2010-09-16 21:39 linux-source-2.6.35
-rw-r--r-- 1 root root 65846876 2010-09-01 22:41 linux-source-2.6.35.tar.bz2
现在我们需要/boot目录下的config-2.6.35-22-generic文件,我们把它拷贝到我们刚下好解压的目录,也就是linux-source-2.6.35
sudo cp /boot/config-2.6.35-22-generic /usr/src/linux-source-2.6.35/.config
接下来切换到root用户
sudo -i
cd /usr/src/linux-source-2.6.35
make menuconfig或者直接make oldconfig(无需拷贝.config)
终端会弹出一个配置界面
最后有两项:load a alternative kernel configuration...
save a alternative configuration...
选择load a kernel configuration保存,然后在选择save akernel configuration再保存退出,并退出配置环境。
接下来我们就要开始编译了。
#cd /usr/src/linux-source-2.6.35
#make
记住一定要是管理员帐号运行,这个过程很久,如果你的cpu是双核的可以在make后面加个参数,make -j4.
#make bzImage 执行结束后,可以看到在当前目录下生成了一个新的文件: vmlinux, 其属性为-rwxr-xr-x。
下面就要编译模块了,但是编译模块时可能会出现如下问题编译问题(ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directory
解决方法:
在/usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile 中
ifeq ($(KERNELRELEASE),)# Support for direct Makefile invocation
的前面增加:PWD=$(shell pwd)
也就是在ifeq的上一行增加。
然后再编译模块
#make modules /* 编译 模块 */
#make modules_install 这条命令能在/lib/modules目录下产生一个目录
如果一切顺利,编译过程中不出现什么错误的话,接下来我们就可以开始linux模块的helloworld了。
我在 /home/xxxx/linux_modules/ 目录下创建2个文本文件 hello.c Makefile
//hello.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT"Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
//Makefile
# Makefile2.6(2.6内核专门的Makefile文件)
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := hello.o #param-objs := file1.o file2.o
obj-m := hello.o #obj-m := param.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions #这个伪命令没起作用,待解决,不影响make
.PHONY: modules modules_install clean
endif
#KERNELRELEASE 是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读 取执行else之后的内容,如果 make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C $(KDIR)指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被定义,kbuild也被启动去解 析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及 要生成的目标模块名。param-objs := file1.o file2.o 表示param.o由file1.o与file2.o 连接生成,obj-m := param.o表示编译连接后将生成param.o模块。
需要注意的是makefile的格式$(MAKE)前面要加个tab.
make 编译,不出现错误的话,用ls -al查看linux_modules目录下产生了如下文件:
hello.c hello.mod.c hello.o modules.order
hello.ko hello.mod.o Makefile Module.symvers
其中hello.ko就是可加载的模块文件
现在我们就可以将编译好的模块helloworld加载到内核中去了
#insmod ./hello.ko //这个命令把hello.ko加载到内核
#lsmod|grep hello //lsmod 这个命令可以查看当前所有的驱动模块,结果应该显示hello 680 0
#rmmod hello //这个命令是把hello这个模块移除掉
程序的输出结果可以在(printk 不会输出到终端)
dmesg |grep world
或是/var/log/syslog文件中查看
Hello,World
Goodbye,cruel world
这是程序的输出。
如果在输入insmod ./hello.ko时出现如下错误提示:insmod: error inserting 'hello.ko': -1 Invalid module format
则是因为记载版本号的字符串和当前正在运行的内核模块的不一样,这个版本印戳作为一个静态的字符串存在于内核模块中,叫vermagic,可以从编译模块中间生成的文件helloworld.moc.h中,如果出现这种情况:
1,根据modinfo hello.ko命令查看vermagic的值2,根据uname -r查看内核版本
3,对比上边两步的值是否相同
若相同,我就不知道了
若不同,采用make -C /lib/modules/此处为你内核版本号对应的文件夹/build M=你模块源码的路径 modules
- linux内核之旅---"hello world"模块
- linux内核模块开发之Hello world
- Linux 内核模块之hello world
- Linux 内核模块编程 Hello World 模块
- Linux内核模块开发之Hello world (上)
- Linux---我的第一个内核模块之Hello World
- Linux内核驱动模块编写(Hello,World)
- Linux内核驱动模块编写(Hello,World)
- linux 第一个内核模块Hello World
- linux 第一个内核模块Hello World
- Linux内核模块(hello world)
- linux内核hello world模块编写
- Hellomod , Linux内核模块的Hello World
- hello world 内核模块
- linux内核驱动模块编程框架---(hello world模块)
- linux内核驱动之hello world module
- linux内核编程之hello,world
- 内核模块的hello world!
- Red Hat搭建邮件服务器(sendmail+dovecot+openwebmail+procmail)
- maven 工程简单打包
- 函数调用的执行过程
- 500 OOPS: cannot change directory 500 OOPS: priv_sock_get_cmd Connection closed by remote host.
- windows 下svn服务器的撘建
- linux内核之旅---"hello world"模块
- 2014年总结
- Flume把命令执行结果写入平面文件
- android studio 项目 转换成eclipse
- d3力场Force Layout
- 用MFC实现的路由分组转发模拟系统
- Winforms: DataGridView的显示刷新问题
- del_substr,C和指针,第六章第二题解答
- listview中radiobutton的选择问题