当前位置:首页 » 编程软件 » 模块编译方法

模块编译方法

发布时间: 2023-05-21 11:34:10

A. 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 的模块。

B. 怎么使用Android源码编译c模块生成可执行文件

1. 在./development目录下创建一目录 如:myhello
2. 进入hello目录,在其下编写自己的.c文件,如: myhello.c
#include <stdio.h>
int main()
{
printf("hello world\n");
exit(0);
//return 0;
}
3. 在hello目录中,编写Android.mk, 内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myhelloworld
LOCAL_SRC_FILES := myhello.c
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
4. 回到Android源代码顶层目录,进行编译,make myhelloworld
5. 生成的可执行文件位于:out/target/proct/lotus/system/bin/ 目录下
6. adb push 到手机 /data 目录下,然后进入adb shell,到data目录下,执行./myhelloworld 皆可

手动编译连接【arm-eabi-gcc 的目录随andorid的版本而有变化,还有就是需要链接的文件如果比较多时,需要很多-l 就很麻烦了】
7、编译成目标文件:
#$(yourAndroid)/prebuilt/linux-x86/toolchain/[arm-eabi-4.2.1]/bin/arm-eabi-gcc -I bionic/libc/arch-arm/include/ -I bionic/libc/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -g -c helloworld.c -o hello.o
8、生成可执行代码:
#$(yourAndroid)/prebuilt/linux-x86/toolchain/[arm-eabi-4.2.1]/bin/arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,noreloc -o helloworld -Lout/target/proct/[generic]/obj/lib -Wl,-rpath-link=out/target/proct/[generic]/obj/lib -lc hello.o -entry=main

其中[ ]中部分根据实际情况修改

**************************************************
实验:
1. 建目录(my Android)/development/test, 在该目录下新建 Android.mk和fb_test.c文件

2. Android.mk文件

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myfbtest
LOCAL_SRC_FILES := fb_test.c
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

3. 以下为fb_test.c
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <linux/kd.h>

#include <stdio.h>

#define FBBIT_PER_PIXEL 32
#define FBBIT_PIXEL_IMAGE 16
#define PIXELS_WIDTH_BYTE 4
#define BYTE_PER_PIXEL 3
#define FB_GRAPHICS_PATH "/dev/graphics/fb0"
#define DEV_TTY0_PATH "/dev/tty0"

#define DISPLAY_ERROR -1
#define DISPLAY_SUCCESS 0

#define GET_BATTERYCAPACITY_ERR -1

#define MAX_STR 255

static struct {
int fd;
void *pixels;
struct fb_fix_screeninfo fixed;
struct fb_var_screeninfo var;
int align_xres;
} fb;

int getBatteryCapacity(void)
{
FILE *in;
char tmpStr[MAX_STR + 1];
char capfile[] = "/sys/class/power_supply/battery/capacity";

if (capfile == NULL)
return GET_BATTERYCAPACITY_ERR;

in = fopen(capfile, "rt");
if (in == NULL)
return GET_BATTERYCAPACITY_ERR;

if (fgets(tmpStr, MAX_STR, in) == NULL) {
printf("Failed to read battery capacity!\n");
fclose(in);
return GET_BATTERYCAPACITY_ERR;

}

printf("Battery capacity(ascii): %s\n", tmpStr);
fclose(in);

return 0;//atoi(tmpStr);
}

static int vt_set_graphicsmode(int graphics)
{
int fd, r;
fd = open(DEV_TTY0_PATH, O_RDWR | O_SYNC);
if (fd < 0)
return DISPLAY_ERROR;
r = ioctl(fd, KDSETMODE, graphics);
close(fd);
return r;
}

int display_init(void)
{
fb.fd = open(FB_GRAPHICS_PATH, O_RDWR);
if (fb.fd < 0)
return DISPLAY_ERROR;

if (ioctl(fb.fd, FBIOGET_FSCREENINFO, &fb.fixed) < 0)
return DISPLAY_ERROR;
if (ioctl(fb.fd, FBIOGET_VSCREENINFO, &fb.var) < 0)
return DISPLAY_ERROR;
fb.align_xres = fb.fixed.line_length /
(fb.var.bits_per_pixel >> BYTE_PER_PIXEL);

fb.pixels = mmap(0, fb.fixed.line_length * fb.var.yres_virtual,
PROT_READ | PROT_WRITE, MAP_SHARED, fb.fd, 0);
if (fb.pixels == MAP_FAILED)
return DISPLAY_ERROR;

vt_set_graphicsmode(KD_GRAPHICS);

memset(fb.pixels, 0, fb.fixed.line_length * fb.var.yres_virtual);
//display_update(fb.pixels, fb.align_xres, fb.var.yres);
fb.var.activate = FB_ACTIVATE_FORCE;
ioctl(fb.fd, FBIOPUT_VSCREENINFO, &fb.var);

printf("display_init ok\n");

return DISPLAY_SUCCESS;
}

void display_on(void)
{
ioctl(fb.fd, FBIOBLANK, FB_BLANK_UNBLANK);
}

void display_off(void)
{
ioctl(fb.fd, FBIOBLANK, FB_BLANK_POWERDOWN);
}

int main()
{
display_init();
display_off();//关显示屏

getBatteryCapacity();
sleep(5);

display_on();//开显示屏

return 0;
}

C. 请教易语言模块如何编译成程序

*.e文件是易语言的源代码文件,该文件中保存了易语言所设计的程序的所有源代码。无论是*.ec的模块文件还是*.exe的可执行文件都是通过*.e文件编译而来的.
如果编译源代码文件(也就是*.e的文件)后,生成的是*.ec的文件,那么说明这份源代码是一个易语言模块的源代码,它只能被编译为*.ec的易语言模块文件。
要生成exe的可执行文件,需要在新建易语言程序项目时选择“Windows窗口程序”类型,该类型的项目可以编译为exe文件。
另:如何建立“Windows窗口程序”项目?启动易语言后在弹出的“新建...”窗口中选择即可。

D. 如何编译一个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源码https://www.kernel.org/
如我的机器3.5.0版本源码下载地址为:https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.5.tar.bz2
下载完后,找一个路径解压,如我解压到/linux-3.5/
然后很重要的一步是:执行命令uname -r,可以看到Ubuntu的版本信息是3.5.0-19-generic
。进入linux源码目录,编辑Makefile,将EXTRAVERSION = 修改为EXTRAVERSION= -19-generic。
这些都是要配置源码的版本号与系统版本号,如果源码版本号和系统版本号不一致,在加载模块的时候会出现如下错误:insmod: error inserting 'hello.ko': -1 Invalid mole 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 mole: "hello world"
======================================================================*/
#include <linux/init.h>
#include <linux/mole.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 ");
}

mole_init(hello_init);
mole_exit(hello_exit);

MODULE_AUTHOR("zeroboundary");
MODULE_DESCRIPTION("A simple HelloWorld Mole");
MODULE_ALIAS("a simplestmole");

4、写一个Makefile对源码进行编译
KERN_DIR = /linux-3.5
all:
make-C $(KERN_DIR) M=`pwd` moles
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 将该Mole加入内核中。在这里需要注意的是要用 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 mole format
用dmesg|tail查看内核日志详细错误
disagrees about version of symbolmole_layout,详细看这里。
http://www.ibm.com/developerworks/cn/linux/l-cn-kernelmoles/index.html
在X86上我的办法是:
make -C/usr/src/linux-headers-3.5.0-19-generic SUBDIRS=$PWD moles

E. 如何编写简单的Perl模块

下面主要讲两个在cmd中安装perl模块的方法。

PPM方式
优点:方面 缺点:部分模块搜索不到,也就不能安装
具体步骤:1,装好库,这些网站都有编译好了的模块,2,用命令安装,ppm install 模块名称
具体方法如下: 添加库的方法:在cmd中运行命令ppm repo suggest (意思是给出建议添加的网站),然后将列出的网站使用命令 ppm repo add 网站url (比如 ppm repo add http //www bribes org/perl/ppm bribes )添加,全部添加完 这步完成后就用模块安装命令安装.

手动编译方式
优点:通吃所唯仿有模块
缺点:有点麻烦
具体步骤:1安装编译器2设置编译器的环境变量3可能安装dmake
具体方法:如下
1.首先要有个c编译器,因为很多模块都是用c编写的。推荐dev-cpp,记得要下含有mingw的就是了(不懂c,下载含有mingw的因为这个版本的bin目录里有gcc.exe等工具).
1.1安装好了编译器之后,要能在cmd中以命令方式运行的话,必须要设置环境变量,将dev-cpp/bin路径加入到环境变量中,否则cmd中无法运行相应的命令,注意加的是绝对路径。弄完好,在cmd中运行gcc -v 显示出内容表示编译器安装成功,并且可以用命令行编译.
2.编译步骤,在cpan上下载需要的模块,比如Win32::SerialPort,一般是gz格式的,用rar解压就行。解压后在cmd中进入这衡谨个目录(简单的dos命令应该知道吧),就用常见的方法:
perl Makefile.pl
make
make test
make install
2.1需要注意几点
2.1.1具体编译步骤应该先看下模块包内的readme
2.1.2用的是dev-pp编译器,故用make,vc编译器好象是nmake。不过一般会遇到问题,make命令没有用,如果没有nmake(nmake可以下载),我们就可以用dmake,在cmd中输入ppm install dmake,下载并安装dmake,这里要注意你以前activeperl安装的路径里不能有中文,否则显示无法安装,而且ppm安装dmake的目录是在perl/site/bin下的,所以确保这个路径添加在环境变量中,否则dmake无法使用。当安装好dmake后,就可以按照上面那个方法安装perl模块了,只需要将make改成dmake即可:
perl Makefile.pl
dmake
dmake test
dmake install
你现在可以打开图形化的ppm界面,搜索看看刚刚那个模块是否安装成功,或者在cmd中输入:perldoc (模块的名称),如果有结果的话,则表示模块安装成功。

因为基本上咐山基所以出现的模块在CPAN里都会找到,所以推荐使用第二种方法。

F. 如何编译一个linux下的驱动模块

Linux内核源码路径:/usr/src/linux(这个源码是从kernel.org网站download的2.4.18版本)

按照《linux设备驱动开发详解》一书中的步骤实现经典例子"hello,world!"的例子。
具体步骤如下:
=============================================
1.源码如下:
/*
* hello.c -- the example of printf "hello world!" in the screen of driver program
*/
#include <linux/init.h>
#include <linux/mole.h>
MODULE_LICENSE("Dual BSD/GPL");/* declare the license of the mole ,it is necessary */
static int hello_init(void)
{
printk(KERN_ALERT "Hello World enter!\n");
return 0;
}
static int hello_exit(void)
{
printk(KERN_ALERT "Hello world exit!\n");
}
mole_init(hello_init); /* load the mole */
mole_exit(hello_exit); /* unload the mole */
进入目录:
[root@Alex_linux /]#cd /work/jiakun_test/moletest
[root@Alex_linux moletest]# vi hello.c
然后拷入上面书上的源码。
2.编译代码:
1>.首先我在2.4内核的虚拟机上进行编译,编译过程如下:
[root@Alex_linux moletest]#gcc -D__KERNEL__ -I /usr/src/linux -DMODULE -Wall -O2 -c -o hello.o hello.c
其中-I选项指定内河源码,也就是内核源码树路径。编译结果:
hello.c:1:22: net/sock.h: No such file or directory
hello.c: In function `hello_init':
hello.c:6: warning: implicit declaration of function `printk'
hello.c:6: `KERN_ALERT' undeclared (first use in this function)
hello.c:6: (Each undeclared identifier is reported only once
hello.c:6: for each function it appears in.)
hello.c:6: parse error before string constant
hello.c: In function `hello_exit':
hello.c:11: `KERN_ALERT' undeclared (first use in this function)
hello.c:11: parse error before string constant
hello.c: At top level:
hello.c:13: warning: type defaults to `int' in declaration of `mole_init'
hello.c:13: warning: parameter names (without types) in function declaration
hello.c:13: warning: data definition has no type or storage class
hello.c:14: warning: type defaults to `int' in declaration of `mole_exit'
hello.c:14: warning: parameter names (without types) in function declaration
hello.c:14: warning: data definition has no type or storage class
在网上查询有网友提示没有引入kernel.h
解决:vi hello.c
在第一行加入:#include <linux/kernel.h>
再次编译仍然报KERN_ALERT没有声明
修改编译条件-I,再次编译:
[root@Alex_linux moletest]#gcc -D__KERNEL__ -I /usr/src/linux -DMODULE -Wall -O2 -c -o hello.o hello.c
[root@Alex_linux moletest]#ls
hello.c hello.o Makefile
[root@Alex_linux moletest]#
2>.接着我尝试在2.6内核的虚拟机上进行编译
编译过程如下:
[root@JiaKun moletest]# ls
hello.c makefile
[root@JiaKun moletest]# vi hello.c
[root@JiaKun moletest]# make
make -C /mylinux/kernel/2.4.18-rmk7 M=/home/alex/test/moletest moles
make: *** /mylinux/kernel/2.4.18-rmk7: No such file or directory. Stop.
make: *** [moles] Error 2
[root@JiaKun moletest]# vi makefile
[root@JiaKun moletest]# make
make -C /usr/src/kernels/2.6.18-53.el5-i686 M=/home/alex/test/moletest moles
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
scripts/Makefile.build:17: /home/alex/test/moletest/Makefile: No such file or directory
make[2]: *** No rule to make target `/home/alex/test/moletest/Makefile'. Stop.
make[1]: *** [_mole_/home/alex/test/moletest] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
make: *** [moles] Error 2
[root@JiaKun moletest]# mv makefile Makefile
[root@JiaKun moletest]# make
make -C /usr/src/kernels/2.6.18-53.el5-i686 M=/home/alex/test/moletest moles
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
CC [M] /home/alex/test/moletest/hello.o
Building moles, stage 2.
MODPOST
CC /home/alex/test/moletest/hello.mod.o
LD [M] /home/alex/test/moletest/hello.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
[root@JiaKun moletest]# ls
hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile Mole.symvers

3.执行代码,加载驱动模块:
2.4内核加载模块:
insmod ./hello.o
但是此时并没有输出printk打印的信息。但是可以在/var/log/messages 中看到打印的信息,这是由于KERN_ALERT优先级不够高。这里
需要修改为:KERN_EMERG。再次编译,加载模块即可以看到结果
2.6内核加载模块:
[root@JiaKun moletest]# insmod hello.ko
[root@JiaKun moletest]#
Message from syslogd@ at Sat Jul 26 19:52:44 2008 ...
JiaKun kernel: Hello, world
有的朋友可能会出现insmod命令找不到的错误,这可能有下面几个原因:
<1> 你的系统没有安装mole-init-tools工具,关于此问题,只需安装即可,但是一般装完系统是有这个命令的。
<2> 环境变量没有添加导致不能使用该命令。使用echo $PATH即可查看PATH环境变量,发现没有/sbin这个路径,所以你当然不能使用insmod这个命令了。解决的方法很简单,只需在命令行输入:
PATH = "$PATH:/sbin"即可添加。(insmod在/sbin这个目录下,你可以使用whereis insmod查看)。
<3> insmod这个命令需要在root权限下才能使用。
加载完成后你可以输入lsmod查看hello这个模块哦。

4.卸载驱动模块:rmmod hello.
加载模块后就可在屏幕上看到如下信息:Hello world enter.
卸载时就可在屏幕上看到如下信息:hello world exit.
[root@JiaKun moletest]# rmmod hello.ko
[root@JiaKun moletest]#
Message from syslogd@ at Sat Jul 26 19:52:58 2008 ...
JiaKun kernel: Goodbye, cruel world

另外,如果有多个文件,则按下列方式编写Makefile文件(file1.c、file2.c):
obj -m := molename.o
mole-objs := file1.o file2.o
转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦

G. 如何编译一个linux下的驱动模块

首先,我们要了解一下模块是如何别被构造的。模块的构造过程与用户空间
的应用程序的构造过程有显着不同;内核是一个大的、独立的程序
,
对于它的各
个部分如何组合在一起有详细的明确的要求。
Linux2.6
内核的构造过程也与以
前版本的内核构造过程不同;
新的构造系统用起来更加简单,
并且可产生更加正
确的结果
,
但是它看起来和先前的方法有很大不同。内核的构造系统非常复杂
,
我们所看到的只是它的一小部分。
如果读者想了解更深入的细节,
则应阅读在内
核源码中的
Document/kbuild
目录下的文件。

在构造内核模块之前,
有一些先决条件首先应该得到满足。
首先,
读者要保证你
有适合于你的内核版本的编译器、模块工具
,
以及其他必要工具。在内核文档目
录下的文件
Documentation/Changes
里列出了需要的工具版本;
在开始构造内
核前,
读者有必要查看该文件,
并确保已安装了正确的工具。
如果用错误的工具
版本来构造一个内核
(
及其模块
)
,可能导致许多奇怪的问题。另外也要注意
,
使
用太新版本的编译器偶尔可能也会导致问题。

一旦做好了上面的准备工作之后
,
其实给自己的模块创建一个
makefile
则非常
简单。实际上
,
对于本章前面展示的
" hello world"
例子
,
下面一行就够了
:
obj-m := hello.o
如果读者熟悉
make

但是对
Linux2.6
内核构造系统不熟悉的话
,
可能奇怪这个
makefile
如何工作。毕竟上面的这一行不是一个传统的
makefile
的样子。问
题的答案当然是内核构造系统处理了余下的工作。上面的赋值语句
(
它利用了由
GNU make
提供的扩展语法
)
说明有一个模块要从目标文件
hello.o
构造,而从
该目标文件构造的模块名称为
hello.ko.
如果我们想由两个源文件
(
比如
file1.c

file2.c )
构造出一个名称为
mole.ko
的模块
,
则正确的
makefile
可如下编写
:
obj-m := mole.o
mole-objs := file1.o file2.o
为了让上面这种类型的
makefile
文件正常工作
,
必须在大的内核构造系统环境
中调用他们。假设读者的内核源码数位于
~/kernel-2.6
目录
,
用来建立你的模
块的
make
命令
(
在包含模块源代码和
makefile
的目录下键入
)
应该是
:
make -C ~/kernel-2.6 M=`pwd` moles
这个命令首先是改变目录到用
-C
选项指定的位置
(
即内核源代码目录
)
,其中保
存有内核的顶层
makefile
文件。这个
M=
选项使
makefile
在构造
moles

标前
,
返回到模块源码目录。
然后,
moles
目标指向
obj-m
变量中设定的模块,
在上面的例子里,我们将该变量设置成了
mole.o


上面这样的
make
命令对于多个文件的编译显得不是很方便
,
于是内核开发者就
开发了一种
makefile
方式
,
这种方式使得内核树之外的模块构造变得更加容易。
代码清单
1.4
展示了
makefile
的编写方法:

代码清单
1.4 makefile
ifeq ($(KERNELRELEASE),)

KERNELDIR ?= /source/linux-2.6.13
PWD := $(shell pwd)

moles:
$(MAKE) -C $(KERNELDIR) M=$(PWD) moles

moles_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) moles_install

clean:
rm -rf *.o *~ core .depend .*. *.ko *.mod.c .tmp_versions

.PHONY: moles moles_install clean

else
obj-m := hello.o
endif
我们再次看到了扩展的
GNU
make
语法在起作用。在一个典型的构造过程中,这

makefile
将被读取两次。当从命令行中调用这个
makefile ,
它注意到
KERNELRELEASE
变量尚未设置。我们可以注意到,已安装的模块目录中存在一
个符号连接,
它指向内核的构造树,
这样这个
makefile
就可以定位内核的源代
码目录。如果读者时间运行的内核并不是要构造的内核,则可以在命令行提供
KERNELDIR=
选项或者设置
KERNELDIR
环境变量
,
或者修改
makefile
中设置
KERNELDIR
的那一行。在找到内核源码树
,
这个
makefile
会调用
default:


,
这个目标使用先前描述过的方法第二次运行
make
命令
(
注意,在这个
makefile

make
命令被参数化成
$(MAKE))
,以便运行内核构造系统。在第二
次读取
makefile
时,
它设置了
obj-m,
而内核的
makefile
负责真正构造模块。

这种构造模块的机制看起来很繁琐,可是,一旦我们习惯了使用这种机制
,
则会
欣赏内核构造系统带给我们的便利。需要注意的是
,
上面
makefile
并不完整,
一个真正的
makefile
应包含通常用来清除无用文件的目标
,
安装模块的目标等
等。一个完整的例子可以参考例子代码目录的
makefile

H. 如何编译/交叉编译内核模块, Linux 2.6.

椤�build 能够编译内核树目录内的内核模块,也能够编译内核树目录外的内核模块(外部内核模块)。. 编译外部内核模块的命令: #cd <your-mole-dir> #make -C <path-to-kernel> M=`pwd` 其中<your-mole-dir> 为要编译的内核模块所在目录,<path-to-kernel> 为内核源码所在的目录。 对于发行版本的Linux ,可以用: #make -C /lib/moles/`uname -r`/build M=`pwd` 注意:使用Kbuild 之前,必须先成功编译过内核源码。 说明: .#make -C <path-to-kernel> M=`pwd` moles 作用与上面的命令一样 .以前的内核版本可以使用 #make -C <path-to-kernel> SUBDIRS=`pwd` moles. 安装外部内核模块 #make -C <path-to-kernel> M=`pwd` moles_install 默认安装目录为:/lib/moles/`uname -r`/extra ,可以通过INSTALL_MOD_PATH 宏在默认安装路径前加前缀。 例如: #make -C <path-to-kernel> INSTALL_MOD_PATH=/opt M=`pwd` moles_install 则编译后的模块会放在/opt/lib/moles/`uname -r`/extra 通过宏INSTALL_MOD_DIR 可以修改是否放在'extra' 下,例如: #make -C <path-to-kernel> INSTALL_MOD_DIR=golf M=`pwd` moles_install 则编译后的模块会放在/lib/moles/`uname -r`/golf . 编译单个文件 #make -C <path-to-kernel> M=`pwd` <filename>. 其他命令 #make -C <path-to-kernel> M=`pwd` clean #make -C <path-to-kernel> M=`pwd` help.Kbuild 文件 Linux的Kbuild 会在内核模块目录下查找Kbuild 文件,如果有,则在编译时会使用该文件。示例: 假设有这么几个文件:8123_if.c 8123_if.h 8123_pci.c 8123_bin.o_shipped( 二进制的模块文件) Kbuild 文件的内容: obj-m := 8123.o 8123-y:8123_if.o 8123_pci.o 8123_bin.o Makefile的内容: #为了兼容旧版本的Kbuild ifneq($(KERNELRELEASE),) include Kbuildelse# 正常的Makefile KDIR:=/lib/moles/`uname -r`/buildall::$(MAKE) -C $(KDIR) M=`pwd` $@ # 其他targetgenbin:echo "X" > 8123_bin_shippedendif 注意,没有源码的二进制.o 文件必须以原文件名加_shipped 结尾,例如8123_bin.o_shipped,KBuild 会把8123_bin.o_shipped 复制为8123_bin.o ,然后一起编译。 应该用: ifeq ($(obj),) obj= .

I. 如何编译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

J. openwrt怎么把模块编译到内核

开发环境为ubuntu.首先搭建编译环境。
sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils subversion libncurses5-dev ncurses-term zlib1g-dev gawk asciidoc libz-dev git-core build-essential libssl-dev
下面就是下载源码,源码分两种,一种是最新版但不稳定,就是trunk版,一种是相对稳定版,
如果不是最新下载,最好定期更新代码,命令为
./scripts/feeds update –a
./scripts/feeds install –a
接着就是编译了。编译方法如下:
make defconfig
make menuconfig进入定制界面,选择自己的设备类型。
make V=99
下面就是增加内核模块的方法了
进入package目录,创建模块目录
cd backfire/package
mkdir example
进入example目录,创建Makefile文件和代码路径
cd example
touchMakefile
mkdir src

热点内容
ims医药数据库 发布:2025-07-18 05:33:52 浏览:812
魅族3脚本精灵 发布:2025-07-18 05:27:39 浏览:807
解压采耳师 发布:2025-07-18 05:23:20 浏览:511
ftp二进制方式 发布:2025-07-18 05:21:04 浏览:751
易观数据库 发布:2025-07-18 05:19:31 浏览:995
linux的c语言编译 发布:2025-07-18 05:16:22 浏览:602
为何编译硬件驱动 发布:2025-07-18 05:15:02 浏览:489
android适配原理 发布:2025-07-18 05:11:59 浏览:551
网络存储服务器如何搭建 发布:2025-07-18 04:47:23 浏览:549
手机上玩电脑我的世界服务器 发布:2025-07-18 04:11:59 浏览:599