免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1152 | 回复: 0
打印 上一主题 下一主题

(转帖)uClinux内核与驱动开发 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-01 22:41 |只看该作者 |倒序浏览

uClinux内核简介
• uCLinux 是Linux 2.0核心的分支,是针对没有
MMU管理单元的微控制器
• 继承了Linux的大多数特性
• 多数的Linux下应用程序和驱动程序都可以在uClinux下
运行
• 内核精简
• Kernel  80k 左右
移植uClinux的主要工作
• 选择处理器对应的交叉编译器
• 选择并修改Bootloader
• 修改链接文件(vmlinux-armv.lds.in),定位各
个数据段
• 定义系统定时器、控制台(Console)
• 编写中断的控制函数
• 定义根文件系统
• 编写其他系统设备驱动…
mic
2006-07-01 01:42
编译器的选择
uClinux内核在ARM上的编译
• 交叉编译器
• arm-elf-gcc、arm-linux-gcc
• 标准C库——应用程序
• uC-libc、uClibc
(uC)linux的bootloader
• 系统配置、中断接管、引导
• 装载内核、根文件系统、参数传递、内核调试、
内核和根文件系统的下载等等
• 常见的uClinux(Linux)的Bootloader:
• Redboot
• Blob
• Vivi
• Uboot
• armBoot…
读懂uClinux内核源码
• (uC)linux内核庞大,结构复杂
• 对uClinux内核的统计:接近1万个文件,4百万
行代码
• 内核编程习惯(技巧)不同于应用程序
mic
2006-07-01 01:45
(uC)linux内核的C代码
• Linux内核的主体使用GNU C,在ANSI C上进
行了扩充
• Linux内核必须由gcc编译编译
• gcc和linux内核版本并行发展,对于版本的依
赖性强
• 内核代码中使用的一些编程技巧,在通常的
应用程序中很少遇到
GNU C的扩充举例
• 从C++中吸收了inline和const关键字
• ANSI C代码与GNU C中的保留关键字冲突的
问题可以通过双下划线(_ _)解决
• 例如:inline 等价于__inline__、asm等价于
__asm__
• 结构体(struct)的初始化
结构体初始化
struct sample {
int member_int;
char *member_str;
void (*member_fun)(void);
};
ANSI C中的实现
struct sample inst_c={
100, //member_int
NULL, //*member_str;
myfunc //void (*member_fun)(void);
};
C99中的实现
struct sample inst_c99 = {
.member_int = 100,
.member_fun = myfun,
};
GCC中的实现
struct sample inst_gcc = {
member_fun: myfun,
member_int: 100,
};
与C99中的用法类似,不必关心struct定义的
中的实际的顺序和其他未定义的数据,在复
杂的结构体初始化的时候很有优势。
mic
2006-07-01 01:46
宏定义的灵活使用(1)
• 虽然GCC中定义了inline关键字,但是,宏
操作(#define)仍然在系统中大量使用
• 举例:
#define DUMP_WRITE(addr,nr) do\
{ memcpy(bufp,addr,nr); bufp += nr; } while(0)
应用DUMP_WRITE,就像使用C的函数一样:
if(addr)
DUMP_WRITE(addr, nr);
else…
但是,如果如通过下的定义,都不能满足上述的情况
定义1:
#define DUMP_WRITE(addr,nr) memcpy(bufp,addr,nr);\
bufp += nr ;
定义2:
#define DUMP_WRITE(addr,nr) {memcpy(bufp,addr,nr);\
bufp += nr;}
宏定义的灵活使用(2)
#define OFFSETOF(strct, elem) \
((long)&(((struct strct *)0)->elem))
• 1、((struct strct *)0) 结构体strct的指针
• 2、&((struct strct *)0)->elem)成员的地址,
也就是相对于0的偏移
• 3、结果:OFFSETOF(strct,elem)返回的是,结构
体strct中成员elem的偏移量
C语言中goto的使用
• 在应用程序的C编程中,为了保证程序的模
块化,建议不使用goto
• 内核代码需要兼顾到效率,所以,大量使用
goto
• 整个内核的比例大概是每260行一个goto语句—
—速度优先
• 短距离的goto——在函数中
mic
2006-07-01 01:49
(uC)linux的驱动程序
• Linux下对外设的访问只能通过驱动程序
• Linux对于驱动程序有统一的接口,以文件的形式
定义系统的驱动程序:
• Open、Release、read、write、ioctl…
• 驱动程序是内核的一部分,可以使用中断、DMA等
操作
• 驱动程序需要在用户态和内核态之间传递数据
• uClinux下可以在应用层直接访问外设,操作寄存
器口,但是无法处理中断——不推荐使用
• uClinux不支持模块加载
内核功能的划分
• 进程管理(进程之间的通讯与同步)
• 内存管理(malloc/free)
• 文件系统
• 设备控制
• 网络功能(网络通讯协议等)
Linux下设备和模块的分类
按照上述系统内核的功能,Linux中把系统
的设备定义成如下三类:
• 字符设备
• 块设备
• 网络设备
Linux下的设备
• Linux的设备以文件的形式存在于/dev目录下
• 设备文件是特殊文件,使用ls /dev -l命令可以
看到:
crw------- 1 root root 10, 7 Aug 31 2002 amigamouse1
crw------- 1 root root 10, 134 Aug 31 2002 apm_bios
brw-rw---- 1 root disk 29, 0 Aug 31 2002 aztcd
主设备号和次设备号
• 主设备号标识设备对应的驱动程序
• 一个驱动程序可以控制若干个设备,次设备号提
供了一种区分它们的方法
• 系统增加一个驱动程序就要赋予它一个主设备
号。这一赋值过程在驱动程序的初始化过程中
int register_chrdev(unsigned int major, const char
*name,struct file_operations *fops);
创建设备节点
• 设备已经注册到内核表中,对于设备的访问通过
设备文件(设备文件与设备驱动程序的主设备号
匹配),内核会调用驱动程序中的正确函数
• 给程序一个它们可以请求设备驱动程序的名字。
这个名字必须插入到/dev目录中,并与驱动程序
的主设备号和次设备号相连
• 使用mknod在文件系统上创建一个设备节点
mknod
/dev/mydevice
c 254 0
动态分配设备号
• 在Documentation/device.txt文件中可以找
到已经静态分配给大部分设备的列表
• 由于许多数字已经分配了,为新设备选择一
个唯一的号码是很困难的
• 如果调用register_chrdev时的major为零,
函数就会选择一个空闲号码并做为返回值返

动态分配的问题
动态分配的主设备号不能保证总是一样的,
无法事先创建设备节点
• 可以从/proc/devices读取
cat /proc/devices
• 利用脚本动态创建设备文件节点
设备管理的问题
如今,Linux 支持很多不同种类的硬件。这
意味着/dev中都有数百个特殊文件来表示所有
这些设备。而且,这些特殊文件中大多数甚至
不会映射到系统中存在的设备上
使用devfs
• 在Linux 2.4的内核里引入了devfs来解决
linux下设备文件管理的问题
• 在驱动程序中通过devfs_register()函数创
建设备文件系统的节点
• 系统启动的时候mount设备文件系统
• 所有需要的设备节点都由内核自动管理。
/dev目录下只有挂载的设备

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/34944/showart_269231.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP