如何把一个自己写的外部驱动模块编译添加到内核中 来自网络

转载 2013年12月05日 09:44:17
有时候还是需要把自己写的驱动模块添加到内核中去编译成一个整体,这样很容易YY,我靠,我也能在内核目录里加代码了

首先选一个典型的例子,一个外部驱动模块,需要传入两个参数,然后通过cat /proc/result 查看他们的和
/*
test_inline_driver.c
这是一个例子,把模块参数val1+ val2的和通过 cat /proc/result 显示出来
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>

#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>

struct proc_dir_entry *sumproc_result_fp=NULL;

int val1=0,val2=0;

module_param(val1,int,S_IRUGO);
module_param(val2,int,S_IRUGO);

MODULE_DESCRIPTION("My kernel module");
MODULE_AUTHOR("deep_pro");
MODULE_LICENSE("GPL");

int read_result(char *page,char **start,off_t off,int count,int *eof,void *data_unused)
{
char *buf;
buf=page;
buf+=sprintf(buf,"result %d+%d = %d \n",val1,val2,val1+val2);
*eof=1;
return buf-page;
}


static int test_inline_driver_init_module(void)
{
printk( KERN_DEBUG "Module test_inline_driver init\n" );
sumproc_result_fp=create_proc_entry("result",S_IFREG|S_IRUSR,NULL);
if(sumproc_result_fp!=NULL)
{
sumproc_result_fp->read_proc=read_result;
}
return 0;
}

static void test_inline_driver_exit_module(void)
{
printk( KERN_DEBUG "Module test_inline_driver exit\n" );
remove_proc_entry("result",0);
}



#ifndef MODULE
static int __init get_val(char *str)
{
int ints[10];
str=get_options(str,ARRAY_SIZE(ints),ints);
if(ints[0]==2)
{
val1=ints[1];
val2=ints[2];
}
return 1;
}
__setup("getval=",get_val);
__initcall(test_inline_driver_init_module);
#else
module_init(test_inline_driver_init_module);
#endif
module_exit(test_inline_driver_exit_module);


可以看到,在代码上有两个要求
首先,编译进内核的模块就不能靠module_init来启动了,需要__initcall
其次,编译进内核的模块不能靠insmod命令这样的方式传入参数,只能通过__setup读取linux启动参数
所以需要靠#ifndef MODULE 来判断当前模块是编译成外部模块还是直接编译进内核

然后就需要修改对应驱动目录下的Kconfig和Makefile文件,这个例子放在/linux-2.6.29/drivers/char 目录下
对于Kconfig,打开后在靠前的位置进行如下修改后的前20行

#
# Character device configuration
#

menu "Character devices"

config test_inline_driver
tristate "test_inline_driver is my test"
---help---
this is a sample driver,to test building a driver into kernel


config VT
bool "Virtual terminal" if EMBEDDED
depends on !S390
select INPUT
default y
---help---
If you say Y here, you will get support for terminal devices with
display and keyboard devices. These are called "virtual" because you
can run several virtual terminals (also called virtual consoles) on

其中加粗的是自己添加的内容,config选项定义了符号值
tristate命令可以选择是Y还是M

这样的修改,make menuconfig可以看到
如何把一个自己写的外部驱动模块编译添加到内核中 - Jesse Rei - Jesse Rei 的博客(优柔寡断)

接下来修改Makefile,修改后前20行
#
# Makefile for the kernel character device drivers.
#

#
# This file contains the font map for the default (hardware) font
#
FONTMAPFILE = cp437.uni

obj-y     += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o

obj-$(CONFIG_test_inline_driver) += test_inline_driver.o

obj-$(CONFIG_LEGACY_PTYS)    += pty.o
obj-$(CONFIG_UNIX98_PTYS)    += pty.o
obj-y                += misc.o
obj-$(CONFIG_VT)        += vt_ioctl.o vc_screen.o selection.o keyboard.o
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
obj-$(CONFIG_HW_CONSOLE)    += vt.o defkeymap.o
obj-$(CONFIG_AUDIT)        += tty_audit.o

其中的加粗的一行是自己加的
很容易理解,obj-y是无条件一定会编译进内核的,obj-$(CONFIG_xxxx)是编译成xxxx.o但会不会链接进内核得看make menuconfig的选择的,obj-m就一定会编译成外部模块

好了,准备工作完成,make之后修改启动linux参数,在最后加上 getval=1,2
如mini2440是noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 getval=1,2
测试结果
 
 
 
驱动
程序的使用可以按照两种方式编译,一种是静态编译进内核,另一种是编译成模块以供动态加载。由于uClinux不支持模块动态加载,而且嵌入式Linux不能够象桌面Linux那样灵活的使用insmod/rmmod加载卸载设备驱动程序,因而这里只介绍将设备驱动程序静态编译进uClinux内核的方法。

      下面以uClinux为例,介绍在一个以模块方式出现的驱动程序test.c基础之上,将其编译进内核的一系列步骤:

  (1) 改动test.c源带代码

  第一步,将原来的:

#include
  #include
  char kernel_version[]=UTS_RELEASE;

  改动为:

#ifdef MODULE
  #include
  #include
  char kernel_version[]=UTS_RELEASE;
  #else
  #define MOD_INC_USE_COUNT
  #define MOD_DEC_USE_COUNT
  #endif

  第二步,新建函数int init_test(void)

  将设备注册写在此处:

result=register_chrdev(254,"test",&test_fops);

  (2) 将test.c复制到/uclinux/linux/drivers/char目录下,并且在/uclinux/linux/drivers/char目录下mem.c中,int chr_dev_init( )函数中增加如下代码:

 #ifdef CONFIG_TESTDRIVE
  init_test();
  #endif

  (3) 在/uclinux/cinux/drivers/char目录下Makefile中增加如下代码:

ifeq($(CONFIG_TESTDRIVE),y)
  L_OBJS+=test.o
  Endif

  (4) 在/uclinux/linux/arch/m68knommu目录下config.in中字符设备段里增加如下代码:

bool 'support for testdrive' CONFIG_TESTDRIVE y

  (5) 运行make menuconfig(在menuconfig的字符设备选项里你可以看见我们刚刚添加的'support for testdrive'选项,并且已经被选中);make dep;make linux;make linux.text;make linux.data;cat linux.text linux.data > linux.bin.

  (6) 在 /uClinux/romdisk/romdisk/dev/目录下创建设备:

 mknod test c 254 0

  并且在/uclinux/appsrc/下运行make,生成新的Romdisk.s19文件。

  到这里,在uClinux中增加设备驱动程序的工作可以说是完成了,只要将新的linux.bin与Romdisk.s19烧入目标板中,你就可以使用自己的新设备test了。





驱动模块可以内核编译好后动态加载进去,也可以在编译内核的时候就直接添加。下面是将驱动程序静态编译进内核的方法:
以一个字符设备为例:
1.修改/drivers/char下的Kconfig文件
在Kconfig中增加如下代码:
config MY_HELLO
    bool "this is test"

a.  保存后回到内核根目录进行make menuconfig 你会在字符驱动选项中得到如下图,选择保存退出


b. 在内核根目录的.config 文件中你会发现
CONFIG_MY_HELLO=y

2.修改/drivers/char下的Makefile文件,增加如下
obj-$(CONFIG_MY_HELLO)        += my_hello.o
当然前提是你的my_hello.c必须放在当前的目录了


END


相关文章推荐

Linux驱动模块编译进内核中

Linux驱动模块编译进内核中 BQ27501驱动编译进内核 一、       驱动程序编译进内核的步骤 在 linux 内核中增加程序需要完成以下三项工作: ...

驱动模块的编写##向内核添加系统调用函数

1.驱动模块的编写 例子: @在PC机源码目录drivers/arm_emb: mkdir dem...

openwrt 编译驱动模块(在openwrt源代码外部任意位置编写代码,独立模块化编译.ko)

在openwrt SDK代码包之外,模块化编译驱动程序,生产.ko文件,不需要再openwrt内部建立文件夹编译。...

将设备驱动程序模块源码添加到Linux内核模块源码中

1、将设备驱动程序模块globalmem添加到内核源码中,存放路径是kernel/drivers/mydriver/globalmem; 2、globalmem模块包含源码文件:globalmem....

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

直接写Makefile 文件(假设要编译的文件为hello.c) 1 ifneq ($(KERNElRELEASE),) 2 obj-m := hello.o 3 else 4 obj-m :...

Ubuntu12.10 内核源码外编译 linux模块--编译驱动模块的基本方法

1、先编写一个简单的hello模块,hello.c 源码如下: 1 #ifndef __KERNEL__ 2 # define __KERNEL__ 3 #endif 4 #ifnde...
  • sonbai
  • sonbai
  • 2013年03月04日 17:39
  • 1710

外部看门狗驱动模块支持-max706s

/*  * max706s Watchdog: A Simple Hardware Watchdog Device  * Based on Softdog driver by Alan Cox a...

Linux内核驱动模块编程指南.pdf

  • 2010年01月16日 13:31
  • 396KB
  • 下载

Android开发-从硬件到APP(一) : 单独编内核驱动模块

Android开发-从硬件到APP(1):  单独编译模块 好久没有更新博客,主要是因为工作太多了,而且居然去考公务员!...

Linux内核驱动模块的调试技术总结

这些天来弄了一个简单的驱动模块,后发现系统只要一卸载模块系统就会死掉。到底是那里出了错? 如果你只是通过printk来调试, 而没有其他的方法去检测错误的。 也是这个原因促使我写驱动模块调试技术相...
  • yuyin86
  • yuyin86
  • 2012年09月04日 13:14
  • 635
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何把一个自己写的外部驱动模块编译添加到内核中 来自网络
举报原因:
原因补充:

(最多只允许输入30个字)