ubantu14.04 32位下第一个hello world驱动程序

ubantu14.04 32位下第一个hello world驱动程序


平台:ubantu14.04,内核版本: 3.13.0-32-generic


编写驱动程序时,首先必须建立内核源码树,内核源码树我现在的理解就是整个linux内核源代码编译后的形式,即下载源码后,执行make编译后的形式,它是编译驱动的前提。ubuntu系统默认情况下是没有的。先前的内核只需要有一套内核头文件就够了,内核模块编译时需要内核源码树中的目标文件,通过这种方式,可得到一个更加健壮的模块装载器,但也需要这些目标文件存在于内核目录树中。


一.  构造内核源码树 
1. uname -r查看内核版本 ,输出: 3.13.0-32-generic
如果安装系统时,自动安装了源码。在 /usr/src 目录下有对应的使用的版本目录,ubuntu系统默认情况下是没有的,如下所示:
2. ls /usr/src,输出:linux-headers-3.13.0-32,linux-headers-3.13.0-32-generic


2. 查看一下可一下载的源码包(切记不要使用超级用户使用此命令否则……会提示没有此命令)
   执行:apt-cache search linux-source,输出:
   linux-source-3.13.0 - Linux kernel source for version 3.13.0 with Ubuntu patches


3. 执行:sudo apt-get install linux-source-3.13.0
   下载完成后,在/usr/src下会有压缩包,然后解压,解压后生成一个新的目录/usr/src/linux-source-3.13.0
   开始配置内核 选择最快的原版的配置(默认)方式 (我是如此)
 
4. 执行:make oldconfig 
  当然你也可以使用 自己喜欢的配置方式 如 menuconfig , xconfig(必须有GTK环境吧)。


5. 执行:make bzImage
   执行结束后,可以看到在当前目录下生成了一个新的文件: vmlinux


6. 执行:make modules和make modules_install,执行结束之后,会在/lib/modules下生成新的目录/lib/modules/3.13.0-32-generic/,
   由于我主机本身内核版本就为3.13.0-32-generic,所以/lib/modules/3.13.0-32-generic/本身就存在,所以make modules和make modules_install两步就不需要执行了。至此,构造内核源码树完成。


ref: http://blog.chinaunix.net/uid-20723653-id-1886847.html


注意:如果没有建立内核源码树,按下面步骤,虽然能够生成hello.ko,但执行sudo insmod hello.ko后,执行lsmod会没反应,导致系统报告问题,
会导致下次开机或重启时有问题,若启动不了,可以进入recovery模式,执行fsck,我就是执行这样,终于开机了,我也不知道为什么。

我们做linux开发一般在PC机上编译好了,下到板子上去运行,板子上的linux内核和PC机上的linux版本很多时候都是不一样的,比如pc机上的是linux2.6,板子上的是linux3.1,这个时候就要下linux3.1的内核,用它编译的驱动模块在板子上才能加载上,不然会出错。


二,编写hello world程序以及加载驱动
1. 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:
obj-m := hello.o 
KERNELDIR := /lib/modules/3.13.0-32-generic/build
PWD := $(shell pwd) 


modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
--------------------------------------------------------------------
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
这句是Makefile的规则:这里的$(MAKE)就相当于make,-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成ko文件
注意:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules和$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install前面为tab占位符

2. 到hello.c文件目录下执行make,会生成hello.ko文件以及其他相关文件。


3. 执行sudo insmod ./hello.ko加载模块


4. 执行lsmod就可以看到hello模块了


5. sudo rmmod hello

ubantu14.04 32位下第一个hello world驱动程序_第1张图片


注意:上面执行insmod和rmmod时,控制台并没有输出,可以cat /var/log/syslog | grep world查看输出:
Hello, world和Goodbye, cruel world
用printk,内核会根据日志级别,可能把消息打印到当前控制台上,这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是──日志输出级别小于console_loglevel(在内核中数字越小优先级越高)。
#cat /proc/sys/kernel/printk 6 4 1 7
上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。
可用下面的命令设置当前日志级别:
# echo 8 > /proc/sys/kernel/printk
这样所有级别<8,(0-7)的消息都可以显示在控制台上.

ref:http://baike.baidu.com/link?url=_nx7k1zg2s64w8qdFVuxWtskaQmYwmUHqnNoSxeri8Zc0YgebzvRLEyJhscUkYJzLvIqe8LdzmbkxsF7PU3ck_


 hello world模块解析:http://blog.chinaunix.net/uid-26833883-id-4366882.html

你可能感兴趣的:(ubantu14.04 32位下第一个hello world驱动程序)