如同C语言的学习一样,入门是从hello world开始的,现在学习驱动设备也选择从这里开始吧! ^_^
先贴上代码:
/*********************************************************************************
* Copyright: (C) 2017 TangBin<[email protected]>
* All rights reserved.
*
* Filename: s3c_hello.c
* Description: This file
*
* Version: 1.0.0(03/23/2017)
* Author: TangBin <[email protected]>
* ChangeLog: 1, Release initial version on "03/23/2017 01:12:59 PM"
*
********************************************************************************/
#include
#include
#include
#define MOD_AUTHOR "TangBin"
#define MOD_DESC "hello,world!"
static int __init hello_init(void)
{
printk("hello,world!\n");
printk("This is my first driver program.\n");
return 0;
}
static void __exit hello_exit(void)
{
printk("Bye!\n");
return;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR(MOD_AUTHOR);
MODULE_DESCRIPTION(MOD_DESC);
MODULE_LICENSE("GPL");
这就是一个简单的代码,但是要如何让它在开发板跑起来呢?
首先,这是要编译成一个模块,模块是可以在内核空间工作的,与我们在用户空间的应用程序是有很大不同的。内核就是一个大的、独立的程序,为了将它的各个片断放在一起,要满足很多详细、明确的要求。
为了将这个.c文件编译成.ko模块并加载到内核中运行,我们需要制作一个Makefile来制定一些规则。
Makefile:
LINUX_SRC ?= ../kernel/linux-3.0
CROSS_COMPILE=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-
obj-m := s3c_hello.o
modules:
@make -C $(LINUX_SRC) M=`pwd` modules
@make clean
clean:
rm -f *.ko.* *.o *mod.c *.order *.symvers
注:
1、Linux驱动Makefile里指定的内核源码路径必须是当前开发板正在运行的内核源码。(LINUX_SRC)
2、指定好交叉编译器的路径。(CROSS_COMPILE)
3、obj-m := s3c_hello.o 说明有一个模块要从目标文件s3c_hello.o中构造从而该目标文件中构造的模块名称为s3c_hello.ko。
4、M=选项让Makefile在构造modules目标之前返回到模块源代码目录。modules目标指向obj-m变量中设定的模块。
5、clean 将一些中间文件删除,因为不是必须的。
之后make:
[tangbin@localhost driver]$ make
make[1]: Entering directory `/home/tangbin/fl2440/kernel/linux-3.0'
CC [M] /home/tangbin/fl2440/driver/s3c_hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/tangbin/fl2440/driver/s3c_hello.mod.o
LD [M] /home/tangbin/fl2440/driver/s3c_hello.ko
make[1]: Leaving directory `/home/tangbin/fl2440/kernel/linux-3.0'
make[1]: Entering directory `/home/tangbin/fl2440/driver'
rm -f *.ko.* *.o *mod.c *.order *.symvers
make[1]: Leaving directory `/home/tangbin/fl2440/driver'
[tangbin@localhost driver]$ ls
Makefile s3c_hello.c s3c_hello.ko
可以看到目录下出现了s3c_hello.ko 文件。file看一下:
[tangbin@localhost driver]$ file s3c_hello.ko
s3c_hello.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
接下来tftp下到开发板中:
[tangbin@localhost driver]$ sudo cp s3c_hello.ko /tftp/
[tangbin@localhost driver]$ ls /tftp/
s3c_hello.ko
在开发板上下载并执行:
>: tftp -gr s3c_hello.ko 192.168.5.201
s3c_hello.ko 100% |*******************************| 25336 0:00:00 ETA
>: insmod s3c_hello.ko
hello,world!
This is my first driver program.
>: lsmod
s3c_hello 561 0 - Live 0xbf004000
要移除模块,使用rmmod:
>: rmmod s3c_hello
Bye!
到此,一个简单的hello world驱动程序完毕。
回过头来看看代码中的一些东西吧:
1、首先,几乎绝大部分的模块代码都包含
#include
#include
#include
这三个头文件。
2、MODULE_AUTHOR()
作者信息,MODULE_DESCRIPTION()
文件的简单描述,MODULE_LICENSE()
指定代码所使用的许可证,如:GPL。
3、printk()这是内核自己的打印输出函数,内核运行时不能依赖与C库。模块能调用printk是因为在insmod函数装入模块后,模块就连接到了内核,因而可以访问内核的公用符号。
4、module_init(hello_init);指定入口函数,module_exit(hello_exit);指定清除函数。
5、static int __init hello_init(void)
初始化函数;static void __exit hello_exit(void)
清除函数。
在开发板装载.ko文件时,提示:
这是因为在__init hello_init(void)
中没有返回值return 0;。