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

转载 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内核模块编译
  • hyperton
  • hyperton
  • 2015年08月03日 08:12
  • 660

如何将驱动或模块编译进内核

如何将驱动或模块编译进内核 我们知道若要给linux内核添加模块(驱动)有如下两种方式: (1)动态方式:采用insmod命令来给运行中的linux加载模块。 (2)静态方式:修改linux的配...
  • MARZ07101
  • MARZ07101
  • 2012年06月09日 07:39
  • 4751

怎样将驱动静态的编译到内核中。

怎样将驱动静态的编译到内核中。   使用的开发板:tq210的s5pv210开发板 内核版本:linux-3.8.3 编译器:arm-linux-gcc 4.4.3 相关下载地址:   一、准备好...
  • a1299600490
  • a1299600490
  • 2016年07月20日 10:37
  • 752

如何写Linux下编译驱动模块的Makefile

编译驱动模块的Makefile的写法示例: #General Purpose Makefile for Linux Kernel module by guoqingbo KERN_DIR = /...
  • lqjun
  • lqjun
  • 2015年10月22日 20:59
  • 1517

嵌入式Linux最简单驱动模块编译与剖析

# 最简单的内核模块: #include #include static int my_driver_init(void) { printk("hello\n"); ret...
  • u012421976
  • u012421976
  • 2017年01月11日 21:09
  • 902

第一个内核模块程序编译

1.创建内核模块源文件hello_printk 代码如下: #include #include static int __init hello_init(void) { printk("Hell...
  • yainyiyi123
  • yainyiyi123
  • 2016年10月30日 18:37
  • 319

Linux驱动程序模块编译流程

Linux驱动程序可以在内核配置时直接编译进内核或者以模块编译成生.ko文件动态加载。 下面是arm开发板上驱动程序模块编译,动态加载的流程。 ##1.编写驱动程序源程序结合具体硬件编写。##2...
  • Tony_Shen
  • Tony_Shen
  • 2016年08月14日 17:13
  • 872

怎样在内核中添加自己的模块

怎样在内核中添加自己的模块   当我们在订制自己的内核的时候很多时候是需要去修改Makefile 和Kconfig 文件...
  • gangyanliang
  • gangyanliang
  • 2012年12月04日 09:19
  • 3080

自己写的一个网络硬盘

用了大约半年的时间写了个网络存储工具clouddrive.   纯Win32API,   使用Acrobat提供5G免费空间, 用户可以通过拖拽把本地文件备份到云端. 该工具直接支持文件夹的拖拽!目前...
  • jerrywjh
  • jerrywjh
  • 2010年02月08日 12:40
  • 591

Linux内核中如何增加自己的驱动代码

Linux内核中如何增加自己的驱动代码?本文给出了详细的步骤。其实本质上就是修改kconfig和makefile两个文件。 先熟悉下kconfig的语法 1.menumenuname   2....
  • chinazhangzhong123
  • chinazhangzhong123
  • 2016年05月31日 23:41
  • 786
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何把一个自己写的外部驱动模块编译添加到内核中 来自网络
举报原因:
原因补充:

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