linux 模块编程

来源:互联网 发布:steam mac和windows 编辑:程序博客网 时间:2024/05/03 10:00

makefile文件

obj-m := hello.o KERNELDIR := /lib/modules/2.6.20/build PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install 

如果有多个依赖文件的话:

obj-m := hello.o
hello-objs := file1.o file2.o
这里的-c选项是指首先改变目录到-C指定的位置(即内核源代码的目录),其中保存着内核的顶层makefile文件。M=选项让该makefile在构造modules目标之前返回到模块源代码目录。然后,modules目标指向obj-m变量中指定的模块;在上面的例子中,我们将该变量设置为hello.o

obj-m:=rt_process.oPWD := $(shell pwd)modules:$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesmodules_install:$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install

模块示范代码

#include<linux/init.h>  #include<linux/types.h>  #include<linux/kthread.h>  #include<linux/module.h>  #include<linux/export.h>  #include <linux/delay.h>  #include<linux/slab.h>  #include <linux/fs.h>  #include<asm/uaccess.h>    #ifndef SLEEP_MSEC  #define SLEEP_MSEC(nMS) \  do{\  unsigned long timeout = (nMS)*HZ/1000;\  while(timeout>0){\  timeout=schedule_timeout(timeout);\  }\  }while(0);   #endif    static struct task_struct * MyThread = NULL;  static int MyPrint(void *data)  {      printk(KERN_ALERT "beginning  Thd!\n");      while(!kthread_should_stop())  {          SLEEP_MSEC(10);       你的测试代码;  }  return 0;  }  static int __init   test_init(void)  {      printk(KERN_ALERT "loading  module!\n");      MyThread = kthread_create(MyPrint,NULL,"mythread");      if(IS_ERR(MyThread)){          printk(KERN_ALERT" task creation fails!\n");                      return -1;      }else{          kthread_bind(MyThread,1);      }      wake_up_process(MyThread);      printk(KERN_ALERT "Task waked!\n");      return 0;  }    static void __exit test_exit(void)  {      if(MyThread)      {          kthread_stop(MyThread);          printk(KERN_ALERT "stop  thread!\n");                 MyThread = NULL;      }      printk(KERN_ALERT "unload module!\n");        return 0;  }    module_init(test_init);  module_exit(test_exit);  

makefile的一些总结:

在讲述Makefile之前,还是让我们先来粗略地看一看Makefile的规则。

target ... : prerequisites ...
command
...
...

target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。(任意的Shell命令)

这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。

在默认的方式下,也就是我们只输入make命令。那么,

1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
3、如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
4、如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。

通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。

makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。于是,我们就可以很方便地在我们的makefile中以“$(objects)”的方式来使用这个变量了。

自动化变量:

$@ : 规则的目标所对应的所有文件
$< : 规则中的第一个相关文件
$@  target$%  file name of an archive member$<  first prerequisite$?  prerequisites newer than target$^  prerequisites$+  similar to $^, including duplicates$*  stem of the target filename

文件搜寻


在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。所以,当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。

Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。

VPATH = src:../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地方)


另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很灵活的功能。它的使用方法有三种:

1、vpath <pattern> <directories>

为符合模式<pattern>的文件指定搜索目录<directories>。

2、vpath <pattern>

清除符合模式<pattern>的文件的搜索目录。

3、vpath

清除所有已被设置好了的文件搜索目录。

vapth使用方法中的<pattern>需要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。<pattern>指定了要搜索的文件集,而<directories>则指定了<pattern>的文件集的搜索的目录。例如:

vpath %.h ../headers

该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)

我们可以连续地使用vpath语句,以指定不同搜索策略。如果连续的vpath语句中出现了相同的<pattern>,或是被重复了的<pattern>,那么,make会按照vpath语句的先后顺序来执行搜索。如:

vpath %.c foo
vpath % blish
vpath %.c bar

其表示“.c”结尾的文件,先在“foo”目录,然后是“blish”,最后是“bar”目录。

vpath %.c foo:bar
vpath % blish

而上面的语句则表示“.c”结尾的文件,先在“foo”目录,然后是“bar”目录,最后才是“blish”目录。


make的参数


下面列举了所有GNU make 3.80版的参数定义。其它版本和产商的make大同小异,不过其它产商的make的具体参数还是请参考各自的产品文档。

“-b”
“-m”
这两个参数的作用是忽略和其它版本make的兼容性。

“-B”
“--always-make”
认为所有的目标都需要更新(重编译)。

“-C <dir>”
“--directory=<dir>”
指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。

“—debug[=<options>]”
输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是<options>的取值:
a —— 也就是all,输出所有的调试信息。(会非常的多)
b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。
v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。
i —— 也就是implicit,输出所以的隐含规则。
j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。
m —— 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。

“-d”
相当于“--debug=a”。

“-e”
“--environment-overrides”
指明环境变量的值覆盖makefile中定义的变量的值。

“-f=<file>”
“--file=<file>”
“--makefile=<file>”
指定需要执行的makefile。

“-h”
“--help”
显示帮助信息。

“-i”
“--ignore-errors”
在执行时忽略所有的错误。

“-I <dir>”
“--include-dir=<dir>”
指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。


“-j [<jobsnum>]”
“--jobs[=<jobsnum>]”
指同时运行命令的个数。如果没有这个参数,make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注意这个参数在MS-DOS中是无用的)

“-k”
“--keep-going”
出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执行了。

“-l <load>”
“--load-average[=<load]”
“—max-load[=<load>]”
指定make运行命令的负载。

“-n”
“--just-print”
“--dry-run”
“--recon”
仅输出执行过程中的命令序列,但并不执行。

“-o <file>”
“--old-file=<file>”
“--assume-old=<file>”
不重新生成的指定的<file>,即使这个目标的依赖文件新于它。

“-p”
“--print-data-base”
输出makefile中的所有数据,包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile,你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则,你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号,所以,用这个参数来调试你的makefile会是很有用的,特别是当你的环境变量很复杂的时候。

“-q”
“--question”
不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新,如果是2则说明有错误发生。

“-r”
“--no-builtin-rules”
禁止make使用任何隐含规则。

“-R”
“--no-builtin-variabes”
禁止make使用任何作用于变量上的隐含规则。

“-s”
“--silent”
“--quiet”
在命令运行时不输出命令的输出。

“-S”
“--no-keep-going”
“--stop”
取消“-k”选项的作用。因为有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。

“-t”
“--touch”
相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行。

“-v”
“--version”
输出make程序的版本、版权等关于make的信息。

“-w”
“--print-directory”
输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。

“--no-print-directory”
禁止“-w”选项。

“-W <file>”
“--what-if=<file>”
“--new-file=<file>”
“--assume-file=<file>”
假定目标<file>需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样,使得<file>的修改时间为当前时间。

“--warn-undefined-variables”
只要make发现有未定义的变量,那么就输出警告信息。
0 0