Linux驱动编程杂记001 -- 环境搭建

来源:互联网 发布:公务员考试模拟软件 编辑:程序博客网 时间:2024/06/03 05:23

 1. 源码树

      驱动和特定版本源码挂钩。一般在 /lib/modules 下可找到系统的源码树。shell命令 uname -r 可以查看当前运行内核的详细版本号,最常见的方法是设置为/lib/modules/`uname -r`/build。编译驱动采用源码树不一定是正在运行的内核。

 

2. Makefile

     2.6内核的驱动构建方式和常见的Make差别很大。假设只有 hello.c 一个文件,那么我们的 Makefile 文件只需要如下一行:

          obj-m := hello.o

     然后执行如下Make:

          $ make -C /lib/modules/`uname -r`/build M=`pwd` modules

     为了简便,可以编写如下Makefile文件,此后直接在shell下输入make即可:

          # filename: Makefile

          # yanyg 2009 11 08
          ifneq ($(KERNELRELEASE),)
                  obj-m := hello.o
          else
                  KERNELDIR ?= /lib/modules/$(shell uname -r)/build
                  PWD := $(shell pwd)

          default:
                  $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
          endif

         注意Makefile文件中,$(MAKE) -C $(KERNELDIR) M=$(PWD) modules行前面的缩进必须保证是一个或者多个TAB键,不可以是空格。

 

3. 简单测试 hello.c

     如下简单的C文件,采用2所描述的方法编译。

      编译:

           $ make

           make -C /lib/modules/2.6.18-8.el5/build M=/home/yanyg/study/linux-driver/000-hello modules
           make[1]: Entering directory `/usr/src/kernels/2.6.18-8.el5-i686'
            CC [M]  /home/yanyg/study/linux-driver/000-hello/hello.o
             Building modules, stage 2.
             MODPOST
             CC      /home/yanyg/study/linux-driver/000-hello/hello.mod.o
            LD [M]  /home/yanyg/study/linux-driver/000-hello/hello.ko
           make[1]: Leaving directory `/usr/src/kernels/2.6.18-8.el5-i686'

 

      升级为超级用户,用 insmod 和 rmmod 进行装载/卸载测试:

           # insmod ./hello.ko

           Hello world, sting-version=undefined, integer-version=020612

           # rmmod ./hello.ko

           Goodbye, cruel world

 

      如果是在windows下通过模拟终端登录测试,则输出内容不会在终端输出,而是在/var/log/messages,可以用如下命令查看:

           # tail -f /var/log/messages

           Nov  9 15:19:46 localhost kernel: Hello world, sting-version=undefined, integer-version=020612
           Nov  9 15:20:39 localhost kernel: Goodbye, cruel world

 

      在代码中,函数原型中可以见到诸如 __init 和 __exit 的宏,__init表明只在模块初始化时候用到的函数,__exit表明只在模块清理时候用到的函数。对应的 __initdata 表明只在初始化时候用到的数据,__exitdata表明只在清理时用到的数据。如果模块是编译在内核里面的,则__init和__initdata标记的部分在初始化完毕后会清掉以释放内存,__exit和__exitdata部分会被直接忽略掉。如果模块编译成可加载可卸载的,则该标记没有任何作用。

原创粉丝点击