A. linux中编写了内核模块的C源程序之后怎么编写makefile文件的内容
make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。
首先,我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是:
1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。
一、Makefile的规则
在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。
target ... : prerequisites ...
command
...
...
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
这
是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说
白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是
Makefile的规则。也就是Makefile中最核心的内容。
说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。呵呵。还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。:)
二、一个示例
正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。
edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
反
斜杠(/)是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,
然后在该目录下直接输入命令“make”就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make
clean”就可以了。
在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件
(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件
edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。
在定义好依赖关系
后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命
令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的
日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。
这里要说明一点的是,clean不是一个文件,它只不过
是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。
要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编
译无关的命令,比如程序的打包,程序的备份,等等。
B. Linux动态模块怎样编译
这个需要编写Makefile文件
首先说一下你的程序有错误:下面这个是我改的,
first.c:
#include<linux/mole.h>
#include<linux/init.h>
static int __init hello_init(void) {
printk(KERN_ALERT "Hello,kernal\n");
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_ALERT "Goodbye,kernal\n");
}
MODULE_LICENSE( "GPL" );
mole_init(hello_init);
mole_exit(hello_exit);
对于你这个程序,我写了一份:
obj-m := first.o #这个是要中间文件
Kernel_path=/usr/src/linux-headers-$(shell uname -r) #内核存在的路径
all:
make -C $(Kernel_path) M=$(PWD) moles
clean:
make -C $(Kernel_path) M=$(PWD) clean
像你的就该为
Kernel_path=/usr/src/linux-headers-$(shell uname -r)/build
保存后make,ok!
C. linux中用C语言编写完模块后怎么编写makefile文件
1、先写Makefile编译出***.ko文件
模板如下,保存到命名为Makefile文件里,放到你代码专的同级目录下
TARGET=my_proc.ko
LINUXDIR=/lib/moles/$(shell uname -r)/build
PWD=$(shell pwd)
obj-m :=
obj-m += my_proc.o
all: $(TARGET)
$(TARGET): $(OBjs)
make -C $(LINUXDIR) SUBDIRS=$(PWD) moles
clean:
rm -f moles.order Mole.symvers $(TARGET) *.mod.c *.o
rm -rf .tmp_versions .mod* Mole.markers
2、属make
3、root权限下用命令插入模块
insmod my_proc.ko
4、可以用你写的应用程序打开、操作模块了
5、查看模块命令
lsmod
cat /proc/moles
modinfo my_proc.ko
6、root下卸载模块
rmmod
D. 如何编译linux驱动模块
第一步:准备源代码
首先我们还是要来编写一个符合linux格式的模块文件,这样我们才能开始我们的模块编译。假设我们有一个源文件mymod.c。它的源码如下:
mymoles.c
1. #include <linux/mole.h> /* 引入与模块相关的宏 */
2. #include <linux/init.h> /* 引入mole_init() mole_exit()函数 */
3. #include <linux/moleparam.h> /* 引入mole_param() */
4
5. MODULE_AUTHOR("Yu Qiang");
6. MODULE_LICENSE("GPL");
7
8. static int nbr = 10;
9. mole_param(nbr, int, S_IRUGO);
10.
11. static int __init yuer_init(void)
12.{
13. int i;
14. for(i=0; i<nbr; 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 mole, I have been unlad./n");
24.}
25.
26. mole_init(yuer_init);
27. mole_exit(yuer_exit);
我们的源文件就准备的差不多了,这就是一个linux下的模块的基本结构。第9行是导出我们的符号变量nbr。这样在你加载这个模块的时候可以动态修改这个变量的值。稍后将演示。yuer_init()函数将在模块加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功。
第二步:编写Makefile文件
首先还是来看看我们Makefile的源文件,然后我们再来解释;
Makefile
obj-m := moles.o #要生成的模块名
moles-objs:= mymod.o #生成这个模块名所需要的目标文件
KDIR := /lib/moles/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) moles
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) moles
clean:
rm -rf *.o
在arm板上插入是
insmod mymod
如果出现以下错误
insmod: chdir(/lib/moles): No such file or directory
则运行
mkdir /lib/moles/2.6.25 (与arm内核版本相同)
并将mymod.ko文件复制到该目录下
cp mymod.ko /lib/moles/2.6.25
然后再执行 (insmod 只在/lib/moles/2.6.25目录下查找相关驱动模块)
insmod mymod
现在我来说明一下这个Makefile。请记住是大写的Makefile而不是小写的makefile;
obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj-m := <模块名>.o
moles-objs :这个变量是说明声称模块moles需要的目标文件 格式要求 <模块名>-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/桌面/mymole/mymoles.o
LD [M] /home/yuqiang/桌面/mymole/moles.o
Building moles, stage 2.
MODPOST 1 moles
CC /home/yuqiang/桌面/mymole/moles.mod.o
LD [M] /home/yuqiang/桌面/mymole/moles.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-24-generic'
第四步:加载/卸载我们的模块
从上面的编译中我可以看到。已经有一个moles.ko生成了。这就是我们的模块了。现在我们就可以来加载了。
首先在终端输入:sudo insmod moles.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 moles
在终端输入:dmesg | tail -3
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
[20412.046932] I come from yuer's mole, I have been unlad.
可以从打印的信息中看到,我们的模块的退出函数已经被执行了。说明我们的模块已经被成功的卸载了。到目前位置我们就已经算是对模块的编译到编译运行算是有了一个整体上的认识了。对于以后深入的学习还是应该有点帮助的。下面我们将在看看于模块相关的一些简单的操作。
第五步:加载模块时传递参数
在终端输入:sudo insmod mole_name.ko nbr=4
在终端输入:dmesg | tail -6
显示结果如下:
[20800.655694] Hello, How are you. 9
[21318.675593] I come from onefile mole, 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/mole/<moles_name>/parameters/来查看。在这里我们是这样输入的
在终端输入:ls /sys/moedle/moles/parameters/
显示结果:
nbr
如果我们的模块加载成功了。最后我们还可以通过modinfo来查看我们的模块信息。如下
在终端输入:sudo modinfo moles.ko
显示结果:
filename: moles.ko
license: GPL
author: Yu Qiang
srcversion: 20E9C3C4E02D130E6E92533
depends:
vermagic: 2.6.24-24-generic SMP mod_unload 586
parm: nbr:int
E. linux内核模块编译-通过Makefile重命名.ko文件名和模块名
假设模块的源文件为hello.c,源码如下:
使用该文件编译内核模块。
正常情况下,Makefile文件内容如下:
执行 make 命令,生成hello.ko文件。
执行 sudo insmod hello.ko 命令,安装该模块。
执行 lsmod 命令,查看安装的模块。就会看到第一行的就是hello模块。
但是,如果想自定义模块名称为 xmole ,而不是默认的 hello ,如何实现呢?方法如下:
在Makefile中重命名obj-m并将obj-m的依赖关系设置为原始模块(hello)
修改后的Makefile文件内容如下:
将obj-m设置为 xmole .o,并使 xmole .o依赖于 hello .o.
执行 make 命令后,生成 xmole .ko, 而不是 hello .ko,
安装命令: sudo insmod xmole.ko
查看命令: lsmod ,就会看到被安装名为 xmole 的模块。
F. linux下模块的编译,写好源文件了,最简单的一个hello的C程序,怎么写makefile文件,参照好多资料,都不行
Makefile的写复法,注意KDIR的根制据你的源码目录更改,我的是ubuntu11.04的源码目录。
obj-m :=hello.o
KDIR := /usr/src/linux-headers-2.6.38-8-generic/
all:
make -C $(KDIR) M=$(shell pwd) moles
clean:
make -C $(KDIR) M=$(shell pwd) clean
G. Linux 添加 net 模块
Linux 添加 net 模块的方法是:
1、创建c文件和makefile文件:在任意位置创建一个文件夹(我创建的名称为/drive)mkdir drive后,输入cd drive进入文件夹。输入vim hello.c新建hello.c文件,输入以下代码。
操作使用工具:Linux。
使用工具版本:CentOS-7.0-x86_64-DVD-1503-01.iso。
Linux编译内核模块Makefile中指令的作用是:
obj-m:指定构建为可加载内核模块的目标文件。 构建外部模块的命令是:make -C<path_to_kernel_src>M=$PWD。
-C $(KERNEL_DIR):内核源所在的目录。 “make”实际上会在执行时更改为指定的目录,并在完成时更改回来。
KERNEL_DIR:指内核源目录的路径。
M = $ PWD:通知make正在构建外部模块。 赋予“M”的值是外部模块所在目录的绝对路径。