2005年10月09日


Linux的发行版中包含了很多软件开发工具。 它们中的很多是用于 C 和 C++应用程序开发的。 本文介绍了在 Linux 下能用于 C 应用程序开发和调试的工具。 本文的主旨是介绍如何在 Linux 下使用 C 编译器和其他 C 编程工具, 而非 C 语言编程的教程。 在本文中你将学到以下知识: 
 
· 什么是 C 
· GNU C 编译器 
· 用 gdb 来调试GCC应用程序 
你也能看到随 Linux 发行的其他有用的 C 编程工具。 这些工具包括源程序美化程序(pretty print programs), 附加的调试工具, 函数原型自动生成工具(automatic function prototypers)。 
 
注意: 源程序美化程序(pretty print programs)自动帮你格式化源代码产生始终如一的缩进格式。 
 
什么是 C?
C 是一种在 UNIX 操作系统的早期就被广泛使用的通用编程语言。 它最早是由贝尔实验室的 Dennis Ritchie 为了 UNIX 的辅助开发而写的, 开始时 UNIX 是用汇编语言和一种叫 B 的语言编写的。 从那时候起, C 就成为世界上使用最广泛计算机语言。 
 
C 能在编程领域里得到如此广泛支持的原因有以下一些: 
· 它是一种非常通用的语言。 几乎你所能想到的任何一种计算机上都有至少一种能用的 C 编译器。 并且它的语法和函数库在不同的平台上都是统一的, 这个特性对开发者来说很有吸引力。 
· 用 C 写的程序执行速度很快。 
· C 是所有版本的UNIX上的系统语言。 
C 在过去的二十年中有了很大的发展。 在80年代末期美国国家标准协会(American National Standards Institute)发布了一个被称为 ANSI C 的 C 语言标准。这更加保证了将来在不同平台上的 C 的一致性。 在80年代还出现了一种 C 的面向对象的扩展称为 C++。 C++ 将在另一篇文章 "C++ 编程"中描述。 
Linux 上可用的 C 编译器是 GNU C 编译器, 它建立在自由软件基金会的编程许可证的基础上, 因此可以自由发布。 你能在 Linux 的发行光盘上找到它。 
GNU C 编译器
随 Slackware Linux 发行的 GNU C 编译器(GCC)是一个全功能的 ANSI C 兼容编译器。 如果你熟悉其他操作系统或硬件平台上的一种 C 编译器, 你将能很快地掌握 GCC。 本节将介绍如何使用 GCC 和一些 GCC 编译器最常用的选项。 
 
使用 GCC
通常后跟一些选项和文件名来使用 GCC 编译器。 gcc 命令的基本用法如下: 
gcc [options] [filenames]
命令行选项指定的操作将在命令行上每个给出的文件上执行。 下一小节将叙述一些你会最常用到的选项。 
 
GCC 选项
GCC 有超过100个的编译选项可用。 这些选项中的许多你可能永远都不会用到, 但一些主要的选项将会频繁用到。 很多的 GCC 选项包括一个以上的字符。 因此你必须为每个选项指定各自的连字符, 并且就象大多数 Linux 命令一样你不能在一个单独的连字符后跟一组选项。 例如, 下面的两个命令是不同的: 
gcc -p -g test.c
 
gcc -pg test.c
第一条命令告诉 GCC 编译 test.c 时为 prof 命令建立剖析(profile)信息并且把调试信息加入到可执行的文件里。 第二条命令只告诉 GCC 为 gprof 命令建立剖析信息。 
 
当你不用任何选项编译一个程序时, GCC 将会建立(假定编译成功)一个名为 a.out 的可执行文件。 例如, 下面的命令将在当前目录下产生一个叫 a.out 的文件: 
gcc test.c
你能用 -o 编译选项来为将产生的可执行文件指定一个文件名来代替 a.out。 例如, 将一个叫 count.c 的 C 程序编译为名叫 count 的可执行文件, 你将输入下面的命令: 
gcc -o count count.c
 
注意: 当你使用 -o 选项时, -o 后面必须跟一个文件名。 
 
GCC 同样有指定编译器处理多少的编译选项。 -c 选项告诉 GCC 仅把源代码编译为目标代码而跳过汇编和连接的步骤。 这个选项使用的非常频繁因为它使得编译多个 C 程序时速度更快并且更易于管理。 缺省时 GCC 建立的目标代码文件有一个 .o 的扩展名。 
-S 编译选项告诉 GCC 在为 C 代码产生了汇编语言文件后停止编译。 GCC 产生的汇编语言文件的缺省扩展名是 .s 。 -E 选项指示编译器仅对输入文件进行预处理。 当这个选项被使用时, 预处理器的输出被送到标准输出而不是储存在文件里。 
优化选项
当你用 GCC 编译 C 代码时, 它会试着用最少的时间完成编译并且使编译后的代码易于调试。 易于调试意味着编译后的代码与源代码有同样的执行次序, 编译后的代码没有经过优化。 有很多选项可用于告诉 GCC 在耗费更多编译时间和牺牲易调试性的基础上产生更小更快的可执行文件。 这些选项中最典型的是-O 和 -O2 选项。 
-O 选项告诉 GCC 对源代码进行基本优化。 这些优化在大多数情况下都会使程序执行的更快。 -O2 选项告诉 GCC 产生尽可能小和尽可能快的代码。 -O2 选项将使编译的速度比使用 -O 时慢。 但通常产生的代码执行速度会更快。 
除了 -O 和 -O2 优化选项外, 还有一些低级选项用于产生更快的代码。 这些选项非常的特殊, 而且最好只有当你完全理解这些选项将会对编译后的代码产生什么样的效果时再去使用。 这些选项的详细描述, 请参考 GCC 的指南页, 在命令行上键入 man gcc 。 
调试和剖析选项
GCC 支持数种调试和剖析选项。 在这些选项里你会最常用到的是 -g 和 -pg 选项。 
-g 选项告诉 GCC 产生能被 GNU 调试器使用的调试信息以便调试你的程序。 GCC 提供了一个很多其他 C 编译器里没有的特性, 在 GCC 里你能使 -g 和 -O (产生优化代码)联用。 这一点非常有用因为你能在与最终产品尽可能相近的情况下调试你的代码。 在你同时使用这两个选项时你必须清楚你所写的某些代码已经在优化时被 GCC 作了改动。 关于调试 C 程序的更多信息请看下一节"用 gdb 调试 C 程序" 。 
-pg 选项告诉 GCC 在你的程序里加入额外的代码, 执行时, 产生 gprof 用的剖析信息以显示你的程序的耗时情况。 关于 gprof 的更多信息请参考 "gprof" 一节。 
 
用 gdb 调试 GCC 程序
Linux 包含了一个叫 gdb 的 GNU 调试程序。 gdb 是一个用来调试 C 和 C++ 程序的强力调试器。 它使你能在程序运行时观察程序的内部结构和内存的使用情况。 以下是 gdb 所提供的一些功能: 
· 它使你能监视你程序中变量的值。 
· 它使你能设置断点以使程序在指定的代码行上停止执行。 
· 它使你能一行行的执行你的代码。 
 
在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容: 
GDB is free software and you are welcome to distribute copies of it
 
under certain conditions; type "show copying" to see the conditions.
 
There is absolutely no warranty for GDB; type "show warranty" for details.
 
GDB 4.14 (i486-slakware-linux), Copyright 1995 Free Software Foundation, Inc.
 
(gdb)
当你启动 gdb 后, 你能在命令行上指定很多的选项。 你也可以以下面的方式来运行 gdb : 
gdb 
当你用这种方式运行 gdb , 你能直接指定想要调试的程序。 这将告诉gdb 装入名为 fname 的可执行文件。 你也可以用 gdb 去检查一个因程序异常终止而产生的 core 文件, 或者与一个正在运行的程序相连。 你可以参考 gdb 指南页或在命令行上键入 gdb -h 得到一个有关这些选项的说明的简单列表。 
 
为调试编译代码(Compiling Code for Debugging)
为了使 gdb 正常工作, 你必须使你的程序在编译时包含调试信息。 调试信息包含你程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号。 gdb 利用这些信息使源代码和机器码相关联。 
在编译时用 -g 选项打开调试选项。 
 
gdb 基本命令
gdb 支持很多的命令使你能实现不同的功能。 这些命令从简单的文件装入到允许你检查所调用的堆栈内容的复杂命令, 表27.1列出了你在用 gdb 调试时会用到的一些命令。 想了解 gdb 的详细使用请参考 gdb 的指南页。 
表 27.1. 基本 gdb 命令. 
命令描述
file  装入想要调试的可执行文件。
kill  终止正在调试的程序。
list   执行一行源代码但不进入函数内部。
next  执行一行源代码但不进入函数内部。
step 执行一行源代码而且进入函数内部。
run 执行当前被调试的程序
quit  终止 gdb
watch  使你能监视一个变量的值而不管它何时被改变。
break  在代码里设置断点, 这将使程序执行到这里时被挂起。
make  使你能不退出 gdb 就可以重新产生可执行文件。
shell  使你能不离开 gdb 就执行 UNIX shell 命令。
gdb 支持很多与 UNIX shell 程序一样的命令编辑特征。 你能象在 bash 或 tcsh里那样按 Tab 键让 gdb 帮你补齐一个唯一的命令, 如果不唯一的话 gdb 会列出所有匹配的命令。 你也能用光标键上下翻动历史命令。 
gdb 应用举例
本节用一个实例教你一步步的用 gdb 调试程序。 被调试的程序相当的简单, 但它展示了 gdb 的典型应用。 
 
下面列出了将被调试的程序。 这个程序被称为 greeting , 它显示一个简单的问候, 再用反序将它列出。 
#include 
main ()
{
char my_string[] = "hello there";
my_print (my_string);
my_print2 (my_string);
}
void my_print (char *string)
{
printf ("The string is %s\n", string);
}
void my_print2 (char *string)
{
char *string2;
int size, i;
size = strlen (string);
string2 = (char *) malloc (size + 1);
for (i = 0; i < size; i++)
string2[size - i] = string[i];
string2[size+1] = `\0′;
printf ("The string printed backward is %s\n", string2);
}
用下面的命令编译它: 
gcc -o test test.c
这个程序执行时显示如下结果: 
The string is hello there
The string printed backward is
输出的第一行是正确的, 但第二行打印出的东西并不是我们所期望的。 我们所设想的输出应该是: 
The string printed backward is ereht olleh
由于某些原因, my_print2 函数没有正常工作。 让我们用 gdb 看看问题究竟出在哪儿, 先键入如下命令: 
gdb greeting
注意: 记得在编译 greeting 程序时把调试选项打开。 
 
如果你在输入命令时忘了把要调试的程序作为参数传给 gdb , 你可以在 gdb 提示符下用 file 命令来载入它: 
 
(gdb) file greeting
这个命令将载入 greeting 可执行文件就象你在 gdb 命令行里装入它一样。 
这时你能用 gdb 的 run 命令来运行 greeting 了。 当它在 gdb 里被运行后结果大约会象这样: 
(gdb) run
 
Starting program: /root/greeting
 
The string is hello there
 
The string printed backward is
 
Program exited with code 041
这个输出和在 gdb 外面运行的结果一样。 问题是, 为什么反序打印没有工作? 为了找出症结所在, 我们可以在 my_print2 函数的 for 语句后设一个断点, 具体的做法是在 gdb 提示符下键入 list 命令三次, 列出源代码: 
(gdb) list
 
(gdb) list
 
(gdb) list
 
技巧: 在 gdb 提示符下按回车健将重复上一个命令。 
 
第一次键入 list 命令的输出如下: 
 
1 #include 
 
2
 
3 main ()
 
4 {
 
5 char my_string[] = "hello there";
 
6
 
7 my_print (my_string);
 
8 my_print2 (my_string);
 
9 }
 
10
如果按下回车, gdb 将再执行一次 list 命令, 给出下列输出: 
 
11 my_print (char *string)
 
12 {
 
13 printf ("The string is %s\n", string);
 
14 }
 
15
 
16 my_print2 (char *string)
 
17 {
 
18 char *string2;
 
19 int size, i;
 
20
再按一次回车将列出 greeting 程序的剩余部分: 
21 size = strlen (string);
 
22 string2 = (char *) malloc (size + 1);
 
23 for (i = 0; i < size; i++)
 
24 string2[size - i] = string[i];
 
25 string2[size+1] = `\0′;
 
26 printf ("The string printed backward is %s\n", string2);
 
27 }
根据列出的源程序, 你能看到要设断点的地方在第24行, 在 gdb 命令行提示符下键入如下命令设置断点: 
(gdb) break 24
gdb 将作出如下的响应: 
Breakpoint 1 at 0×139: file greeting.c, line 24
 
(gdb)
 
现在再键入 run 命令, 将产生如下的输出: 
 
Starting program: /root/greeting
 
The string is hello there
Breakpoint 1, my_print2 (string = 0xbfffdc4 "hello there") at greeting.c :24
 
24 string2[size-i]=string[i]
你能通过设置一个观察 string2[size - i] 变量的值的观察点来看出错误是怎样产生的, 做法是键入: 
 
(gdb) watch string2[size - i]
gdb 将作出如下回应: 
Watchpoint 2: string2[size - i]
现在可以用 next 命令来一步步的执行 for 循环了: 
 
(gdb) next
经过第一次循环后, gdb 告诉我们 string2[size - i] 的值是 `h`。 gdb 用如下的显示来告诉你这个信息: 
 
Watchpoint 2, string2[size - i]
 
Old value = 0 `\000′
 
New value = 104 `h’
 
my_print2(string = 0xbfffdc4 "hello there") at greeting.c:23
 
23 for (i=0; i
这个值正是期望的。 后来的数次循环的结果都是正确的。 当 i=10 时, 表达式 string2[size - i] 的值等于 `e`, size – i 的值等于 1, 最后一个字符已经拷到新串里了。 
如果你再把循环执行下去, 你会看到已经没有值分配给 string2[0] 了, 而它是新串的第一个字符, 因为 malloc 函数在分配内存时把它们初始化为空(null)字符。 所以 string2 的第一个字符是空字符。 这解释了为什么在打印 string2 时没有任何输出了。 
现在找出了问题出在哪里, 修正这个错误是很容易的。 你得把代码里写入 string2 的第一个字符的的偏移量改为 size – 1 而不是 size。 这是因为 string2 的大小为 12, 但起始偏移量是 0, 串内的字符从偏移量 0 到 偏移量 10, 偏移量 11 为空字符保留。 
为了使代码正常工作有很多种修改办法。 一种是另设一个比串的实际大小小 1 的变量。 这是这种解决办法的代码: 
#include 
main ()
{
 
char my_string[] = "hello there";
my_print (my_string);
 
my_print2 (my_string);
 
}
my_print (char *string)
 
{
 
printf ("The string is %s\n", string);
 
}
my_print2 (char *string)
 
{
 
char *string2;
 
int size, size2, i;
size = strlen (string);
 
size2 = size -1;
 
string2 = (char *) malloc (size + 1);
 
for (i = 0; i < size; i++)
 
string2[size2 - i] = string[i];
 
string2[size] = `\0′;
 
printf ("The string printed backward is %s\n", string2);
 
}
另外的 C 编程工具
Slackware Linux 的发行版中还包括一些我们尚未提到的 C 开发工具。 本节将介绍这些工具和它们的典型用法。 
xxgdb
xxgdb 是 gdb 的一个基于 X Window 系统的图形界面。 xxgdb 包括了命令行版的 gdb 上的所有特性。 xxgdb 使你能通过按按钮来执行常用的命令。 设置了断点的地方也用图形来显示。 
 
你能在一个 Xterm 窗口里键入下面的命令来运行它: 
xxgdb
你能用 gdb 里任何有效的命令行选项来初始化 xxgdb 。 此外 xxgdb 也有一些特有的命令行选项, 表 27.2 列出了这些选项。 
 
表 27.2. xxgdb 命令行选项. 
选 项  描 述 
db_name   指定所用调试器的名字, 缺省是 gdb。 
db_prompt   指定调试器提示符, 缺省为 gdb。 
gdbinit   指定初始化 gdb 的命令文件的文件名, 缺省为 .gdbinit。 
nx   告诉 xxgdb 不执行 .gdbinit 文件。 
bigicon   使用大图标。 
calls
你可以在 sunsite.unc.edu FTP 站点用下面的路径: 
/pub/Linux/devel/lang/c/calls.tar.Z 
来取得 calls , 一些旧版本的 Linux CD-ROM 发行版里也附带有。 因为它是一个有用的工具, 我们在这里也介绍一下。 如果你觉得有用的话, 从 BBS, FTP, 或另一张CD-ROM 上弄一个拷贝。 calls 调用 GCC 的预处理器来处理给出的源程序文件, 然后输出这些文件的里的函数调用树图。 
注意: 在你的系统上安装 calls , 以超级用户身份登录后执行下面的步骤: 1. 解压和 untar 文件。 2.cd 进入 calls untar 后建立的子目录。 3.把名叫 calls 的文件移动到 /usr/bin 目录。 4.把名叫 calls.1 的文件移动到目录 /usr/man/man1 。 5.删除 /tmp/calls 目录。 这些步骤将把 calls 程序和它的指南页安装载你的系统上。 
 
当 calls 打印出调用跟踪结果时, 它在函数后面用中括号给出了函数所在文件的文件名: 
main [test.c]
如果函数并不是向 calls 给出的文件里的, calls 不知道所调用的函数来自哪里, 则只显示函数的名字: 
printf
calls 不对递归和静态函数输出。 递归函数显示成下面的样子: 
fact <<< recursive in factorial.c >>>
静态函数象这样显示: 
total [static in calculate.c]
作为一个例子, 假设用 calls 处理下面的程序: 
 
#include 
main ()
 
{
 
char my_string[] = "hello there";
 
my_print (my_string);
 
my_print2(my_string);
 
}
my_print (char *string)
 
{
 
printf ("The string is %s\n", string);
 
}
my_print2 (char *string)
 
{
 
char *string2;
 
int size, size2, i;
size = strlen (string);
 
size2 = size -1;
 
string2 = (char *) malloc (size + 1);
 
for (i = 0; i < size; i++)
 
string2[size2 - i] = string[i];
 
string2[size] = `\0′;
 
printf ("The string printed backward is %s\n", string2);
 
}
将产生如下的输出: 
1 main [test.c]
 
2 my_print [test.c]
 
3 printf
 
4 my_print2 [test.c]
 
5 strlen
 
6 malloc
 
7 printf
calls 有很多命令行选项来设置不同的输出格式, 有关这些选项的更多信息请参考 calls 的指南页。 方法是在命令行上键入 calls -h 。 
cproto
cproto 读入 C 源程序文件并自动为每个函数产生原型申明。 用 cproto 可以在写程序时为你节省大量用来定义函数原型的时间。 
如果你让 cproto 处理下面的代码: 
#include 
main ()
 
{
 
char my_string[] = "hello there";
 
my_print (my_string);
 
my_print2(my_string);
 
}
my_print (char *string)
 
{
 
printf ("The string is %s\n", *string);
 
}
my_print2 (char *string)
 
{
 
char *string2;
 
int size, size2, i;
size = strlen (string);
 
size2 = size -1;
 
string2 = (char *) malloc (size + 1);
 
for (i = 0; i < size; i++)
 
string2[size2 - i] = string[i];
 
string2[size] = `\0′;
 
printf ("The string printed backward is %s\n", string2);
 
}
你将得到下面的输出: 
/* test.c */
 
int main(void);
 
int my_print(char *string);
 
int my_print2(char *string);
这个输出可以重定向到一个定义函数原型的包含文件里。 
indent
indent 实用程序是 Linux 里包含的另一个编程实用工具。 这个工具简单的说就为你的代码产生美观的缩进的格式。 indent 也有很多选项来指定如何格式化你的源代码。这些选项的更多信息请看indent 的指南页, 在命令行上键入 indent -h 。 
 
下面的例子是 indent 的缺省输出: 
运行 indent 以前的 C 代码: 
#include 
main () {
 
char my_string[] = "hello there";
 
my_print (my_string);
 
my_print2(my_string); }
my_print (char *string)
{
printf ("The string is %s\n", *string);
 
}
my_print2 (char *string) {
 
char *string2;
 
int size, size2, i;
size = strlen (string);
 
size2 = size -1;
 
string2 = (char *) malloc (size + 1);
 
for (i = 0; i < size; i++)
 
string2[size2 - i] = string[i];
 
string2[size] = `\0′;
printf ("The string printed backward is %s\n", string2);
 
}
运行 indent 后的 C 代码: 
#include 
main ()
{
char my_string[] = "hello there";
 
my_print (my_string);
 
my_print2 (my_string);
 
}
my_print (char *string)
 
{
printf ("The string is %s\n", *string);
my_print2 (char *string)
{
char *string2;
 
int size, size2, i;
size = strlen (string);
 
size2 = size -1;
 
string2 = (char *) malloc (size + 1);
 
for (i = 0; i < size; i++)
 
string2[size2 - i] = string[i];
 
string2[size] = `\0′;
 
printf ("The string printed backward is %s\n", string2);
 
}
indent 并不改变代码的实质内容, 而只是改变代码的外观。 使它变得更可读, 这永远是一件好事。 
gprof
gprof 是安装在你的 Linux 系统的 /usr/bin 目录下的一个程序。 它使你能剖析你的程序从而知道程序的哪一个部分在执行时最费时间。 
gprof 将告诉你程序里每个函数被调用的次数和每个函数执行时所占时间的百分比。 你如果想提高你的程序性能的话这些信息非常有用。 
为了在你的程序上使用 gprof, 你必须在编译程序时加上 -pg 选项。 这将使程序在每次执行时产生一个叫 gmon.out 的文件。 gprof 用这个文件产生剖析信息。 
在你运行了你的程序并产生了 gmon.out 文件后你能用下面的命令获得剖析信息: 
gprof 
参数 program_name 是产生 gmon.out 文件的程序的名字。 
技巧: gprof 产生的剖析数据很大, 如果你想检查这些数据的话最好把输出重定向到一个文件里。 
f2c 和 p2c
f2c 和 p2c 是两个源代码转换程序。 f2c 把 FORTRAN 代码转换为 C 代码, p2c 把 Pascal 代码转换为 C 代码。 当你安装 GCC 时这两个程序都会被安装上去。 
如果你有一些用 FORTRAN 或 Pascal 写的代码要用 C 重写的话, f2c 和 p2c 对你非常有用。 这两个程序产生的 C 代码一般不用修改就直接能被 GCC 编译。 
如果要转换的 FORTRAN 或 Pascal 程序比较小的话可以直接使用 f2c 或 p2c 不用加任何选项。 如果要转换的程序比较庞大, 包含很多文件的话你可能要用到一些命令行选项。 
在一个 FORTRAN 程序上使用 f2c , 输入下面的命令: 
f2c my_fortranprog.f
 
注意: f2c 要求被转换的程序的扩展名为 .f 或 a .F 。 
 
要把一个Pascal 程序装换为 C 程序, 输入下面的命令: 
p2c my_pascalprogram.pas
这两个程序产生的 C 源代码的文件名都和原来的文件名相同, 但扩展名由 .f 或 .pas 变为 .c 。

2005年10月08日


硬件规格
•行动通讯、音效编译码电路板规格说明:
(1)行动通讯支持:GSM
(2)无线网络支持:GPRS / PDA
(3)音效编译码:Audio CODEC / MP3/MPEG4
(4)音源输出/入:麦克风输入接头 / 喇叭输出接头
(5)预留模块:无线网络Camera 802.11b /CF Card / 蓝芽/ FM / GPS全球定位系统
•CPU板规格:
(1)CPU : TI OMAP5910 -150MHz, ARM 925 + DSP 55X ;
(2)SDRAM : 32MB ;
(3)Flash Memory : Intel Strata Flash E28F128J3(16MB NOR) up to Max 32MB ; (PS:M-Systems Disk On Chip : By Request ;)
(4)LED: 2 LED ;
(5)RESET Button : yes;
(6)Debug Interface : JTAG ;
(7)UART : COM1;
(8)SRAM :Option ( 61LV25616 256K x 16 bit )
(9)Serial EEPROM(I2C ) : 24LC02B(选配)
•LCD 电路规格说明:
(1)触控板 : 4 wire type
(2)LCD :
款式:SHARP 3.5吋TFT,
分辨率:240×320,16位高分辨率
支援:高亮度背光
画素:262,144 colors
•电源板规格说明:
(1)输入电压 : DC +5V,
(2)输出电压 : DC 3V/3.3V,
(3)电源指示灯, 可支持记忆电池接脚
•主板规格说明:
(1)USB 支援 : USB 1.1 Host / Client
(2)记忆卡插槽 : SD Memory card slot;
(3)串行接口 : 提供四组串行接口
(4)键盘 : 5×6 按钮开关
(5)LED : 16颗 LED
(6)网络接口 : Ethernet RJ-45
 软件规格
•主控端可工作于标准的计算机终端机接口(Ex :Linux Minicom)可下载数个映像档至SDRAM包含srec 和 rrbin(二进制) 格式支持数个输出/入接脚; 串行传输和网络接口内存配置管理嵌入于组件中供系统保存与回复自动执行使用者所预先储存的列表于系统开机区中.
 工具套件
Binutils        2.10           Utilities for dealing with object files
Gcc               2.95.2       GNU C compiler
Glibc             2.1.3         GNU C library
 Linux Kernel
Kernel          2.4.20       Based on Linux for ARM
 实习项目
•GSM行动通讯/ GPRS行动无线网络
•PDA整合平台实验
•BOOTLOADER实验
•Ethernet通讯实验
•USB Host/Client界面实验
•Mp3音效接口实验
•MPEG4档案拨放实验
•16组LED规划实验
•SD 卡实验
•6X5键盘规划实验
•4组RS232串行传输接口实习
•熟悉嵌入式MontaVista Linux开发环境
•4 wire LCD触控屏幕实验
•MIC界面实验
•PDA整合平台实验
•JTAG下载实习
•喇叭接口实验
•I2C界面实验

2005年10月05日

[文章导读]JFS应该是未来日志文件系统中最具实力的一个文件系统……

JFS是IBM公司为linux系统开发的一个日志文件系统。从IBM的实力及它对Linux的态度来看,JFS应该是未来日志文件系统中最具实力的一个文件系统。

JFS提供了基于日志的字节级文件系统,该文件系统是为面向事务的高性能系统而开发的。JFS 能够在几秒或几 分钟内就把文件系统恢复到一致状态。JFS能够保证数据在任何意外宕机的情况下,不会造成磁盘数据的丢失与损坏。

一、JFS文件系统特点

1.存储空间更大

JFS 支持的最小文件系统是 16M 字节。最大文件系统的大小为 512 万亿字节(TB)。JFS 是真正意义上的 64 位的文件系统。所有 JFS 文件系统结构化字段都是 64 位大小。

2.动态磁盘 inode 分配

JFS 按需为磁盘 inode 动态地分配空间,释放不再需要的空间。这种方式避开了在文件系统创建期间,为磁盘 inode 保留固定数量空间的传统方法。用户不需要考虑文件系统包含的文件和目录最大数目。

3.基于盘区的寻址结构

JFS 使用基于盘区的寻址结构,JFS 分配尝试通过分配最小数量的盘区策略,而使每个盘区尽可能大。这有利于大的 I/O 传送,磁盘读写性能所有提高。

4.块尺寸可变

JFS 支持 512、1024、2048 和 4096 字节的块尺寸,允许用户根据应用环境优化空间利用率。较小的块尺寸减少有利于内部存储碎片的数量,提高空间利用率。系统缺省块尺寸为 4096 字节。

二、使用JFS文件系统

1.编译内核以支持JFS文件系统

首先下载最新的2.4.x 核心,下载地址ftp://ftp.kernel.org/。然后下载JFS系统软件包:http://www-124.ibm.com/developerworks/oss/jfs/,名称为:jfs-x.y.z-patch.tar.gz。 将下载文件存放在/usr/src目录中。

在/usr/src/上当目录下解开jfs的软件包

# tar –zxvf jfs-2.4-1.0.4.tar.gz

# tar –zxvf jfs-2.4-1.0.4-patch.tar.gz

得到四个文件:

jfs-2.4.common-v1.0.4-patch

jfs-2.4.7-v1.0.4-patch

jfs-2.4.5-v1.0.4-patch

jfs-2.4.0-v1.0.4-patch

其中,jfs-2.4.common-v1.0.4-patch文件用于所有的2.4核心,jfs-2.4.0-v1.0.4-patch用于2.4.0-2.4.2。jfs-2.4.5-v1.0.4-patch可用于核心2.4.5及2.4.6。

注意仔细阅读README文件,不要用错了patch文件

接着是为核心打补丁:

# patch –p1 < jfs-2.4.5-v1.0.4-patch

打补丁工作完成。

最后运行

#make menuconfig

将新的文件系统加入了核心编译配置文件中,要进行以下内核配置:

使用make menuconfig 在菜单"Code maturity level options"中,选择"Prompt for development and/or incomplete code/drivers."选项。然后,进入文件系统菜单"File systems",选择"JFS filesystem support."选项。配置核心,使核心支持JFS文件系统。配置核心的其它选项。

<*> JFS filesystem support

 

##将JFS文件系统的支持编译入内核,也可以将其编译成模块加载方式,见以下选择:

<M> JFS filesystem support

笔者建议将JFS文件系统支持直接编译进内核,这有利于提高系统性能。

然后编译核心:

#make dep

#make clean

#make bzImage

#make modules

#make modules_install

#cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.5-jfs

最后,编辑 /etc/lilo.conf 文件,加入新内核条目,以便使用新的内核引导系统。如下所示,在 lilo.conf文件中加入以下几行内容:

image=/boot/vmlinuz-2.4.5-jfs

label=jfs

read-only

root=/dev/hda5

然后运行lilo,使更改生效。

#lilo

三、创建JFS文件系统

1.查看系统对JFS文件系统的支持

如果新的内核正确启动,这说明核心已支持JFS文件系统了。查看系统进程,可以看到以下进程:

#lsmod

7 ? SW 0:00 [jfsIO]

8 ? SW 0:00 [jfsCommit]

9 ? SW 0:00 [jfsSync]

如果你看到了以上这几个进程,这表明系统核心已支持JFS文件系统。

另外,在/proc/fs/jfs 目录下应该还有三个文件:

jfsFYI

logmgr

TxAnchor

2.下载编译JFS文件系统工具

 

为了使用JFS文件系统,我们还需要创建文件系统的工具,到IBM的JFS网站下载相应工具jfsutils-1.0.7.tar.gz软件包。

下载地址:http://oss.software.ibm.com/developer/opensource/jfs/project/pub/jfsutils-1.0.7.tar.gz

编译安装过程如下:

#tar –zxvf jfsutils-1.0.7.tar.gz

#cd jfsutils-1.0.7

#./configure

#make

#make install

安装完成后,在/usr/sbin中就多出一个 可执行文件mkfs.jfs,我们就用它将分区格式化成jfs文件系统。

3.创建JFS文件系统

以下开始创建一个JFS文件系统, 将hda6分区格式化成JFS文件系统,以下为格式化时显示的内容:

#mkfs -t jfs /dev/hda6

mkfs.jfs development version: $Name: v0_3_1 $

Warning! All data on device /dev/hda6 will be lost!

Continue? (Y/N) y

\

Format completed successfully.

5120608 kilobytes total disk space.

运行完成后,JFS文件系统已经在hda6分区创建完成了。

4.加载JFS文件系统

首先,创建一个目录jfs,以便将JFS文件系统mount到其上:

#mkdir jfs

将新的分区mount到jfs目录下:

#mount –t jfs /dev/hda6 /jfs

这样,新的文件系统就加载到/jfs目录下了。现在可以使用新的文件系统了。

四、使用JFS文件系统

1.普通分区使用JFS文件系统

Linux内核支持了JFS文件系统后,可以将磁盘所有分区均格式化为JFS文件系统。通常情况下,建议/usr,/usr/sbin等分区采用非日志文件系统,而在那些对读写要求频繁的分区上使用JFS文件系统。这有利于提高系统性能。

2.主引导区使用JFS文件系统

主分区为linux的启动分区,其中存放了系统启动所需的基本文件。以下开始将JFS文件系统用于主分区,首先备份主分区上的所有常用文件目录:

#cd /

#cp -a bin etc lib boot dev home usr var [...] /jfs

#mkdir /jfs/proc

在使用JFS文件系统启动之前,还应该更改/etc/fstab文件,将相应的分区用作根分区。如下所示:原来的根分区为:

LABEL=/ / ext2 defaults 1 1

应该更改为:

/dev/hda6 / jfs defaults 1 1

然后,编译/etc/lilo.conf文件,将主引导分区更改为/dev/hda6。置label为jfs,将缺省的启动设置为jfs。

如下所示:

default=jfs

image=/boot/vmlinuz-2.4.0-jfs

label=jfs

read-only

root=/dev/hda6

然后,运行lilo,完成。

最后,reboot 系统,启动之后,你就得到一个纯jfs文件系统的linux环境了,剩下的事情就是将原来的主分区重新格式化成 jfs,然后再将其mount到主分区的某个目录下就行了。

来源: 天极网
 


一、下载与编译

下载GFS文件系统 

GFS文件系统以前是一个源代码完全公开的项目,直至版本为GFS-4.2.0时都可以下载到源代码。笔者在写这一篇文章时,下载到了GFS4.2.0的源代码,但是现在再也无法下载到GFS4.2.0以后的代码了,因为GFS开始收费了。不过,4.1.1及以前的版本仍然可以在这里下载到。试用版可以通过在http://www.sistina.com/注册后下载使用30天。

1、编译核心

本文以GFS4.2.0为例进行说明。首先对核心打补丁,运行以下脚本,为核心打补丁:

# ./GFS-contribe-4.2.0/scripte/apply_patch –k /usr/src/linux –p

回答一大串的yes,

完成打补丁工作。之后,运行以下命令:

#make menuconfig

#make dep

#make bzImage;make modules; make modules_install

#cp bzImage /boot

编辑/etc/lilo.conf,运行lilo之后,重新启动系统。

2、安装GFS文件系统的配套工具软件安装步骤如下:

#tar –zxvf GFS-4.2.0.tar.gz

编译过程如下:

#./configure

#make

#make install

编译安装GFS工具完成。

二、使用GFS文件系统

在编译时,将GFS编译为可加载模块,所以在使用时,首先要加载GFS模块。加载模块命令如下:

#modprobe nolock

在加载gfs模块之前首先要加载nolock模块,因为gfs依赖于nolock模块

#modprobe gfs

编译时,GFS文件系统是以可插入模块方式编译的,所以用此命令加载gfs模块。

内核加载了对GFS文件系统的支持模块后,接下来是创建一个GFS文件系统,使用GFS工具创建GFS文件系统,创建过程如下:

[root@test /sbin]# ./mkfs_gfs -j 5 /dev/sda8 –p nolock

Device: /dev/sda8

Blocksize: 4096

Filesystem Size: 177484

Journals: 5

Resource Groups: 10

Locking Protocol:

Lock Table:

Syncing…

All Done

[root@test /sbin]#

说明:将分区/dev/sda8格式化为gfs文件系统,在本分区内保存日志记录。

格式化完成后,下来是加载GFS文件系统

# mount –t gfs /dev/hda8 /gfs ##说明:将GFS分区加载到/gfs目录下

GFS: Trying to acquire journal lock 0…

GFS: Trying at journal 0…

GFS: Done

以上表示成功mount,接下来就可以使用了。

为了让以后机器启动以后自动加载GFS文件系统,需要改写/etc/fstab文件,加以下内容:

/dev/hda8 /gfs default 0 0

以后系统启动时就会自动加载GFS文件系统了。
 
                                                                                                                              来源: 天极网

内核版本: 2.4.22
阅读此文的目的: 学会编写Linux设备驱动。
阅读此文的方法: 阅读以下2个文件: hello.c,asdf.c。
此文假设读者:
已经能用C语言编写Linux应用程序,
理解"字符设备文件, 块设备文件, 主设备号, 次设备号",
会写简单的Shell脚本和Makefile。

1. "hello.c"
——————————–
/*
* 这是我们的第一个源文件,
* 它是一个可以加载的内核模块,
* 加载时显示"Hello,World!",
* 卸载时显示"Bye!"。

* 需要说明一点,写内核或内核模块不能用写应用程序时的系统调用或函数库,
* 因为我们写的就是为应用程序提供系统调用的代码。

* 内核有专用的函数库,如<linux/kernel.h>, <linux/fs.h>, <linux/sche.h>等,
* 现在还没必要了解得很详细,
* 这里用到的printk的功能类似于printf。

* "/usr/src/linux"是你实际的内核源码目录的一个符号链接,
* 如果没有现在就创建一个,因为下面和以后都会用到。

* 编译它用"gcc -c -I/usr/src/linux/include hello.c",
* 如果正常会生成文件hello.o,

* 加载它用"insmod hello.o",
* 只有在文本终端下才能看到输出。

* 卸载它用"rmmod hello"
*/

/*
* 小技巧: 在用户目录的.bashrc里加上一行:
* alias mkmod=’gcc -c -I/usr/src/linux/include’
* 然后重新登陆Shell,
* 以后就可以用"mkmod hello.c"的方式来编译内核模块了。
*/

/* 开始例行公事 */
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif

#include <linux/config.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
#ifdef CONFIG_SMP
#define __SMP__
#endif
/* 结束例行公事 */

#include <linux/kernel.h> /* printk()在这个文件里 */

static int
init_module
(){
printk("Hello,World!\n");
return 0; /* 如果初始工作失败,就返回非0 */
}

static void
cleanup_module
(){
printk("Bye!\n");
}
————————————

2. "asdf.c"
————————————
/*
* 这个文件是一个内核模块。
* 内核模块的编译,加载和卸载在前面已经介绍了。

* 这个模块的功能是,创建一个字符设备。
* 这个设备是一块4096字节的共享内存。
* 内核分配的主设备号会在加载模块时显示。
*/

/* 开始例行公事 */
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif

#include <linux/config.h>
#include <linux/module.h>

#ifdef CONFIG_SMP
#define __SMP__
#endif
MODULE_LICENSE("GPL");
/* 结束例行公事 */

#include <asm/uaccess.h> /* copy_to_user(), copy_from_user */
#include <linux/fs.h> /* struct file_operations, register_chrdev(), … */
#include <linux/kernel.h> /* printk()在这个文件里 */
#include <linux/sched.h> /* 和任务调度有关 */
#include <linux/types.h> /* u8, u16, u32 … */

/*
* 关于内核功能库,可以去网上搜索详细资料,
*/

/* 文件被操作时的回调功能 */
static int asdf_open (struct inode *inode, struct file *filp);
static int asdf_release (struct inode *inode, struct file *filp);
static ssize_t asdf_read (struct file *filp, char *buf, size_t count,loff_t *f_pos);
static ssize_t asdf_write (struct file *filp, const char *buf, size_t count,loff_t *f_pos);
static loff_t asdf_lseek (struct file * file, loff_t offset, int orig);

/* 申请主设备号时用的结构, 在linux/fs.h里定义 */
struct file_operations asdf_fops = {
open: asdf_open,
release: asdf_release,
read: asdf_read,
write: asdf_write,
llseek: asdf_lseek,
};

static int asdf_major; /* 用来保存申请到的主设备号 */
static u8 asdf_body[4096]="asdf_body\n"; /* 设备 */

static int
init_module
(){
printk ("Hi, This’ A Simple Device File!\n");
asdf_major = register_chrdev (0, "A Simple Device File", &asdf_fops); /* 申请字符设备的主设备号 */
if (asdf_major < 0) return asdf_major; /* 申请失败就直接返回错误编号 */
printk ("The major is:%d\n", asdf_major); /* 显示申请到的主设备号 */
return 0; /* 模块正常初始化 */
}

static void
cleanup_module
(){
unregister_chrdev(asdf_major, "A Simple Device File"); /* 注销以后,设备就不存在了 */
printk("A Simple Device has been removed,Bye!\n");
}

/*
* 编译这个模块然后加载它,
* 如果正常,会显示你的设备的主设备号。
* 现在你的设备就建立好了,我们可以测试一下。
* 假设你的模块申请到的主设备号是254,
* 运行"mknod abc c 254 0",就建立了我们的设备文件abc。
* 可以把它当成一个4096字节的内存块来测试一下,
* 比如"cat abc", "cp abc image", "cp image abc",
* 或写几个应用程序用它来进行通讯。

* 介绍一下两个需要注意的事,
* 一是printk()的显示只有在非图形模式的终端下才能看到,
* 二是加载过的模块最好在不用以后卸载掉。

* 如果对Linux环境的系统调用很陌生,建议先看APUE这本书。
*/

static int
asdf_open /* open回调 */
(
struct inode *inode,
struct file *filp
){
printk("^_^ : open %s\n ",\
current->comm);
/*
* 应用程序的运行环境由内核提供,内核的运行环境由硬件提供。
* 这里的current是一个指向当前进程的指针,
* 现在没必要了解current的细节。
* 在这里,当前进程正打开这个设备,
* 返回0表示打开成功,内核会给它一个文件描述符。
* 这里的comm是当前进程在Shell下的command字符串。
*/
return 0;
}

static int
asdf_release /* close回调 */
(
struct inode *inode,
struct file *filp
){
printk("^_^ : close\n ");
return 0;
}

static ssize_t
asdf_read /* read回调 */
(
struct file *filp,
char *buf,
size_t count,
loff_t *f_pos
){
loff_t pos;
pos = *f_pos; /* 文件的读写位置 */
if ((pos==4096) || (count>4096)) return 0; /* 判断是否已经到设备尾,或写的长度超过设备大小 */
pos += count;
if (pos > 4096) {
count -= (pos – 4096);
pos = 4096;
}
if (copy_to_user(buf, asdf_body+*f_pos, count)) return -EFAULT; /* 把数据写到应用程序空间 */
*f_pos = pos; /* 改变文件的读写位置 */
return count; /* 返回读到的字节数 */
}

static ssize_t
asdf_write /* write回调,和read一一对应 */
(
struct file *filp,
const char *buf,
size_t count,
loff_t *f_pos
){
loff_t pos;
pos = *f_pos;
if ((pos==4096) || (count>4096)) return 0;
pos += count;
if (pos > 4096) {
count -= (pos – 4096);
pos = 4096;
}
if (copy_from_user(asdf_body+*f_pos, buf, count)) return -EFAULT;
*f_pos = pos;
return count;
}

static loff_t
asdf_lseek /* lseek回调 */
(
struct file * file,
loff_t offset,
int orig
){
loff_t pos;
pos = file->f_pos;
switch (orig) {
case 0:
pos = offset;
break;
case 1:
pos += offset;
break;
case 2:
pos = 4096+offset;
break;
default:
return -EINVAL;
}
if ((pos>4096) || (pos<0)) {
printk("^_^ : lseek error %d\n",pos);
return -EINVAL;
}
return file->f_pos = pos;
}
———————————————

摘自:www.linuxeden.com

1、引言

动态库(Dynamic Link Library abbr,DLL)技术是程序设计中经常采用的技术。其目的减少程序的大小,节省空间,提高效率,具有很高的灵活性。

采用动态库技术对于升级软件版本更加容易。与静态库(Static Link Library)不同,动态库里面的函数不是执行程序本身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。

在Windows和Linux操作系统中,都可采用这种方式进行软件设计,但他们的调用方式以及程序编制方式不尽相同。本文首先分析了在这两种操作系统中通常采用的动态库调用方法以及程序编制方式,然后分析比较了这两种方式的不同之处,最后根据实际移植程序经验,介绍了将VC++编制的Windows动态库移植到Linux下的方法。

2、动态库技术

2.1 Windows动态库技术

动态链接库是实现Windows应用程序共享资源、节省内存空间、提高使用效率的一个重要技术手段。常见的动态库包含外部函数和资源,也有一些动态库只包含资源,如Windows字体资源文件,称之为资源动态链接库。通常动态库以.dll,.drv、.fon等作为后缀。

相应的windows静态库通常以.lib结尾,Windows自己就将一些主要的系统功能以动态库模块的形式实现。

Windows动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地址空间分配的内存,成为调用进程的一部分。DLL也只能被该进程的线程所访问。DLL的句柄可以被调用进程使用;调用进程的句柄可以被DLL使用。

DLL模块中包含各种导出函数,用于向外界提供服务。DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL在内存中只有一个实例;DLL实现了代码封装性;DLL的编制与具体的编程语言及编译器无关,可以通过DLL来实现混合语言编程。DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。

根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。

(1)静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码(Windows系统负责对DLL调用次数的计数),调用方式简单,能够满足通常的要求。通常采用的调用方式是把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。

LIB文件包含了每一个DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。Lib文件包含的信息进入到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。

(2)动态调用,即显式调用方式,是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。在Windows系统中,与动态库调用有关的函数包括:

①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。

②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址。

③FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库。

在windows中创建动态库也非常方便和简单。在Visual C++中,可以创建不用MFC而直接用C语言写的DLL程序,也可以创建基于MFC类库的DLL程序。每一个DLL必须有一个入口点,在VC++中,DllMain是一个缺省的入口函数。DllMain负责初始化(Initialization)和结束(Termination)工作。

动态库输出函数也有两种约定,分别是基于调用约定和名字修饰约定。DLL程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调用。通常可以有下面几种方法导出函数:

①采用模块定义文件的EXPORT部分指定要输入的函数或者变量。

②使用MFC提供的修饰符号_declspec(dllexport)。

③以命令行方式,采用/EXPORT命令行输出有关函数。

在windows动态库中,有时需要编写模块定义文件(.DEF),它是用于描述DLL属性的模块语句组成的文本文件。

2.2 Linux共享对象技术

在Linux操作系统中,采用了很多共享对象技术(Shared Object),虽然它和Windows里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so作为后缀,为了方便,在本文中,对该概念不进行专门区分。Linux系统的/lib以及标准图形界面的/usr/X11R6/lib等目录里面,就有许多以so结尾的共享对象。

同样,在Linux下,也有静态函数库这种调用方式,相应的后缀以.a结束。Linux采用该共享对象技术以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活性。Linux还可以通过LD-PRELOAD变量让开发人员可以使用自己的程序库中的模块来替换系统模块。

同Windows系统一样,在Linux中创建和使用动态库是比较容易的事情,在编译函数库源程序时加上-shared选项即可,这样所生成的执行程序就是动态链接库。通常这样的程序以so为后缀,在Linux动态库程序设计过程中,通常流程是编写用户的接口文件,通常是.h文件,编写实际的函数文件,以.c或.cpp为后缀,再编写makefile文件。对于较小的动态库程序可以不用如此,但这样设计使程序更加合理。

编译生成动态连接库后,进而可以在程序中进行调用。在Linux中,可以采用多种调用方式,同Windows的系统目录(..\system32等)一样,可以将动态库文件拷贝到/lib目录或者在/lib目录里面建立符号连接,以便所有用户使用。

下面介绍Linux调用动态库经常使用的函数,但在使用动态库时,源程序必须包含dlfcn.h头文件,该文件定义调用动态链接库的函数的原型。

(1)_打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag); dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。

(2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol); dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。

(3)关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle); dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

(4)动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

在取到函数执行地址后,就可以在动态库的使用程序里面根据动态库提供的函数接口声明调用动态库里面的函数。在编写调用动态库的程序的makefile文件时,需要加入编译选项-rdynamic和-ldl。

除了采用这种方式编写和调用动态库之外,Linux操作系统也提供了一种更为方便的动态库调用方式,也方便了其它程序调用,这种方式与Windows系统的隐式链接类似。其动态库命名方式为“lib*.so.*”。在这个命名方式中,第一个*表示动态链接库的库名,第二个*通常表示该动态库的版本号,也可以没有版本号。

在这种调用方式中,需要维护动态链接库的配置文件/etc/ld.so.conf来让动态链接库为系统所使用,通常将动态链接库所在目录名追加到动态链接库配置文件中。如具有X window窗口系统发行版该文件中都具有/usr/X11R6/lib,它指向X window窗口系统的动态链接库所在目录。

为了使动态链接库能为系统所共享,还需运行动态链接库的管理命令./sbin/ldconfig。在编译所引用的动态库时,可以在gcc采用 –l或-L选项或直接引用所需的动态链接库方式进行编译。在Linux里面,可以采用ldd命令来检查程序依赖共享库。

3、两种系统动态库比较分析

Windows和Linux采用动态链接库技术目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同,下面从以下几个方面进行阐述。

(1)动态库程序编写,在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数作为初始化的人口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。Linux下的gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要到函数做特别声明,编写比较方便。

(2)动态库编译,在windows系统下面,有方便的调试编译环境,通常不用自己去编写makefile文件,但在linux下面,需要自己动手去编写makefile文件,因此,必须掌握一定的makefile编写技巧,另外,通常Linux编译规则相对严格。

(3)动态库调用方面,Windows和Linux对其下编制的动态库都可以采用显式调用或隐式调用,但具体的调用方式也不尽相同。

(4)动态库输出函数查看,在Windows中,有许多工具和软件可以进行查看DLL中所输出的函数,例如命令行方式的dumpbin以及VC++工具中的DEPENDS程序。在Linux系统中通常采用nm来查看输出函数,也可以使用ldd查看程序隐式链接的共享对象文件。

(5)对操作系统的依赖,这两种动态库运行依赖于各自的操作系统,不能跨平台使用。因此,对于实现相同功能的动态库,必须为两种不同的操作系统提供不同的动态库版本。

4、动态库移植方法

如果要编制在两个系统中都能使用的动态链接库,通常会先选择在Windows的VC++提供的调试环境中完成初始的开发,毕竟VC++提供的图形化编辑和调试界面比vi和gcc方便许多。完成测试之后,再进行动态库的程序移植。

通常gcc默认的编译规则比VC++默认的编译规则严格,即使在VC++下面没有任何警告错误的程序在gcc调试中也会出现许多警告错误,可以在gcc中采用-w选项关闭警告错误。

下面给出程序移植需要遵循的规则以及经验。

(1)尽量不要改变原有动态库头文件的顺序。通常在C/C++语言中,头文件的顺序有相当的关系。另外虽然C/C++语言区分大小写,但在包含头文件时,Linux必须与头文件的大小写相同,因为ext2文件系统对文件名是大小写敏感,否则不能正确编译,而在Windows下面,头文件大小写可以正确编译。

(2)不同系统独有的头文件。在Windows系统中,通常会包括windows.h头文件,如果调用底层的通信函数,则会包含winsock..h头文件。因此在移植到Linux系统时,要注释掉这些Windows系统独有的头文件以及一些windows系统的常量定义说明,增加Linux都底层通信的支持的头文件等。

(3)数据类型。VC++具有许多独有的数据类型,如__int16,__int32,TRUE,SOCKET等,gcc编译器不支持它们。通常做法是需要将windows.h和basetypes.h中对这些数据进行定义的语句复制到一个头文件中,再在Linux中包含这个头文件。例如将套接字的类型为SOCKET改为int。

(4)关键字。VC++中具有许多标准C中所没有采用的关键字,如BOOL,BYTE,DWORD,__asm等,通常在为了移植方便,尽量不使用它们,如果实在无法避免可以采用#ifdef 和#endif为LINUX和WINDOWS编写两个版本。

(5)函数原型的修改。通常如果采用标准的C/C++语言编写的动态库,基本上不用再重新编写函数,但对于系统调用函数,由于两种系统的区别,需要改变函数的调用方式等,如在Linux编制的网络通信动态库中,用close()函数代替windows操作系统下的closesocket()函数来关闭套接字。另外在Linux下没有文件句柄,要打开文件可用open和fopen函数,具体这两个函数的用法可参考文献[2]。

(6)makefile的编写。在windows下面通常由VC++编译器来负责调试,但gcc需要自己动手编写makefile文件,也可以参照VC++生成的makefile文件。对于动态库移植,编译动态库时需要加入-shared选项。对于采用数学函数,如幂级数的程序,在调用动态库是,需要加入-lm。

(7)其它一些需要注意的地方

①程序设计结构分析,对于移植它人编写的动态库程序,程序结构分析是必不可少的步骤,通常在动态库程序中,不会包含界面等操作,所以相对容易一些。

②在Linux中,对文件或目录的权限分为拥有者、群组、其它。所以在存取文件时,要注意对文件是读还是写操作,如果是对文件进行写操作,要注意修改文件或目录的权限,否则无法对文件进行写。

③指针的使用,定义一个指针只给它分配四个字节的内存,如果要对指针所指向的变量赋值,必须用malloc函数为它分配内存或不把它定义为指针而定义为变量即可,这点在linux下面比windows编译严格。同样结构不能在函数中传值,如果要在函数中进行结构传值,必须把函数中的结构定义为结构指针。

④路径标识符,在Linux下是“/”,在Windows下是“\”,注意windows和Linux的对动态库搜索路径的不同。

⑤编程和调试技巧方面。对不同的调试环境有不同的调试技巧,在这里不多叙述。

5、结束语

本文系统分析了windows和Linux动态库实现和使用方式,从程序编写、编译、调用以及对操作系统依赖等方面综合分析比较了这两种调用方式的不同之处,根据实际程序移植经验,给出了将VC++编制的Windows动态库移植到Linux下的方法以及需要注意的问题,同时并给出了程序示例片断,实际在程序移植过程中,由于系统的设计等方面,可能移植起来需要注意的方面远比上面复杂,本文通过总结归纳进而为不同操作系统程序移植提供了有意的经验和技巧。
 

2005年10月03日

产品介绍  
  中央处理器
◆ CPU: INTEL公司的Xscale,主频400MHz, 工业级;
外部存储器
◆ 内存:64MByte SDRAM(2片16位的SDRAM芯片组成32位接口);
◆ NOR Flash:32MByte存储器(2片intel E28F128组成32位接口);
◆ NandFlash(与SmartMedia卡复用,可支持16M~128M的NandFlash);

  
  硬件资源  
  中央处理器
◆ CPU: INTEL公司的Xscale,主频400MHz, 工业级;
外部存储器
◆ 内存:64MByte SDRAM(2片16位的SDRAM芯片组成32位接口);
◆ NOR Flash:32MByte存储器(2片intel E28F128组成32位接口);
◆ NandFlash(与SmartMedia卡复用,可支持16M~128M的NandFlash);
串口
◆ 一个标准全双工串口(FFUART);
◆ 一个高速蓝牙串口(BTUART);
网络接口
◆ 10/100M以太网接口(LAN91C111),带联接和传输指示灯;
USB接口
◆ 一个USB HOST接口(USB1.1规范,采用SL811HST)
◆ 一个USB Device接口(USB1.1规范)
红外通讯口
◆ 一个IRDA红外线数据通讯口;
音频接口
◆ 一路音频输出,板子自带驻机体话筒可直接录音,另有一路话筒输入接口可接麦克风;
◆ 采用芯片WM9705,AC97音频CODEC,支持立体声音乐播放、录音和触摸屏;
存储卡接口
◆ 一个SD/MMC卡接口,可支持256M SD/MMC卡;
◆ 一个PCMCIA接口,支持PCMCIA卡和CF卡;
IDE接口
◆ 一个40芯标准IDE接口,可接硬盘或光驱;
LCD和触摸屏接口
◆ 一个44芯LCD接口引出了LCD控制器和触摸屏的全部信号;
◆ 支持黑白、4级灰度、16级灰度、256色、4096色STN液晶屏,尺寸从3.5寸到12.1寸,屏幕分辨率可达到1024×768象素;
◆ 支持黑白、4级灰度、16级灰度、256色、64K色、真彩色TFT液晶屏,尺寸从3.5寸到12.1寸,屏幕分辨率可达到1024×768象素;
◆ 标准配置为夏普256K色240×320/3.5英寸TFT液晶屏,带触摸屏;
RTC时钟
◆ 采用芯片PCF8563T扩展的实时时钟(带有后备锂电池);
调试及下载接口
◆ 一个20芯Multi-ICE标准JTAG接口,支持SDT2.51,ADS1.2等调试 ;
电源接口
◆ CPU单独使用两组高效率开关电源分别为内核和IO供电,稳定可靠;
◆ 底板采用开关电源供电,输入直流电压范围是7~20V(推荐使用12V),带电源开关和指示灯;
其他
◆ 一个EEPROM(AT24C02)用来验证IIC总线读写;
◆ 八个小按键,四个高亮LED;
◆ 一个PWM控制的蜂鸣器(带使能控制的短路块);
◆ 4个由CPU的GPIO控制的LED,一个电源指示LED;
◆ 板上的地址线、数据线全部采用驱动芯片74LVTH162245进行了隔离;
◆ 一个60芯2毫米间距双排标准连接器用作扩展口,引出了地址线、数据线、读写、片选、中断、IO口、5V和3.3V电源、地等用户扩展可能用到的信号;
  
  软件资源  
  1)SldView For ARM集成开发环境
2)启动引导源代码和下载烧写工具JFlashmm.exe
3)Linux for JH-PXA255内核源码包以及内核交叉编译工具,可运行的根文件系统及根文件系统制作工具mkcramfs
4)busybox-1.0源码,qt-embedded-2.3.7和qtopia-free-1.7.0源码,应用程序交叉编译器
5)WINCE4.2.NET板级支持包BSP for PXA255,及已编译好的WINCE镜像文件
6)PXA255及部分板上扩展芯片的资料
7)JH-PXA255底板电路原理图(pdf格式)
8)JH-PXA255开发板使用手册(pdf格式)
  
  操作系统支持  
  ◆ 支持Linux-2.6.8.1操作系统;
驱动程序包含串口、100M网口、PCMCIA接口、SD/MMC卡、NOR Flash、NAND FLASH(或SmartMedia卡)、AC97音频录音放音、LCD、触摸屏、USB HOST、USB DEVICE等多种驱动。
应用程序包括QT,MINIGUI等图形系统;
◆ 支持WINCE4.2.NET

  
  组件配置  
  1)一块已测试好的JH-PXA255II开发板(包括核心板与外设底板)
2)两张JH-PXA255II用户光盘
3)3.5" TFT 彩色LCD板一块 ,带触摸屏
4)一条交叉串口线(两边都是母头)
5)一条直连串口线(两边都是母头)
6)一条网线(交叉网线线)
7)USB线一条
8)触摸笔一支
9)一个+12V/1A直流电源
10)一个包装盒

产品介绍  
  中央处理器
◆ CPU: 三星S3C2410A,主频203MHz;
外部存储器
◆ 内存:64M字节;
◆ NOR Flash:2M字节(SJH-39VF160或SJH-39VF1601);
◆ NAND Flash:64M字节(K9F1208,用户可自己更换为16M、32M或128M的NandFlash)

  
  硬件资源  
  中央处理器
◆ CPU: 三星S3C2410A,主频203MHz;
外部存储器
◆ 内存:64M字节;
◆ NOR Flash:2M字节(SJH-39VF160或SJH-39VF1601);
◆ NAND Flash:64M字节(K9F1208,用户可自己更换为16M、32M或128M的NandFlash)
串口
◆ 两个标准3线串口;
网络接口
◆ 10M网口,CS8900Q3,带联接和传输指示灯;
USB接口
◆ 一个USB HOJH-(USB 1.1规范)接口;
◆ 一个USB Device(USB1.1规范)接口(它与USB HOJH-接口复用,通过短路块选择);
红外通讯口
◆ 一个IRDA红外线数据通讯口;
音频接口
◆ 采用IIS接口芯片CS4334和音频功率放大芯片TDA2822;
◆ 一路带功率放大的双声道立体声音频输出;
◆ 板上还带有一个标准2芯小连接器可以接喇叭;
存储卡接口
◆ 一个SD卡接口,可接256M SD卡;
LCD和触摸屏接口
◆ 板上集成了4线电阻式触摸屏接口的相关电路;
◆ 一个50芯LCD接口引出了LCD控制器的全部信号,并且这些信号引脚都加了74LVTH162245驱动,所以LCD输出更加稳定可靠;
◆ 支持黑白、4级灰度、16级灰度、256色、4096色JH-N液晶屏,尺寸从3.5寸到12.1寸,屏幕分辨率可达到800×600象素;
◆ 支持黑白、4级灰度、16级灰度、256色、64K色、真彩色TFT液晶屏,尺寸从3.5寸到12.1寸,屏幕分辨率可达到800×600象素;
◆ 标准配置为夏普256K色240×320/3.5英寸TFT液晶屏,带触摸屏;
◆ 板上引出一个5V电源输出接口,可为大尺寸TFT液晶屏的5V CCFL背光模块供电;
时钟源
◆ 内部实时时钟(带有后备锂电池);
复位电路
◆ 一个复位按键,并采用专用复位芯片进行复位,稳定可靠;
电源接口
◆ +5V电源供电,带电源开关和指示灯;
调试及下载接口
◆ 一个20芯Multi-ICE标准JTAG接口,支持SDT2.51,ADS1.2等调试 ;
其他
◆ 一个EEPROM(AT24C02)用来验证IIC总线读写;
◆ 四个小按键,四个高亮LED;
◆ 一个带功率驱动的蜂鸣器;
◆ 一个可调电阻接到ADC引脚上用来验证模数转换;
◆ 一个40芯2.54间距双排标准连接器用作扩展口,引出了地址线、数据线、读写、片选、中断、IO口、ADC、5V和3.3V电源、地等用户扩展可能用到的信号;

  
  软件资源  
  ◆ SldView For ARM集成开发环境
◆ 烧写FLASH的工具软件SJF2410(包含NT/2000/XP解决方案)
◆ 串口工具软件sscom32.exe、dnw.exe、tftp.exe;
◆ 64K色(RGB565)图片字模软件;
◆ USB Device接口驱动程序;
◆ JH-2410 BIOS源代码(ADS1.20的项目文件);
◆ JH-2410测试程序(ADS1.20的项目文件,包含全部源代码),具有如下功能测试:
NANDBOOT:demo的功能是从nandFlash程序中引导系统的示例代码;
2410APP:这个demo的功能是USB下载运行、串口下载运行、SD卡读写测试、音频录音放音测试、蜂鸣器测试、按键、触摸屏、TFT液晶屏测试程序等等;
U2410MON:这个demo是从三星网站上的代码移植过来的,它是一个监控程序,供用户参考S3C2410_TEJH—这个demo是从三星网站上的测试代码移植过来的,包含CPU所有功能单元的测试程序,NAND FLASH烧写程序
◆ Linux for S3c2410内核源码包以及编译工具,含CS8900 EHTNENET端口驱动,UART驱动USB HOJH- & DEVICE驱动
◆ WINCE4.2.NET板级支持包BSP for S3c2410
◆ 已经编译好并可在JH-2410上运行的wince内核,基于优龙提供的BSP
◆ Samsung半导体网站关于S3C2410的全部资料和参考代码
◆ JH-2410核心板和底板电路原理图(pdf格式);
◆ JH-2410开发板使用手册(pdf格式)
◆ 开发板上所用到的全部芯片手册、资料

  
  操作系统支持  
  ◆ 支持linux和WINCE4.2.NET
  
  组件配置  
  一块已测试好的JH-2410开发板(包括核心板与外设底板)
两张JH-2410用户光盘
3.5" TFT 彩色LCD板一块 ,带触摸屏.(选配件)
一个SUPER JTAG调试头(带20芯排线)
一条并口线(一边是公头一边是母头,一对一)
一条串口线(两边都是母头,直连串口线)
一条网线(交叉网线)
USB线一条
一个+5V/1A直流电源
一个包装盒

产品介绍  
  JH-44B0XII V3.0是核心板(4层板)+底板(双面板)结构,有助于迅速研发自己的产品!
该板扩展接口丰富,具有USB HOST与USB Device接口、SmartMedia卡、IDE硬盘、10M以太网接口、音频输出接口、PS/2接口、串口,以及可支持触摸屏的LCD接口。
核心板采用四层板,PCB布线极度优化,可以稳定运行到74MHz,mp3解码轻松实现!
  
  硬件资源  
  中央处理器
◆ S3C44B0X (SAMSUNG),ARM7TDMI
外部存储器
◆ 2M BytesNOR FLASH (SST39VF160或SST39VF1601,可支持4M字节的SST39VF320或SST39VF3201);
◆ 8M Bytes SDRAM (K4S641632H或者是HY57V641620,可支持16M字节的SDRAM);
◆ 16M Bytes NAND FLASH (K9F2808,用户可自己更换为32M、64M或128M的NandFlash)
串口
◆ 两个标准三线RS232接口;
网络接口
◆ 10M网口,RTL8019AS,带发送和接收指示灯;
USB Device接口
◆ USB1.1规范,PDIUSBD12,带联接状态指示灯;
USB HOST接口
◆ USB1.1规范,SL811HST,采用了48M有源晶振更加稳定可靠;
LCD接口
◆ LCD接口信号线全部采用了74HC244进行了驱动,更加稳定可靠
◆ 支持单色、4级灰度、16级灰度、256色STN液晶屏,最大支持640×480/256色STN液晶屏
◆ 可选配16级灰度屏G35I、G35II、G57 (带触摸屏)或256色彩屏C57(带触摸屏)
◆ LCD接口旁边留有12V电源输出接口,可为LCD的12VCCFL背光模块供电
IDE接口
◆ 40芯标准连接器,可挂载IDE硬盘;
SmartMedia卡接口
◆ 可支持256M字节的大容量SmartMedia卡;
音频接口
◆ 带音量调节旋钮和功率放大的双声道音频输出(CS4334+TDA7050 );
时钟源
◆ 内部实时时钟(带有后备锂电池);
复位电路
◆ 一个复位按键,并采用专用复位芯片进行复位,稳定可靠;
调试及下载接口
◆ 一个20芯Multi-ICE标准JTAG接口,支持SDT2.51,ADS1.2等调试 ;
电源接口
◆ 开关电源供电,输入直流电压范围是7~20V(推荐使用12V),带电源指示灯;
其他
◆ 四个小按键,四个高亮LED;
◆ 一个蜂鸣器(带使能控制的短路块);
◆ 一个EEPROM(AT24C02)用来验证IIC总线读写;
◆ PS/2接口,信号线接在中断引脚上;
◆ 一个精密可调电阻接到ADC引脚上用来验证模数转换;
◆ 未使用的ADC引脚通过一个10芯标准连接器引出留给用户自己扩展;

  
  软件资源  
  ◆ SldView For ARM集成开发环境
◆ 烧写FLASH的工具软件FLASHPGM2.2.4(评估版)以及适用于S3C44B0X的OCD配置文件;
◆ 串口工具软件sscom32.exe、dnw.exe、tftp.exe;
◆ LCD图片转换和字模转换工具软件UC-GUI-BITMAPCONVERT.EXE;
◆ 经典的通过JTAG烧写flash工具Fluted(包含NT/XP解决方案)
◆ JH-44B0XII BIOS源代码(ADS1.20的项目文件,包含RTL8019驱动和TFTP协议源码);
◆ JH-44B0XII测试程序(ADS1.20的项目文件,包含全部源代码),具有如下功能测试:
内存(SDRAM)读写自测试
PWM输出蜂鸣器测试
IIC总线EEPROM读写测试
模数转换ADC测试
IIS音频播放测试
USB从设备PDIUSBD12测试
USB主设备SL811HST测试
黑白STN液晶屏测试
4级灰度STN液晶屏测试
16级灰度STN液晶屏测试
256色STC液晶屏测试
黑白STN屏字符串显示测试
外部中断测试
IDE硬盘测试
SmartMedia卡测试
◆ 三星提供的S3C44B0X标准测试程序,经修改后可以运行在JH-44B0XII开发板上面:
◆ uC/OS-II V2.76测试(ADS1.20的项目文件,五个任务的演示DEMO,提供全部源码)
◆ ucLinux内核源码包和编译器等(可演示板子运行uclinux,不免费提供技术支持);
◆ 使用SUPERJTAG进行软件和硬件仿真DEBUG的演示动画;
◆ 使用FLASHPGM烧写FLASH的演示动画;
◆ 使用ADS1.20创建项目并进行相关设置的演示动画;
◆ JH-44B0XII核心板和底板电路原理图(pdf格式);
◆ JH-44B0XII开发板使用手册(pdf格式)
◆ 开发板上所用到的全部芯片手册、资料
  
  操作系统支持  
  ◆ 支持uC/OS-II ,ucLinux
  
  组件配置  
  1)一块已测试好的JH-44B0XII开发板
2)一张JH-44B0XII光盘
3)一个SUPER JTAG调试头
4)一条并口线(一边是公头一边是母头,一对一)
5)一条串口线(两边都是母头,直连串口线)
6)一条网线(交叉网线线)
7)一个+9V或+12V直流电源
8)一个包装盒

产品介绍  
  JH-44B0XI资源完全向用户开放,性能稳定,demo软件丰富。
所有的软件都含源代码。IDE硬盘接口中加入总线缓冲,大大的增强了硬盘的读写速度。
音频输出加入功放,可调节音量变阻器,设计更合理。
JH-44B0XI 配G35II,G57T,C57T LCD使用。
  
  硬件资源  
  中央处理器
◆ S3C44B0X (SAMSUNG),ARM7TDMI
外部存储器
◆ 2M BytesNOR FLASH (SST39VF160或SST39VF1601,可支持4M字节的SST39VF320或SST39VF3201);
◆ 8M Bytes SDRAM (K4S641632H或者是HY57V641620,可支持16M字节的SDRAM);
◆ 16M Bytes NAND FLASH (K9F2808,用户可自己更换为32M、64M或128M的NandFlash)
串口
◆ 两个标准三线RS232接口,其中COM1带发送和接收指示灯;
网络接口
◆ 10M网口,RTL8019AS,带发送和接收指示灯;
USB Device接口
◆ USB1.1规范,PDIUSBD12,带联接状态指示灯;
LCD接口
◆ LCD接口信号线全部采用了74HC244进行了驱动,更加稳定可靠
◆ 支持单色、4级灰度、16级灰度、256色STN液晶屏,最大支持640×480/256色STN液晶屏
◆ 可选配16级灰度屏G35I、G35II、G57 (带触摸屏)或256色彩屏C57(带触摸屏)
◆ LCD接口旁边留有12V电源输出接口,可为LCD的12VCCFL背光模块供电
IDE接口
◆ 总线上采用驱动芯片74LVTH162245进行了隔离,具有更好的稳定性;
◆ 板上留有IDE硬盘的电源接口,如果板子电源采用12V,就可以直接使用该接口给IDE硬盘供电;
音频接口
◆ 带音量调节旋钮和功率放大的双声道音频输出(CS4334+TDA2822 )
时钟源
◆ 内部实时时钟(带有后备锂电池);
复位电路
◆ 一个复位按键,并采用专用复位芯片进行复位,稳定可靠;
调试及下载接口
◆ 一个20芯Multi-ICE标准JTAG接口,支持SDT2.51,ADS1.2等调试 ;
电源接口
◆ 开关电源供电,输入直流电压范围是7~20V(推荐使用12V),带电源指示灯;
其他
◆ 四个小按键,四个高亮LED;
◆ 一个蜂鸣器(带使能控制的短路块);
◆ 一个EEPROM(AT24C02)用来验证IIC总线读写
  
  软件资源  
  ◆ ADS1.20安装程序(评估版);
◆ 使用SUPERJTAG并支持ADS1.20和SDT2.51的JTAG调试软件ARMJTAGDEBUGFINAL;
◆ 烧写FLASH的工具软件FLASHPGM2.2.4(评估版)以及适用于S3C44B0X的OCD配置文件;
◆ 串口工具软件sscom32.exe、dnw.exe、tftp.exe;
◆ LCD图片转换和字模转换工具软件UC-GUI-BITMAPCONVERT.EXE;
◆ 经典的通过JTAG烧写flash工具Fluted(包含NT/XP解决方案)
◆ JH-44B0XI BIOS源代码(ADS1.20的项目文件,包含RTL8019驱动和TFTP协议源码);
◆ JH-44B0XI测试程序(ADS1.20的项目文件,包含全部源代码),具有如下功能测试:
内存(SDRAM)读写自测试
PWM输出蜂鸣器测试
IIC总线EEPROM读写测试
模数转换ADC测试
IIS音频播放测试
USB从设备PDIUSBD12测试
黑白STN液晶屏测试
4级灰度STN液晶屏测试
16级灰度STN液晶屏测试
256色STC液晶屏测试
黑白STN屏字符串显示测试
外部中断测试
IDE硬盘测试
◆ 三星提供的S3C44B0X标准测试程序,经修改后可 支持uC/OS-II ,ucLinux以运行在JH-44B0XI开发板上面:
◆ 支持uC/OS-II ,ucLinux uC/OS-II V2.76测试(ADS1.20的项目文件,五个任务的演示DEMO,提供全部源码)
◆ 支持uC/OS-II ,ucLinux ucLinux内核源码包和编译器等(可演示板子运行uclinux,不免费提供技术支持);
◆ 使用SUPERJTAG进行软件和硬件仿真DEBUG的演示动画;
◆ 使用FLASHPGM烧写FLASH的演示动画;
◆ 使用ADS1.20创建项目并进行相关设置的演示动画;
◆ JH-44B0XI电路原理图(pdf格式);
◆ JH-44B0XI开发板使用手册(pdf格式)
◆ 开发板上所用到的全部芯片手册、资料
  
  操作系统支持  
  ◆ 支持uC/OS-II ,ucLinux
  
  组件配置  
  1)一块已测试好的JH-44B0XI开发板
2)一张JH-44B0XI光盘
3)一个SUPER JTAG调试头
4)一条并口线(一边是公头一边是母头,一对一)
5)一条串口线(两边都是母头,交叉串口线)
6)一条网线(交叉网线线)
7)一个+9V或+12V直流电源
8)一个包装盒