printk打印级别 打印的信息可以显示在远程终端上吗

自定义内核只需将以下内核选项打开即可(编译为模块).

tgt-macaddr 目的MAC地址,一般为当前设备网关; 统一个网关内可直接指定目的ip的MAC

下面为一个自动化脚本, 自动获取当前默认路由网卡ip及网关ip&MAC地址加载netconsole模块脚本,只需指定syslogd服务器目的地址即可.

中以下选项开启UDP 514端口:

在没有syslogd在运行的主机上可以 netcat/socat 接收来自远程主机的消息:

}

               第十八章    调试

1、在用户级的程序里,bug表现比较直接;在内核中却不清晰。

2、内核级开发的调试工作远比用户级开发艰难的多。

3、准备工作需要的是:

  (2)一个藏匿bug的内核版本

  (3)相关内核代码的知识和运气

1、内核中的bug多种多样。

2、引用空指针会产生一个oops;垃圾数据会导致系统崩溃。

3、定时限制和竞争条件都允许多个线程在内核中同时运行产生的结果。

18.3 通过打印来调试

1、健壮性——在任何时候,任何地方都能调用它。

2、内核中的printk()比比皆是:

  (1)在中断上下文和进程上下文中被调用

  (2)在任何持有锁时被调用

  (3)在多处理器上同时被调用,并且不必使用锁。

3、除非在启动程序的初期就要在终端上输出,否则可以认为printk()在什么情况下都能工作。

1、printk()和printf()在使用上最主要的区别就是前者可以指定一个日志级别,内核根据这个级别来判断是否在终端上打印消息。内核把级别比某个特定值低的所有消息显示在终端上。

5、有两种赋予记录等级的方法:

  (1)保持终端的默认记录等级不变,给所有调试信息KERN_CRIT或更低的等级。

  (2)给所有调试信息KERN_DEBUG等级,调整终端的默认记录等级。

1、内核消息都被保存在一个LOG_BUF_LEN大小的环形队列中。在单处理器的系统上其默认值是16KB。

2、优点:在中断上下文中也可以方便的使用。

      使记录维护起来更容易。

1、用户空间的守护进程klogd从记录缓冲区中获取内核消息,再通过syslogd守护进程将它们保存在系统日志文件中。

2、Klogd程序既可以从/proc/kmsg文件中,也可以通过syslog()系统调用读取这些消息。默认是/proc方式。两种情况klogd都会阻塞,直到有新的内核消息可供读出,唤醒之后默认处理是将消息传给syslogd守护进程。可以通过-c标志来改变终端的记录等级

3、syslogd守护进程把它接收到的所有消息添加进一个文件中,该文件默认是/var/log/messages。也可以通过/etc/syslog.conf配置文件重新指定。

1、反复出现的错误很快就会让你开始培养新的习惯。

1、oops是内核告知用户有不幸发生的最常用的方式。

2、内核很难自我修复,也不能将自己杀死,只能发布oops,过程包括:

  (1)向终端上输出错误消息

  (2)输出寄存器中保存的信息

  (3)输出可供跟踪的回溯线索

3、通常发送完oops之后,内核会处于一种不稳定状态。

  (1)在中断上下文时发生:内核无法继续,会陷入混乱,导致系统死机

  (2)在idle进程(pid为0)或init进程(pid为1)时发生,结果同样是系统陷入混乱。

  (3)在其他进程运行时发生,内核会杀死该进程并尝试着继续执行。

5、oops的产生有很多可能原因:内存访问越界、非法的指令等。

6、oops中包含的重要信息:寄存器上下文和回溯线索

  (1)回溯线索:显示了导致错误发生的函数调用链。

  (2)寄存器上下文信息也很有用,比如帮助冲进引发问题的现场

1、回溯线索中的地址需要转化成有意义的符号名称才方便使用,这需要调用ksymoops命令,并且还需要提供编译内核时产生的System.map。如果用的是模块,还需要一些模块信息。一般可以这样调用它:ksymoops saved_oops.txt。

18.5 内核调试配置选项

1、在内核配置编辑器的内核开发菜单项中,依赖CONFIG_DEBUG_KERNEL。

2、使用锁时睡眠是引发死锁的元凶。

2、被调用时会引发oops,导致栈的回溯和错误信息的打印。可以把这些调用当做断言使用,想要断言某种情况不该发生:

3、调用panic()不但会打印错误信息,而且还会挂起整个系统。

4、dump_stack()只在终端上打印寄存器上下文和函数的跟踪线索。

18.7 神奇的系统请求键

1、这个功能可以通过定义CONFIG_MAGIC_SYSRQ配置选项来启用。SysRq(系统请求)键在大多数键盘上都是标准键。

2、该功能被启用时,无论内核出于什么状态,都可以通过特殊的组合键和内核进行通信。

4、Sysrq的几个命令:

5、在一行内发送这三个键的组合可以重新启动濒临死亡的系统,这比直接按下机器的Reset键要安全一些。

18.8 内核调试器的传奇

1、可以使用标准的GNU调试器对正在运行的内核进行查看。针对内核启动调试器的方法与针对进程的方法大致相同:gdb vmlinux /proc/kcore

2、vmlinx文件是未经压缩的内核映像,不是压缩过的zImage或bImage,它存放于源代码树的根目录上。

3、/proc/kcore作为一个参数选项,是作为core文件来用的,通过它能够访问到内核驻留的高端内存。只有超级用户才能读取此文件的数据

4、可以使用gdb的所有命令来获取信息。例如:打印一个变量的值:p global_variable

                      反汇编一个函数:disassemble function

                      -g参数还可以提供更多的信息。

  (1)没有办法修改内核数据

  (2)不能单步执行内核代码,不能加断点。

1、是一个补丁 ,可以让我们在远程主机上通过串口利用gdb的所有功能对内核进行调试。

2、需要两台计算机:仪态运行带有kgdb补丁的内核,第二胎通过串行线使用gdb对第一台进行调试。

3、通过kgdb,gdb的所有功能都能使用:读取和修改变量值、设置断点、设置关注变量、单步执行等。

一、用UID作为选择条件

1、一般情况下,加入特性时,只要保留原有的算法而把新算法加入到其他位置上,基本就能保证安全。

2、可以把用户id(UID)作为选择条件来实现这种功能:

通过某种选择条件,安排到底执行哪种算法。

即,除了uid=7777的用户以外,其他所有的用户都是用的老算法,所以这个7777用户可以专门用来测试新算法。

1、如果代码与进程无关,或者希望有一个针对所有情况都能使用的机制来控制某个特性,可以使用条件变量。

2、这种方式比使用UID更简单,只需要创建一个全局变量作为一个条件选择开关。如果该变量为0,就使用某一个分支上的代码;否则,选择另外一个分支。

3、操控方式:某种接口,或者调试器。

1、需要掌握某个特定事件的发生规律,需要比较多个事件并从中得出规律通过创建统计量并提供某种机制访问其统计结果。

2、定义两个全局变量:

  每当事件发生的时候,就让相应的变量加1.然后在觉得合适的地方输出它。可以在/proc目录中创建一个文件,还可以新建一个系统调用。最简单的办法还是通过调试器直接访问它们。

3、注意,这种实现并非是SMP安全的,更好的方法是通过原子操作进行实现。

1、当系统的调试信息过多的时候,有两种方式可以防止这类问题发生:

  (1)重复频率限制

  (2)发生次数限制

2、为了避免调试信息发生井喷,可以每隔几秒执行一次操作。

18.10 用二分法找出引发罪恶的变更

1、知道bug是什么时候引入内核源代码的通常都是很有用的。

1、具体哪次提交的代码引发了bug,可以使用Git进行二分搜索。

  接下来,git就会利用二分搜索法在Linux源码树中,自动检测正常的版本内核和有bug的内核版本之间那个版本有隐患,然后再编译、运行以及测试正被检测的版本。

2、对于每一个命令,Git将在每一个版本的基础上反复二分搜索源码树,并且返回所查的下一个内核版本,一直到不能再进行二分搜索位置,最终git会打印出有问题的版本号。

18.12 当所有努力都失败时:社区

1、应该向内核邮件列表发送一份电子邮件,对bug进行完整而又简洁的描述。

2、社区和它最重要的论坛——Linux内核邮件列表(LKML)。

  本章讨论了内核的调试——调试过程其实是一种寻求实现与目标偏差的行为。其中考察了几种技术:从内核内置的调试架构到程序调试,从记录日志到用git二分法查找。

  本章的内容对于试图在内核代码中牛刀小试的任何人都至关重要。

}

宽带上网已经不是什么新鲜事 情,人们对相关的网络器件已经不再陌生,比如说常见的路由器。对于一般的网络用户,他们能知道怎样使用路由器来上网、玩游戏等就已经感到很满足了,通常情 况下对路由器的深层技术很少去过问研究,但做为兴趣广泛的技术爱好者,对这方面的知识是非常感兴趣的。但限于各种条件的制约,这些爱好者都非开发者,很大 程度上无法深入了解真正的技术实现过程以及相关的核心内幕。正是基于此点,笔者凭借自身的知识沉淀,尽最大努力为爱好技术的读者架设一坐能通向深层核心的 桥梁,为大家揭开路由器的神秘面纱,剖开其核心内脏。为使读者能清晰明白的理解掌握,笔者尽量将专业的技术内容转化为容易接受的知识讲解,其中可能有不足 偏颇之处,还请大家多见谅。

互联网是依靠路由器连接起来的,路由器是互联网或者说IP网络的核心设备。宽带接入的不断增长,带动了路由器的需求不断增加。

路由器究竟是什么样的技术产物?

谈到路由器的开发,我们就不免要谈到“嵌入式”设备的开发,没错,通俗的说,路由器就是一种嵌入式产品。那么究竟什么是嵌入式设备呢?

   其实就目前而言,嵌入式设备已经不断深入我们的日常生活方方面面。通俗的讲,嵌入式设备是指具有计算机功能,但又不称为计算机的设备或器材,它几乎包括 了我们周围的所有电器设备 PDA、手机、机顶盒、汽车、微波炉、电梯、安全系统、自动售货机、医疗仪器、立体音响、自动取款机等。

   用较为专业的话来表述的话,嵌入式设备就是使用微处理器或微控制器芯片(MCU)加上外围电路再加上内部的程序部分来实现特定功能的嵌入设备。比如8位的 单片机、32的ARM以及DSP芯片等都属于嵌入式核心芯片的范畴。8位MCU市场已逐步趋向稳定,32位MPU代表着嵌入式技术的发展方向,正在加速发 展。在32位嵌入式微处理器市场上,基于ARM内核的微处理器在市场上处于绝对的领导地位,因此追踪ARM技术的发展趋势显得尤为重要。

   路由器的开发通常都是基于32位处理器的,就通常的中低端路由器而言,在开发的配置上有多种选择,比如有ARM9核心芯片+Wince操作系统、 ARM7核心芯片+uClinux操作系统、DSP芯片+Vxworks操作系统等等各种各样的选择。本文针对常用的SOHO路由器来介绍,选择ARM7 核心芯片+uClinux操作系统开发模式,以完整形象的实例为大家清晰讲解路由器的技术实现过程。

  我们为什么以SOHO路由器为介绍对象呢?什么是SOHO路由器?前很多家庭中有不止一台

电脑, 需要上网获取信息、收发邮件等。这些小型公司和家庭网络用户计算机的数目一般不多,网络结构不复杂。功能和带宽的要求不高。出于提高网络性能、共享有限 IP地址或节省上网费用等原因,这些用户迫切需要具有较高性价比的小型路由器。我们把这种小型路由器称为SOHO路由器。目前市场上已经充斥了大量的这类 低端路由器.由于ARM7系列芯片价格便宜,非常适合嵌入式系统使用。目前市场上的SOHO路由器大多采用ARM7系列处理器。不过由于技术的发 展,ARM9系列的专用路由芯片的路由器也逐渐普及。

第2章:路由器宏观介绍 


我 们可以形象的把嵌入式设备的开发简单的理解成三层模式,最底层的是微控制器芯片加外围器件组成的硬件系统,比如我们介绍的开发小型SOHO路由器所使用的 ARM7TDMI芯片等硬件环境,它是设备功能实现的硬件基础,要实现上层的应用肯定离不开最底层硬件的支持。中间层是操作系统,比如我们所选择的 uClinux操作系统,它是衔接硬件部分和应用程序的过渡层,它既可以完成对底层硬件的基本操作,又能为上层应用程序提供运行环境支持。最上层自然就是 应用程序层了,它是实现针对性应用的程序代码部分,比如路由设置等功能程序部分。

  那对与SOHO路由器来说,它当然也脱离不了这样的技术框架,它的更为具体的实现过程简单的汇总的话,莫过于如下内容:

  首先先要知道SOHO实现的网络功能,典型路由器应该具备以下功能:


  DHCP动态主机配置协议; 
  支持一定数量的特殊应用程序;
  然后针对于上边的功能要求,相应地要通过硬件和软件的构造来实现:

  1、要明确家用小型路由器(一个WAN接口,四个LAN接口)的硬件原理。

  2、实现硬件电路板设计,完成电路布线设计,并对元件焊接,通过硬件板的调试。

  1、在分析 uClinux内核源代码的基础上,对uClinux操作系统的内核裁剪。

  2、完成BoaWeb服务器的配置,并对CGI脚本进行设计,完成动态网页的功能。

  3、对PPPOE的拨号进行配置实现。

  4、针对Linux内核防火墙部分,运用IPtable工具进行防火墙规则操作。

  通过如上的基本构造,一个路由器就基本成型了。说起来简单,但其中包含了很多很多的技术细节,要有大量的实践经验才能真正实现。做为门外观奇的好学读者,现在肯定有些不耐烦了吧,想要了解更多的更详细的构造内容吧?那好,现在就可以开始我们真正的技术之旅了。

第3章:路由器工作原理 

要 实 现 网 络中通信节点彼此之间的通信,首先必须给每个节点分配一个唯一的IP地址。路由器应该至少有两个网络端口,分别连接LAN或者WAN子网上,每个端口必须 具有一个唯一的IP地址,并且要求与所连接IP子网的网络号相同。不同的端口有不同的网络号,对应不同的IP子网,这样各子网中的主机才能通过自己子网的 IP地址把要求发出去的IP数据报送到路由器上。

  当路由器收到一份IP数据报后,首先要对该报文进行判断,然后根据判断的结果做进一 步的处理。如果数据报是有效或正确的,路由器就根据数据报的目的IP地址转发该报文:否则就把报文丢弃。如果这个数据报的目的IP地址与路由器直接相连的 一个子网上,路由器会通过相应的接口把报文转发到目的子网上去;否则会把它转发到下一跳(Hop)路由器。为了完成上述的操作,每台路由器必须维护一个路 由表。把对应不同目的地的最佳路径存放在路由表中,这就是路由策略(Routing Policy)问题。路由表反映网络的拓扑结构,一般一条表项应该包含数据报的目的IP地址(通常是目的主机所在网络的地址)、下一跳路由器的地址和相应 的网络接口等,在网络拓扑发生变化的时候,路由表也应该做相应的变动。所以路由器必须能够生成并更新路由表。

  选路机制实际上就是如何查找路由表,通过查询路由表来决定向哪个方向转发数据。一般来说,路由器首先搜索匹配的主机地址:如果没有,再搜索匹配的网络地址:最后搜索默认路由。一旦查到匹配的表项,路由器就会把数据从相应的接口发送出去。

  路由器具备了上述各要素后,就可以完成数据转发任务了。另外,路由器不仅负责对IP包的转发,还要负责与别的路由器进行联络,共同确定互联网的路由选择和路由表的更新维护。

2、SOHO路由器原理


当 内部计算机要与外部Internet网络进行通信时,各内部间通过私有IP地址进行通信的计算机必须把私有IP地址转换成合法IP。这种网络地址转换技术 称为NAT(Network Address Translation,网络地址转换)。在一个实际的私有网络中,NAT功能通常内建在路由器、防火墙或独立的NAT设备之上,网络中的主机将这些设备 作为自己的默认网关。通过这样的配置,每一台内部主机发送往Internet的数据报就会送到具有NAT功能的设备中进行转换。NAT是SOHO路由器的 必备功能,它是为解决IPv4地址不够分配的矛盾而产生的一个简单高效的解决方案。它能将任何两个地址域的地址进行转换,使私有网络中多台主机共享一个合 法IP地址访问Internet。

第4章:嵌入式路由器硬件系统介绍 

硬件结构是非常重要的部分,因为我们拆开一个路由器后首先看到的、所能看到的也就是硬件结构,我们就举例简单介绍一下硬件设计的各个部位的细节内容。


为了宏观查看,我们给出交换式宽带路由器的硬件设计实例图一张。图中主要分为两部分:

  ARM4510B部分和交换芯片RTL8305部分,前者主要见上半图,后者为下半图。还有电源及各自的复位电路。

  组成,作为嵌入式操作系统内核及应该程序运行的

内存空 间。Flash存储器由一片1MX16位的SS139VF160组成,作为内核映像的存储,并在嵌入式操作系统启动时加载系统内核及程序。根据调试程序及 烧写Flash存储器的需要,引出JTAG接口。根据显示调试和运行信息的需要,提供了RS232接口。交换芯片 RTL8305部分中,提供4个LAN口(PORTO--PORT3)通过一四口的网络隔离变压器连接一个四口RJ45口,每个口可连接到 10/10013aseT以太网,各端口之间有交换功能:还有一个WAN接口(CPO RT4)通过一单口的隔离变压器连接RJ45口。根据显示连接速度、状态和电源等需要,接出LED灯进行显示。根据交换芯片的管理需要,提供一串行 EEPROM 24C01电路接口。根据交换芯片的主电源为2.5V.提供一个3.3V到2.5V的转换器。

  中央处理芯片通过MR(独立媒体接口)接口与交换芯片RTL8035SB的PORT4的Mil接口相联,将交换芯片的PORT4配置为物理层接收器。

  当各部分电路设计完成后,形成硬件连接图,进而焊接之后,就可以作为开发用的实验硬件板了。下面就简要介绍一下个硬件电路部分。

2、硬件系统的简要设计介绍

 ⑴ARM处理器系统设计介绍

S3C4510B结构框图所示。在实际运行过程中最主要用到的部分为:以太网接口及串口部分,前者用于收发以太包,后者主要作为操作系统调试接口。

  ②ARM 处理器系统电源电路和复位电路

  主要是实现供电和复位功能,电路部分不做详细讲解,有深入研究需要的爱好者可以查看相关的电子相关参考资料进行深入学习。为使文章通俗易懂,以下各电路部分也是做一宏观介绍,细节部分包括电路布线等不再深入讲解。

  ③ARM处理器与Flash存储器接口电路

  读者只要知道这部分的电路连接是为实现能在Flash存储器编写程序即可。

  ④ARM处理器与SDRAM接口电路设计介绍

   与 Flash存储器相比,SDRAM不具有掉电保持数据的特性,但其存储速度大大高于Flash存储器,且具有读/写属性。因此SDRAM在系统中主要用于 程序的运于空间、数据及堆栈。当系统启动时,CPU首先从复位地址0x0片读取启动代码,在完成系统的初始化后,程序代码调入SDRAM中运行,以提高系 统的运行速度。

  SDRAM 具有单位空间存储量大和价格便宜的特点,广泛用于各种嵌入式系统中。SDRAM 的存储单元可以理解为一个电容,总是倾向于放电,为了避免数据丢失,必须定时刷新(充电)。因此,在系统中使用SDRAM,就要求微处理器有刷新的控制逻 辑或者在系统中另外加刷新控制逻辑电路。S3C4510B在片内具有独立的SDRAM刷新控制逻辑,可以方便的与SDRAM接口。

  ⑤ARM处理器串行接口电路设计介绍

   几乎所有的微控件器、PC都提供串行接口,使用美国电子工业协会(EIA)推荐的RS-232-C接口标准,这是一个很常用的串行数据传输总线接口标 准。早期被用于计算机和终端通过电话线和MODEM进行远距离的数据传输,随着微型计算机和微控制器的发展,不仅在远距离,近距离也采用了该通信方式。在 近距离的通信中不采用电话线和MODEM,而是直接进行端到端的连接。

  RS-232-C标准采用的是9芯或是25芯的D型插头。

  ⑥ARM处理器JTAG接口电路设计介绍

   JTAG(JointTe stAc tionG roup,联合测试行动小组)是一种国际标准测试协议,主要用于芯片内部测试及系统进行仿真、调试。JTAG是一种嵌入式调试技术,它在芯片内部封装了 TAP(Test Access Port,测试访问接口),通过专用的JTAG测试工具对内部节点进行测试.标准的JTAG接口是四线:TMS、TCK、TDI、TDO,分别为测试模式 选择、测试时钟、测试数据输入、测试数据输出。JTAG测试允许多个器件通过JTAG接口串联在一起,形成一个JTAG链,能实现以各个器件分别测试。 JTAG接口还常用于ISP(In System Programmable)功能,如对Flash器件进行编程。

  ⑵以太网交换电路设计介绍

  以太网交换电路主要是采用五口交换芯片RTL8305SB来实现。RTL8305SB是一个集成了片内存储器,五个MAC层接口,五个物理层(PHY)接口的l0M/l00M自适应的五口交换芯片,该集成芯片具有低功耗,可灵活配置为五口小型办公及家用(SOHO)

交换机,家用网关,xDSL路由器及其它智能应用。要实现必要的网络功能,这部分的电路是关键中的关键。

第5章:操作系统介绍 

  Linux是一个诞生于网络,成长于网络且成熟于网络的奇特的操作系统。1991年,芬兰大学生Linus Torvalds萌发开发了一个自由的UNIX操作系统的想法,并将Linux通过Internet进行发布。从此一大批编程人员加入到开发过程中 来,Linux逐渐成长起来。Linux一开始要求所有的源代码必须公开,后来转向GPL( GNUG eneral Public Licence),成为GUN的阵营的主要一员。只要遵守GPL的规定,就可以免费获得复制,因此Linux是一个免费软件。同样,Linux下遵循 GPL规定的C, C++, Java等一系列的工具开发包,从功能的角度上看并不亚于商用的开发包,但却可以极大的降低开发成本,这一优势是其它商用操作系统无法比拟的。

   Linux 操作系统最突出的是网络部分,基本上所有的网络协议和网络接口都可以在Linux上找到,Linux的内核比标准的UNIX处理网络协议更加高效,系统的 网络吞吐性能更好,这也是Linux网络服务器市场上占据较大的市场分额的重要原因。对于一般的小型的SOHO路由器,Linux的网络技术无疑是其开发 运行的最佳选择,Linux完全能对给其提供全方位的网络技术支持。Linux作为互联网的产物,许多关于Linux的文档可以在Internet上下载 到。

不支持MMU,多任务的实现就需要技巧了。但是,在uClinux上运行的绝大多数的用户程序并不需要多任务。另外,针对uclinux内核的二进制代码 和源代码都是经过了重新编写,以紧缩和裁剪基本的代码。这就使得uClinux的内核同标准的Linux内核相比非常之小,但是它仍保持了Linux操作 系统的主要的优点,如稳定性、强大的网络功能和出色的文件系统支持等。uclinux包含Linux常用的API、小于512K的内核和相关的工具。操作 系统所有的代码加起来小于900KB。

在 PC机上开发应用程序的用户都会有这样的感觉,PC机有完善的操作系统并提供应用程序接口(API),开发好的应用程序可以直接在操作系统上运行。虽然嵌 入式系统的应用程序完全可以在裸板上运行,但为了使系统具有任务管理、定时器管理、存储器管理、资源管理、事件管理、系统管理、消息管理、队列管理和中断 处理的能力,提供多任务处理,更好的分配系统资源的功能,用户就需要针对自己的硬件平台和实际应用选择适当的嵌入式操作系统(Embedded Operating System,以下简称EOS)。由于本文实例中的硬件平台是以不含MMU (Memory Management Unit,内存管理单)的S3C4510B为核心的,因此采用不带MMU的ARM 微处理器的嵌入式操作系统uclinux。uclinux 是一个完全符合GNUIGPL公约的操作系统,完全开放代码,现在由Line。公司支持维护。uClinux从Linux 2.0(2.4内核派生而来,沿袭了主流Linux的绝大部分特性。它是专门针对没有MMU的CPU,并且为嵌入式系统做了许多小型化的工作.适用于没有 虚拟内存或内存管理单元(MMU )的处理器,例如ARM7TDMI。它通常用于具有很少内存或Flash的嵌入式系统。uclinux是为了支持没有MMU的处理器而对标准Linux作 出的修正。它保留了操作系统的所有特性,为硬件平台更好的运行各种程序提供了保证。在GNU通用公共许可证(GNU GPL)的保证下,运行uClinux操作系统的用户可以使用几乎所有的Linux API函数,不会因为没有MMU而受到影响。由于uClinux在标准的Linux基础上进行了适当的裁剪和优化,形成了一个高度优化的、代码紧凑的嵌入 式Linux,虽然它的体积很小,uClinux仍然保留了Linux的大多数的优点:稳定、良好的裁剪性、优秀的网络功能、完备的对各种文件系统的支 持、以及标准丰富的API等。

  BootLoader:负责uCLinux内核的启动,它用于初始化系统资源,包括SDRAM。这部分代码用于建立uCLinux内核运行环境和从Flash中装载初始化内核镜象。

  内核初始化:uCLinux内核的入口点是start kernel() 函数。它初始化内核的其他部分,包括捕获,IRQ通道,调度,设备驱动,标定延迟循环,最重要的是能够fork "init"进程,以启动整个多任务环境。

  系统调用函数/捕获函数:在执行完“init”程序后,内核对程序流不再有直接的控制权,此后,它的作用仅仅是处理异步事件(例如硬件中断)和为系统调用提供进程。

  设备驱动 :设备驱动占据了uCLinux内核很大部分。同其他操作系统一样,设备驱动为它们所控制的硬件设备和操作系统提供接口。

   文件系统 :uCLinux最重要的特性之一就是对多种文件系统的支持。这种特性使得uCLinux很容易地同其他操作系统共存。文件系统的概念使得用户能够查看存 储设备上的文件和路径而无须考虑实际物理设备的文件系统类型。ucLinux透明的支持许多不同的文件系统,将各种安装的文件和文件系统以一个完整的虚拟 文件系统的形式呈现给用户。uClinux带有一个完整的TCP/IP协议,同时它还支持许多其他网络协议。uclinux对于嵌入式系统来说是一个网络 完备的操作系统。

  GNU软件包括C编译器GCC,C ++编译器G++,汇编器AS,链接器LD,二进制转换工具(OBJCOPY,OBJDUMP),调试工具(GDB.GD BSERVER,KGDB)和基于不同硬件平台的开发库。在GNU GCC支持下用户可以使用流行的C/C++语言开发应用程序,满足生成高效率运行代码、易掌握的编程语言的用户需求,这些工具都是按GPL版权声明发布, 任何人可以从网上获取全部的源代码,无需任何费用。关于GNU和公共许可证协议的详细资料,读者可以参看GNU网站的介绍,

[url]http://www[/url],gnu.oTgfhDmc.html。 GNU开发套件作为通用的Linux开放套件,包括一系列的开发调试工具。GNU开发工具都是采用命令行的方式,用户掌握起来相对比较困难,不如基于 Windows系统的开发工具好用,但是GNU工具的复杂性是由于它更贴近编译器和操作系统的底层,并提供了更大的灵活性。一旦学习和掌握了相关工具后, 就了解了系统设计的基础知识。运行于Linux操作系统下的自由软件GNU gcc编译器,不仅可以编译Llnux操作系统下运行的应用程序,还可以编译Linux内核本身,甚至可以作交叉编译,编译运行于其它CPU上的程序。所 以,在进行嵌入式系统应用程序开发时,这些工具得到了日益广泛的应用。

  通常情况 下,uClinux的默认终端是串口,内核在启动时所有的信息都打印到串口终端(使用printk函数打印),同时也可以通过串口终端与系统交互。 uClinux在启动时启动了telnetd(远程登录服务),操作者可以远程登录上系统,从而控制系统的运行。至于是否允许远程登录可以通过烧写 romfs文件系统时由用户决定是否启动远程登录服务。

  支持一种新的处理器,必须具备一些编译,汇编工具,使用这些工具可以形成可运行于这种处理器的二进制文件。对于内核使用的编译工具同应用程序使用的有所不同。 uClinux 操作系统提供了嵌入式Web服务器、PPPOE拔号软件、基于IPTable过滤防火墙等功能模块的源代码。路由器软件系统的设计包括uClinux操作 系统的裁剪、基于uClinux操作系统提供的以上功能模块源代码下的修改和设计,从而实现本路由器的嵌入式Web服务器、PPPOE拔号软件、基于 IPTable过滤防火墙。

  uclinux的裁剪牵涉到对目标 的硬件支持问题。要让uClinux支持一个新硬件体系,要做的第一件事情就是收集和构建代码的工具。然后就可以裁减和编译内核。一旦内核支持基本的处理 器功能,它就可以运作了,但是如果缺乏驱动程序的支持,就起不了多大作用。典型的驱动程序集合中包括了诸如控制台终端、基本串行设备和一个可能包含了根文 件系统的块设备的驱动等。

  在这里主要介绍针对我们刚才介绍的实例系统采用的uClinux裁剪方法。本实例中的宿主机上装redhat9操作系统,因为redhat9具备安装uClinux交叉编译工具时所需要的库。

  首先必须在redhat9下建立uclinux开发环境,建立uclinux开发环境的方法有很多,而且也十分方便。可以从

[url]http://www.uClinux.org[/url]处 下载最新的uClinux的源代码、最新的gcc3的工具链,不过针对于不同的工具链在不同的操作系统下,以及目标板的MCU的不一样,可能在编译内核时 会产生错误,在这里,我讲解实例所使用的不是最新版本的。同样的,针对不同的硬件开发环境要对uClinux源代码进行不同的适当修改,修改部分通常是以 代码补丁形式实现的,一般网络上会有各种通用模式的补丁提供使用。好了,切入正题,有了齐全的软件包后,安装过程如下:

  (1) 下载内核和工具包

  uclinux的源代码和文件系统的源代码,软件包后的数字代表完成的日期。

  (2) 安装工具包

  (3) 解压缩内核

  将补丁文件复制到uClinux-disk目录下,进入该目录,在Shell命令中使用如下命令:

  ⑵内核的编译和生成

  执行以下命令可以进行uClinux编译:

  make xconfig。具体的编译选项配置过程本文不做详细介绍。但在此给出编译的一些基本思想:

  ucLinux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了旧内核的bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统度身定制一个更高效,更稳定的内核,就需要重新编译内核。

  为了正确的合理地设置内核编译配置选项,从而只编译系统需要的功能的代码,一般主要有下面四个考虑:

  自己定制编译的内核运行更快(具有更少的代码)。

  系统将拥有更多的内存(内核部分将不会被交换到虚拟内存中)。

  不需要的功能编译进入内核可能会增加被系统攻击者利用的漏洞。

  将某种功能编译为模块方式会比编译到内核内的方式速度要慢一些。

   在此需要补充说明的是内核编译的目的是为了创建一个能够放置在flash上支持flash读取的完成要求功能的内核,同时也是flash读取步骤其中一 步。对uCLinux的内核进行配置和创建要对uCLinux内核的版本进行选择:uCLinux内核的版本号有三种:主号、次号、修订号。以 2.4.10为例一般来说,主号如目前的2是很稳定的。主号的变动说明了操作系统发生了很大的变动。次号如目前的.4,用来说明内核的稳定性。当次号为偶 数号((0,2, 4, 6) 时,表明现在的内核的稳定性强,而当次号为奇数号(1,3, 5) 时,表明现在的内核处于测试的阶段,其稳定性值得考虑,如果你使用次号为奇数号的内核进行配置和创建时、就值得三思而行了。而修订号的发表比较的频繁,它 主要是用来对前面的版本进行修补。开发新的版本和修改以前的版本是同时进行的,很有可能修改的修订版本在新的版本出来之后。

  依次执行以下命令完成uClinux的编译过程:

最终在image目录下生成2个文件:

  zImage——uClinux内核2.4.x的压缩方式可执行映象文件;

  romfs——文件系统的映象文件。

  这就是我们要用来烧录到硬件板内的最终文件了。具体烧写可以通过使用专用的烧写工具来实现,烧写过程一定要参照烧写工具的说明要求来进行。

   其中zImage已经包含了文件系统映象文件,通常直接烧写到Flash文件上即可执行了。当然在这之前要进行BootLoader的烧录, BootLoader其实就是一个引导程序,主要作用就是初始化系统,进而来引导操作系统。在嵌入式系统中,处理器上电后首先执行的一段代码就是 BootLoader,BootLoader与硬件密切相关,其代码主要用C和汇编语言写成,不同的系统中,BootLoader的功能有所不同,但主要 作用还是差不多的,主要有下面几点:

初始化微控制器MCU运行的时钟频率;

  初始化Flash和内存的数据宽度,读/写访问周期和刷新周期;

  初始化系统中各种片内、片外设备和I/O端口设备;

  初始化系统各种运行模式下的寄存器和堆栈;

  加载和引导操作系统;

BLOb 是BootLoaderObject的缩写,它是一个功能强大、源代码公开的自由软件,它已经实现了对多种处理器芯片的Linux 引导支持。对ARM7等核心的BootLoader支持版本可以到专业网站上进行下载,并稍微做适当修改来满足开发应用中的硬件环境要求即可,在此我们不 做过多讲述。

  上面所讲述的内核编译过程只是比较宽泛的、笼统的操作过程,也就是说只是基本的操作过程,而在真正的路由功能实现过程 中,还要对内核进行多种设置编译,比如说对硬件系统中设计到的部件进行驱动配置安装等,当然,这些并不是特别难的操作技术,再比如我们下面就要讲到的内 容,这可就是很有挑战性的核心技术了,这些都是针对内核进行技术性操作来实现特定的网络功能。

第7章:内核编译核心部分 

文 件系统是uClinux操作系统的重要组成部分,uClinux文件系统是操作运行的基础。许多嵌入式系统在不存在磁盘的情况下也可以运行。文件系统可以 随同内核一起被打包并在启动时作为一个文件系统的映像被加载。对一个简单的应用系统来说,这己足够了。文件系统可以存放在一个传统磁盘中,但也可以存放在 非易失性的存储介质— 闪存中。闪存有一个引导块,它存放了CPU上电后运行的第一个软件,这个软件可以是uclinux的引导程序,也可以是自己编的bootloader。 uClinux的内核可以被引导程序从闪存中拷贝到RAM中全速运行。闪存也可以作为文件的存储介质,必要时写入一些需要保存的数据。

   uClinux支持NFS(Network File System),它允许通过网络加载各种应用程序。由于用在每一个嵌入式系统上的软件可以从一个公用的服务器上加载,这在控制软件的修订或升级中是很重要 的.在系统运行的过程中,导入和导出数据、配置、状态信息的备份也很重要。对用户监控而言,这是一个非常强大的功能。例如,一个嵌入式系统可能装配了一个 RAM DISK,它包含着与系统当前状态的更新维持一致的(状态)文件。那么别的嵌入式系统仅需通过网络把这个RAM DISK作为远程磁盘mount过来便可以访问那些位于远端RAM DISK中的状态文件。这也允许在另一台机器上的WEB服务器借助简单的CGI脚本来访问那些状态信息。运行在其他机器上的应用程序包能够很容易地访问这 些数据。uClinux操作系统根据不同的安装选择可以生成不同的文件系统。系统中提供了十分丰富的文件系统以供不同需要的用户选择。每种类型的文件系统 的基本块大小、优化分配策略、一次传送的数据长度等等都是相互匹配的,使得本类文件系统均有相应的最佳性能。

2、嵌入式Web服务器

对uClinux操作系统下嵌入式Web技术的实现主要用于用户可以通过网

  页方式来管理路由器。

   uClinux下,主要有三个WebServer:htpd,thttpd和Boa。Httpd是最简单的一个Web Server,它的功能最弱,不支持认证,不支持CGI。Thttpd和Boa都支持认证、CGI等,功能都比较全。为了实现动态Web技术,这里我们选 择实现一个支持CGI的、非常适合于嵌入式系统的Boa Web Server。Boa是一个单任务的http服务器,源代码开放、性能高。目前,uClinux的代码中已经包含boa的源代码,在uClinux下实现 Boa,需要对Boa做一些配置和修改。这主要通过对boa.conf和mime.types文件进行修改来实现,需要改动的配置有以下几项:

  由于uClinux默认的根文件系统romfs是只读的,不能用mkdir等命令来新建目录,故应在编译内核前先建好要用到的目录,这通过修改

  定义默认首页和CGI程序所在目录,即

  这样指定后,.index.htm为远程浏览客户访问WebServer所看到的首页默认值,用C编写的CGI程序编译成二进制文件,放到/cgi-bin/目录下,CGI程序能被正确地执行。

  配置过程后,重新编译内核,编译时选中Boa选项。把编译好的内核下载到硬 件板,启动uclinux,完成IP配置,启动Boa Web Server,然后就可以通过lE访问你的网页了。如果想启动uclinux时自动启动Boa Web Server,可以修改re文件,进入uclinux-samsung/vendors/Samsung/4510B目录,在运行脚本rc中增加两行:

  修改后重新编译内核,再下载到硬件板运行.运行uclinux后,不需要配置就可以直接通过IE来访问

PHP等动态Web页面技术。CGI(通用网关接口)提供Web服务器一个执行外部程序的通道,这种服务端技术使得浏览器和服务器之间具有交互性。CGI 程序属于一个外部程序,需要编译成可执行文件,以便在服务端运行。浏览器将用户输入的数据送到Web服务器,Web服务器将数据使用STDIN送给CGI 程序,在执行CGI程序后,可能会访问存储数据的一些文档,最后使用STDOUT输出HTML形式的结构文件,经Web服务器送回浏览器显示给用户。 CGI程序可以用任何程序设计语言编写,如Shell脚本语言、Perl,Fortran, Pascal, C语言等。但目前uclinux不支持Pert, Fortran等语言,而且C语言在平台无关性上表示不错,所以我们选择用C来编写CGI程序。另外,uClinux也不支持数据库,所以需要保存的数据 只能保存到文件中,CGI查询数据时也是查询这些文件,而不是访问数据库。

  ⑶uClinux下动态Web页面的实现

   下面通过一个例子来说明如何实现uClinux下的动态Web页面技术。此例子的目的是使用户能够通过Web页面内嵌表单提交数据,并能把用户提交的数 据通过Web浏览器正确地返回给用户。实现动态Web页面的第一步是用HTML语言编写Web页及内建表单。编写Web页面时,要由ACTION属性来指

   实现动态 Web页面的第二步是用C编写CGI程序,CGI程序分为以下几部分:①根据POST方法或GET方法从提交的表单中接收数据;②URL编码的解码;③用 printf() 函数来产生HTML源代码,并将经过解码后的数据正确地返回给浏览器。包括demo.c, cgivars.h和cgivars.c三个文件。将编写好的CGI程序编译成二进制文件放在cgi-bin/目录下,CGI程序能被正确地执行,最终 CGI程序就可以对上述表单数据的进行处理了。

  经过一系列深入的配置后,基本的路由功能器就这样诞生了,当然实际中路由器还有相当多 的应用功能,这些都是通过软件开发来逐步深层次实现的,如果你想成为一个嵌入式工程师的话,那这篇文章就算是一个引路人吧,要达到更高的境界,还需要自己 刻苦学习研究,一步一步在魔幻般的技术殿堂中自由遨游。

}

我要回帖

更多关于 printk打印级别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信