linux编译驱动命令 linux编译驱动程序

怎么编译目标机linux设备驱动在宿主机上安装开发工具和下载linux源码(要求版本号和目标机上的linux内核版本一致) 。开发工具主要有gcc、gdb、make等linux编译驱动命令,这些工具在redhat或fc中默认就安装linux编译驱动命令了,在debian或Ubuntu中可以通过下面这个命令安装linux编译驱动命令:
apt-get install build-essential
linux源码可以通过以下几种途径获得linux编译驱动命令:
将源码解压到/usr/src/目录后 , 进入linux-source-(版本号)目录中执行下面几个命令linux编译驱动命令:
make oldconfig
make prepare
make scripts
直接去下载
通过包管理工具下载源码,在debian和Ubuntu中可以通过下面这个命令下载,
apt-get install linux-source-(版本号),下载后的文件在/usr/src目录中,解压到该目录即可
编写Linux驱动程序,以一个最简单的hello.c为例,hello.c的内容如下:
#include "linux/init.h"
#include "linux/module.h"
static int hello_init(void)
{
printk(KERN_ALERT "Hello World linux_driver_module\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbey linux_driver_module\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lpj");
写Makefile文件,一个示例如下,里面各项参数根据实际情况更改:
#sample driver module
obj-m := hello.o
KDIR = /usr/src/linux-source-2.6.24/
all:
$(MAKE) -C $(KDIR) M=$(PWD)
.PHONY:clean
clean:
rm -f *.mod.c *.mod.o *.ko *.o *.tmp_versions
编译,在hello.c和Makefile所在目录下执行 make 即可,编译后在当前目录生成hello.ko文件
加载并测试:加载使用insmod或modprobe命令来实现,如在当前路径执行如下代码:
insmod hello.ko 或 modprobe hello
注意 , 如果在虚拟终端加载内核的话 , 将看不到内核打印信息 , 因为内核打印信息不会输出到虚拟终端,而是输出到/proc/kmsg文件中 , 所以可以通过以下方式查看内核信息:
cat /proc/kmsg 会一直打?。?需要Ctrl-C手动终止
dmesg 或 dmesg | tail -N,N为一数字,表示显示最后N行
卸载:使用rmmod命令卸载驱动模块,如 rmmod hello
如何编写Linux 驱动程序以装载和卸载模块为例:
1、首先输入代码
#include linux/init.h
#include linux/module.h
2、然后输入下方linux编译驱动命令的代码:
static int my_init(void)
{
return0;
}
static void my_exit(void)
3、然后在输入下方linux编译驱动命令的代码:
{
return;
}
module_init(my_init);
module_exit(my_exit);这样就完成了 。
如何编译一个linux下的驱动模块linux下编译运行驱动
嵌入式linux下设备驱动的运行和linux x86 pc下运行设备驱动是类似的,由于手头没有嵌入式linux设备,先在vmware上的linux上学习驱动开发 。
按照如下方法就可以成功编译出hello world模块驱动 。
1、首先确定本机linux版本
怎么查看Linux的内核kernel版本?
'uname'是Linux/unix系统中用来查看系统信息的命令,适用于所有Linux发行版 。配合使用'uname'参数可以查看当前服务器内核运行的各个状态 。
#uname -a
Linux whh 3.5.0-19-generic #30-Ubuntu SMPTue Nov 13 17:49:53 UTC 2012 i686 i686 i686 GNU/Linux
只打印内核版本,以及主要和次要版本:
#uname -r
3.5.0-19-generic
要打印系统的体系架构类型,即的机器是32位还是64位,使用:
#uname -p
i686
/proc/version 文件也包含系统内核信息:
# cat /proc/version
Linux version 3.5.0-19-generic(buildd@aatxe) (gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1) ) #30-UbuntuSMP Tue Nov 13 17:49:53 UTC 2012
发现自己的机器linux版本是:3.5.0-19-generic
2、下载机器内核对应linux源码
到下面网站可以下载各个版本linux源码
如我的机器3.5.0版本源码下载地址为:
下载完后 , 找一个路径解压,如我解压到/linux-3.5/
然后很重要的一步是:执行命令uname -r,可以看到Ubuntu的版本信息是3.5.0-19-generic
。进入linux源码目录,编辑Makefile,将EXTRAVERSION =修改为EXTRAVERSION= -19-generic 。
这些都是要配置源码的版本号与系统版本号,如果源码版本号和系统版本号不一致,在加载模块的时候会出现如下错误:insmod: error inserting 'hello.ko': -1 Invalid module format 。
原因很明确:编译时用的hello.ko的kenerl 不是我的pc的kenerl版本 。
执行命令cp /boot/config-3.5.0-19-generic ./config,覆盖原有配置文件 。
进入linux源码目录,执行make menuconfig配置内核 , 执行make编译内核 。
3、写一个最简单的linux驱动代码hello.c
/*======================================================================
Asimple kernel module: "hello world"
======================================================================*/
#include linux/init.h
#include linux/module.h
MODULE_LICENSE("zeroboundaryBSD/GPL");
static int hello_init(void)
{
printk(KERN_INFO"Hello World enter\n");
return0;
}
static void hello_exit(void)
{
printk(KERN_INFO"Hello World exit\n ");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("zeroboundary");
MODULE_DESCRIPTION("A simple HelloWorld Module");
MODULE_ALIAS("a simplestmodule");
4、写一个Makefile对源码进行编译
KERN_DIR = /linux-3.5
all:
make-C $(KERN_DIR) M=`pwd` modules
clean:
make-C $(KERN_DIR) M=`pwd` clean
obj-m= hello.o
5、模块加载卸载测试
insmod hello.ko
rmmod hello.ko
然后dmesg|tail就可以看见结果了
最后,再次编译驱动程序hello.c得到hello.ko 。执行insmod ./hello.ko,即可正确insert模块 。
使用insmod hello.ko 将该Module加入内核中 。在这里需要注意的是要用 su 命令切换到root用户 , 否则会显示如下的错误:insmod: error inserting 'hello.ko': -1 Operation not permitted
内核模块版本信息的命令为modinfo hello.ko
通过lsmod命令可以查看驱动是否成功加载到内核中
通过insmod命令加载刚编译成功的time.ko模块后,似乎系统没有反应,也没看到打印信息 。而事实上,内核模块的打印信息一般不会打印在终端上 。驱动的打印都在内核日志中,我们可以使用dmesg命令查看内核日志信息 。dmesg|tail
可能还会遇到这种问题insmod: error inserting 'hello.ko': -1 Invalid module format
用dmesg|tail查看内核日志详细错误
disagrees about version of symbolmodule_layout , 详细看这里 。
在X86上我的办法是:
make -C/usr/src/linux-headers-3.5.0-19-generic SUBDIRS=$PWD modules
如何编译linux驱动模块第一步:准备源代码
首先我们还是要来编写一个符合linux格式的模块文件,这样我们才能开始我们的模块编译 。假设我们有一个源文件mymod.c 。它的源码如下:
mymodules.c
1. #include linux/module.h/* 引入与模块相关的宏 */
2. #include linux/init.h/* 引入module_init() module_exit()函数 */
3. #include linux/moduleparam.h /* 引入module_param() */
4
5. MODULE_AUTHOR("Yu Qiang");
6. MODULE_LICENSE("GPL");
7
8. static int nbr = 10;
9. module_param(nbr, int, S_IRUGO);
10.
11. static int __init yuer_init(void)
12.{
13.int i;
14.for(i=0; inbr; i)
15.{
16.printk(KERN_ALERT "Hello, How are you. %d/n", i);
17.}
18.return 0;
19.}
20.
21.static void __exit yuer_exit(void)
22.{
23.printk(KERN_ALERT"I come from yuer's module, I have been unlad./n");
24.}
25.
26. module_init(yuer_init);
27. module_exit(yuer_exit);
我们的源文件就准备的差不多了,这就是一个linux下的模块的基本结构 。第9行是导出我们的符号变量nbr 。这样在你加载这个模块的时候可以动态修改这个变量的值 。稍后将演示 。yuer_init()函数将在模块加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功 。
第二步:编写Makefile文件
首先还是来看看我们Makefile的源文件,然后我们再来解释;
Makefile
obj-m := modules.o#要生成的模块名
modules-objs:= mymod.o#生成这个模块名所需要的目标文件
KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions
ARM平台
Makefile
obj-m= mymod.o
KDIR := /home/workspace2/kernel/linux-2.6.25#如果是用于arm平台,则内核路径为arm内核的路径
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o
在arm板上插入是
insmod mymod
如果出现以下错误
insmod: chdir(/lib/modules): No such file or directory
则运行
mkdir /lib/modules/2.6.25 (与arm内核版本相同)
并将mymod.ko文件复制到该目录下
cp mymod.ko /lib/modules/2.6.25
然后再执行 (insmod 只在/lib/modules/2.6.25目录下查找相关驱动模块)
insmod mymod
现在我来说明一下这个Makefile 。请记住是大写的Makefile而不是小写的makefile;
obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj-m := 模块名.o
modules-objs :这个变量是说明声称模块modules需要的目标文件 格式要求模块名-objs := 目标文件
切记:模块的名字不能取与目标文件相同的名字 。如在这里模块名不能取成 mymod;
KDIR:这是我们正在运行的操作系统内核编译目录 。也就是编译模块需要的环境
M=:指定我们源文件的位置
PWD:这是当前工作路径$(shell)是make的一个内置函数 。用来执行shell命令 。
第三步:编译模块
现在我们已经准备好了我们所需要的源文件和相应的Makefile 。我们现在就可以编译了 。在终端进入源文件目录输入make
运行结果:
make[1]: Entering directory `/usr/src/linux-headers-2.6.24-24-generic'
CC [M] /home/yuqiang/桌面/mymodule/mymodules.o
LD [M] /home/yuqiang/桌面/mymodule/modules.o
Building modules, stage 2.
MODPOST 1 modules
CC/home/yuqiang/桌面/mymodule/modules.mod.o
LD [M] /home/yuqiang/桌面/mymodule/modules.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-24-generic'
第四步:加载/卸载我们的模块
从上面的编译中我可以看到 。已经有一个modules.ko生成了 。这就是我们的模块了 。现在我们就可以来加载了 。
首先在终端输入:sudo insmod modules.ko
现在我们来看看我们的模块加载成功没有呢?
在终端输入:dmesg | tail -12这是查看内核输出信息的意思 。tail -12 显示最后12条;
显示结果如下:
[17945.024417] sd 9:0:0:0: Attached scsi generic sg2 type 0
[18046.790019] usb 5-8: USB disconnect, address 9
[19934.224812] Hello, How are you. 0
[19934.224817] Hello, How are you. 1
[19934.224818] Hello, How are you. 2
[19934.224820] Hello, How are you. 3
[19934.224821] Hello, How are you. 4
[19934.224822] Hello, How are you. 5
[19934.224824] Hello, How are you. 6
[19934.224825] Hello, How are you. 7
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
看到了吧 。我们的模块的初始化函数yuer_init();已经成功运行了 。说明我们的模块已经加载成功;
现在我们再来卸载模块试试看 。
在终端输入:sudo rmmod modules
在终端输入:dmesg | tail -3
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
[20412.046932] I come from yuer's module, I have been unlad.
可以从打印的信息中看到,我们的模块的退出函数已经被执行了 。说明我们的模块已经被成功的卸载了 。到目前位置我们就已经算是对模块的编译到编译运行算是有了一个整体上的认识了 。对于以后深入的学习还是应该有点帮助的 。下面我们将在看看于模块相关的一些简单的操作 。
第五步:加载模块时传递参数
在终端输入:sudo insmod module_name.ko nbr=4
在终端输入:dmesg | tail -6
显示结果如下:
[20800.655694] Hello, How are you. 9
[21318.675593] I come from onefile module, I have been unlad.
[21334.425373] Hello, How are you. 0
[21334.425378] Hello, How are you. 1
[21334.425380] Hello, How are you. 2
[21334.425381] Hello, How are you. 3
这样我们就可以看到在模块加载的时候动态设置了我们的一个变量 。初始化函数中的循环只执行了4次 。
可能你会问我怎么知道一个模块可以设置那些变量呢 。当然,你可以先不设变量加载一次 。然后可以在终端输入ls /sys/module/modules_name/parameters/来查看 。在这里我们是这样输入的
在终端输入:ls /sys/moedle/modules/parameters/
显示结果:
nbr
如果我们的模块加载成功了 。最后我们还可以通过modinfo来查看我们的模块信息 。如下
在终端输入:sudo modinfo modules.ko
显示结果:
filename:modules.ko
license:GPL
author:Yu Qiang
srcversion:20E9C3C4E02D130E6E92533
depends:
vermagic:2.6.24-24-generic SMP mod_unload 586
parm:nbr:int
【linux编译驱动命令 linux编译驱动程序】linux编译驱动命令的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux编译驱动程序、linux编译驱动命令的信息别忘了在本站进行查找喔 。

    推荐阅读