ARM技术论坛
直播中

nhcp

15年用户 1137经验值
私信 关注
[经验]

基于OK6410-A的ARM11开发Linux系统讨论

1. 开发环境:Ubuntu 9.10
2. 使用虚拟机时(VM 8.0.0 build-471780),Linux目录下的/mnt/hgfs/放置和Windows进行共享的文件夹
3. Linux编译环境支持2.6.28。Linux版本查看方式为
  a) cat /proc/version
  b) uname -r
4. QT Creator的老版本
5. 交叉编译:在一个版本的Linux(例如桌面版的Ubuntu或者Fedora)下编译,在另一个版本的Linux(嵌入式系统的Linux)下运行。需要用到交叉编译器,且不同的Linux版本对应不同版本的gcc交叉编译器,比如arm-linux-gcc-4.3.2.tgz交叉编译器对应arm上可以编译Linux 2.6.28版本的程序。
一段交叉编译示例:
在桌面Linux上编辑一段小程序hello.c:
#include
Main()
{
        Printf(“forlinx--Helllo world!”);
}
然后使用交叉编译器进行编译:
/usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc –o hello-arm hello.c
得到的hello-arm可执行程序拷贝到SD卡上,在ARM嵌入式平台上进入SD卡目录运行./hello-arm,即可观察到结果。
6. 模块的加载和卸载
本文讨论了模块的加载与卸载的一些操作, 及其自己的理解
[root@flydream MODULES]# dmesg -C         //  在这里清空消息队列以便插入模块后方便查看结果
============================================================================================
============================================= Makefile =====================================
============================================================================================
[root@flydream MODULES]# cat Makefile
TARGET1=helloworld  
TARGET2=hello2
KVER=$(shell uname -r)
KDIR=/lib/modules/$(KVER)/build
PWD=$(shell pwd)
obj-m += $(TARGET1).o   // 说明把helloworld.c 和 hello2.c分别编译成相关模块。 即helloworld.ko hello2.ko
obj-m += $(TARGET2).o
default:
    make -C $(KDIR) M=$(PWD) modules//说明要编译成模块
.PHONY: install
install:
    insmod $(TARGET).ko $(TERGET2).ko
.PHONY: uninstall
uninstall:
    rmmod $(TARGET1).ko $(TARGET2).ko
clean:
    -rm *.ko
    -rm *.o
    -rm -f Mo*
    -rm *.mod.*
    -rm *.order
============================================================================================
============================================================================================
============================================================================================
============================================= helloworld.c =================================
============================================================================================
[root@flydream MODULES]# cat helloworld.c
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
MODULE_LICENSE("GPL");   
// MODULE_LICENSE 的定义参见内核源码/opt/linux-3.0.4/include/linux 目录下module.h 文件140 #define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
MODULE_AUTHOR;
MODULE_DESCRIPtiON("This is a test module");
/*********************************************************************************
//#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
//#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
*********************************************************************************/
static int N = 3;
module_param(N, int, 0644);  //定义于内核文件 src/include/linux/moduleparam.h
int my_print(int n)
{
    printk(KERN_ALERT "This function was called , obtain param is %dn", n);
    return 0;
}
EXPORT_SYMBOL(my_print);    // 导出模块符号, 以供其他模块使用, 也就是说my_print函数可以被其他模块调用, 但是有一点很重要的
                            // 一点是, 当删除此模块的时候要看看还有//没有其他模块在引用这个模块, 否则会出错。
static int init_hello(void)
{
    printk(KERN_ALERT "Enter helloworld module...nparam is %dn", N);
    return 0;
}
static void exit_hello(void)
{
    printk(KERN_ALERT "Exit helloworld module...n");
}
module_init(init_hello);   // 当加载模块的时候会执行模块初始化函数
module_exit(exit_hello);  // 当模块卸载的时候会执行模块析构函数
============================================================================================
============================================================================================
[root@flydream MODULES]# cat hello
hello2.c      helloworld.c
============================================================================================
============================================= hello2.c =====================================
============================================================================================
[root@flydream MODULES]# cat hello2.c
#include
extern int my_print(int n);   // 说明本模块要引用其他模块的函数
MODULE_LICENSE("GPL");
static int init_hello2(void)
{
    request_module("helloworld");
    printk(KERN_ALERT "in hello2.ko: request loaded module helloworld.ko success!n");
    my_print(5);
    return 0;
}
static void exit_hello2(void)
{
    printk(KERN_ALERT "in hello2.ko: leaving hello2 module successed !n");
}
module_init(init_hello2);   // 当加载模块的时候会执行模块初始化函数
module_exit(exit_hello2);  // 当模块卸载的时候会执行模块析构函数
============================================================================================
============================================================================================
[root@flydream MODULES]# make  // 生成模块
make -C /lib/modules/3.2.7-1.fc16.i686.PAE/build M=/opt/MODULES modules
make[1]: Entering directory `/usr/src/kernels/3.2.7-1.fc16.i686.PAE'
  CC [M]  /opt/MODULES/helloworld.o
  CC [M]  /opt/MODULES/hello2.o
  Building modules, stage 2.
  MODPOST 2 modules
  CC      /opt/MODULES/hello2.mod.o
  LD [M]  /opt/MODULES/hello2.ko
  CC      /opt/MODULES/helloworld.mod.o
  LD [M]  /opt/MODULES/helloworld.ko
make[1]: Leaving directory `/usr/src/kernels/3.2.7-1.fc16.i686.PAE'
[root@flydream MODULES]# ls
hello2.c      hello2.mod.o  helloworld.ko     helloworld.o   Module.symvers
hello2.ko     hello2.o      helloworld.mod.c  Makefile
hello2.mod.c  helloworld.c  helloworld.mod.o  modules.order
[root@flydream MODULES]# ls *.ko
hello2.ko  helloworld.ko
[root@flydream MODULES]# cat /proc/modules | grep helloworld  // 加载前查看模块在不在, 没有输出
[root@flydream MODULES]# insmod ./helloworld.ko // 加载模块
[root@flydream MODULES]# cat /proc/modules | grep helloworld  // 加载后查看模块在不在内存
helloworld 12617 0 - Live 0xfa30d000 (O)   //这里的输出说明了加载成功
[root@flydream MODULES]# lsmod | grep helloworld  //再次验证模块加载成功
helloworld             12617  0
[root@flydream MODULES]# dmesg   //在一次验证模块加载成功, 由下面的输出可以知道
[  737.870084] Enter helloworld module...
[  737.870086] param is 3
[root@flydream MODULES]# lsmod | grep hello2  //同样查看hello2模块加载没有, 没有输出说明没有加载
[root@flydream MODULES]# cat /proc/modules | grep hello2 //同样查看hello2模块加载没有, 没有输出说明没有加载
[root@flydream MODULES]# insmod ./hello2.ko // 现在开始加载hello2模块
[root@flydream MODULES]# dmesg
[  737.870084] Enter helloworld module...
[  737.870086] param is 3
[  854.563622] in hello2.ko: request loaded module helloworld.ko success!  //说明加载hello2模块成功
[  854.563627] This function was called , obtain param is 5 //hello2模块调用个helloworld模块里面的函数, 见前面代码
[root@flydream MODULES]# rmmod helloworld //删除helloworld模块出错, 因为helloworld模块里面的函数被hello2模块引用, 因此先要卸载hello2模块
ERROR: Module helloworld is in use by hello2
[root@flydream MODULES]# rmmod hello2  //先删除hello2模块
[root@flydream MODULES]# dmesg  //查看结果
[  737.870084] Enter helloworld module...
[  737.870086] param is 3
[  854.563622] in hello2.ko: request loaded module helloworld.ko success!
[  854.563627] This function was called , obtain param is 5
[  890.793224] in hello2.ko: leaving hello2 module successed ! 可以看出模块间的依赖关系。
[root@flydream MODULES]# rmmod helloworld
[root@flydream MODULES]# dmesg
[  737.870084] Enter helloworld module...
[  737.870086] param is 3
[  854.563622] in hello2.ko: request loaded module helloworld.ko success!
[  854.563627] This function was called , obtain param is 5
[  890.793224] in hello2.ko: leaving hello2 module successed !
[  901.294832] Exit helloworld module...
[root@flydream MODULES]# insmod ./hello2.ko
insmod: error inserting './hello2.ko': -1 Unknown symbol in module
7. linux内核结构体初始化时出现的.owner = THIS_MODULE是什么?
在阅读Linux内核源码时候经常会遇到一种神秘的结构体初始化情况  像这种  .owner = THIS_MODULE  这到底是怎么回事呢?其实这是Linux内核代码中一种特殊的结构体初始化方式---指定初始化。因为才谭浩强的书上也没有提到过,看过了一些C语言书也没有提到过。今天一查,原来这个是C99标准,这个目前也是最新的标准,之前我也清楚这件事,但是没意识到这是一个差别。网上找到一篇文章,写得很详细,copy过来了。
在阅读GNU/Linux内核代码时,我 们会遇到一种特殊的结构初始化方式。该方式是某些C教材(如谭二版、K&R二版)中没有介绍过的。这种方式称为指定初始化(designated initializer)。下面我们看一个例子,Linux-2.6.x/drivers/usb/storage/usb.c中有这样一个结构体初始化 项目:
static struct usb_driver usb_storage_driver = {
   .owner = THIS_MODULE,
   .name = "usb-storage",
   .probe = storage_probe,
   .disconnect = storage_disconnect,
   .id_table = storage_usb_ids,
};
乍一看,这与我们之前学过的结构体初始化差距甚远。其实这就是前面所说的指定初始化在Linux设备驱动程序中的一个应用,它源自ISO C99标准。以下我摘录了C Primer Plus第五版中相关章节的内容,从而就可以很好的理解2.6版内核采用这种方式的优势就在于由此初始化不必严格按照定义时的顺序。这带来了极大的灵活 性,其更大的益处还有待大家在开发中结合自身的应用慢慢体会。 已知一个结构,定义如下
struct book {
   char title[MAXTITL];
   char author[MAXAUTL];
   float value;
};
C99支持结构的指定初始化项目,其语法与数组的指定初始化项目近似。只是,结构的指定初始化项目使用点运算符和成员名(而不是方括号和索引值)来标识具体的元素。例如,只初始化book结构的成员value,可以这样做:
struct book surprise = { .value = 10.99 };
可以按照任意的顺序使用指定初始化项目:
struct book gift = {
   .value = 25.99,
   .author = "James Broadfool",
   .title = "Rue for the Toad"
};
正像数组一样,跟在一个指定初始化项目之后的常规初始化项目为跟在指定成员后的成员提供了初始值。

原作者:HugeDomains

更多回帖

发帖
×
20
完善资料,
赚取积分