Profil de Wekeywekey 的个人空间PhotosBlogListesPlus Outils Aide

Blog


23 juin

IPTV端到端业务质量监测技术研究

本文关键字: IPTV99, 监测45, 运营商6, 网络23, 监测系统5, 融合2, 电信5, 有线电视1, 宽带2, Qos8, ITU15, 测试30, VOD4, 流媒体3, 信令1, IP6, 服务器1, DSL5, 国际标准化组织1, 机顶盒6, 广域网1, H.2641, 中国电信2, 电信网1

 

摘要 在IPTV业务的实际运营中,如何保证和监测端到端的业务质量是运营商关注的主要问题。本文首先介绍了IPTV业务质量的定义和业务质量模型,并从运营商角度提出了业务质量监测的需求。之后介绍了目前IPTV质量监测领域的技术、标准和产业发展状况,最后提出了在IPTV业务网络中部署端到端监测系统的技术方案。

 

1、引言

随着近几年在业务融合、技术、标准以及商业模式等方面的摸索,IPTV业务在中国开始逐步成熟并进入到规模商用阶段。IPTV作为一种电信级业务,要达到大规模应用需要有效的业务质量保障。由于IPTV是电视类的媒体业务,用户希望得到如同有线电视的服务水平,包括频道切换速度、节目的图像质量、播放的流畅性等。而传统的宽带业务质量监测侧重于数据链路层和网络层的监测,无法直接反映用户对IPTV业务的主观感受,因此不能满足IPTV质量监测的需求。

本文针对现有监测方案的不足,提出了一种采用分布式部署与集中管理相结合的监测方案,该方案具有监测功能丰富、可扩展性强等优点,可满足现阶段IPTV业务质量监测的需要。

2、业务质量定义及模型

业务质量(quality of service,QoS)术语并不是针对IPTV的,在很多电信业务中都提出QoS要求及相关的QoS保障技术。在ITU-T E.800[1]标准中,QoS被定义为“反映用户对业务使用满意程度的服务性能的综合效果”。对传统电信业务而言,QoS通常指网络性能,尤其是网络传输性能。而由于IPTV是一种上层应用的业务,传统的QoS无法满足对最终用户感受的评估,因此目前业界往往采用体验质量(quality of experience,QoE)一词来描述面向最终用户应用的业务质量。QoE在ITU-T P.10/G.100[2]中被定义为“最终用户对使用的应用或业务的总体主观可接受程度”,可见QoE相比QoS更强调最终用户的业务使用感受。

目前尚无国际规范对IPTV业务质量进行完整定义,国际标准组织ITU正在进行IPTV GSI(global standard initial,全球主动标准)工作,以推动全球IPTV标准化进程。其中暂时还没有对IPTV业务质量进行定义,仍沿用了ITU-T P.10/G.100中对QoE的定义。IPTV GSI也指出,IPTV QoE应该同时包含主观评估质量和客观评估质量两部分内容,前者主要根据人眼视觉系统来评估视频质量,通过主观感受来评估体验质量;后者则可以定义各种客观指标,并采用相应的测试工具进行测量,具体如图1所示。

目前ITU IPTV GSI规定的QoE定义范围

图1 目前ITU IPTV GSI规定的QoE定义范围

作者比较赞同ITU IPTV GSI目前对IPTV业务质量的定义,在本文中也采用IPTV QoE来表示IPTV业务质量。当然,从运营商的角度来说不仅仅关心IPTV业务质量定义,更具实际意义的是如何量化IPTV业务质量,如何建立IPTV 业务质量的指标体系以指导现网的质量运维。因此,需要根据IPTV所涉及的技术环节,建立IPTV业务质量的评估模型。

图2参考OSI的7层模型,给出了一种可供参考的IPTV业务质量的参数模型,并展示了与IPTV协议栈之间的对应关系。

IPTV业务质量模型与OSI 7层模型和IPTV协议栈的关系

图2 IPTV业务质量模型与OSI 7层模型和IPTV协议栈的关系

如图2所示,IPTV QoE的参数模型覆盖了OSI 7层模型的所有层次。其中,客观QoE相关的分层质量对应于IPTV的协议栈中各个协议,各层次的质量参数可以通过采集对应的协议及其字段获得。

具体的,客观QoE包含以下几方面的内容。

●内容质量和业务控制质量:主要指直播频道、时移节目、VOD节目、图片、文字等内容的品质和业务控制的性能指标。例如对于直播频道质量,需要采集和分析媒体编码参数、分辨率参数等;对于业务控制质量,需要采集HTTP和RTSP请求的响应速度、页面数据呈现完整度、组播加入/退出的时延等。

流媒体质量:主要指流媒体传输层的性能指标,以采用MPEG2 TS协议传输IPTV节目为例,DVB系统测试标准TR 101-290根据各参数对质量影响的程度不同,定义了3个级别,每个级别分别对应一组质量参数,这些参数同样可供采用MPEG2 TS协议的IPTV系统参考,例如需要采集第一级别中的同步错误字段(sync loss)、包识别丢失(PID missing),第二级别中的数据传输错误(transport error)、节目参考时钟抖动错误(PCR,jitter error)等参数。如果采用RTSP作为VOD节目的流控制协议,则要采集RTSP信令参数。

●网络传输层质量:主要指网络传输层相关协议的性能指标,包括TCP/UDP的重传次数,在采用了RTP的情况下,需要监测RTP丢包率、RTP抖动等。

●网络层质量:主要指传统IP网络层的性能指标,根据ITU-T Y.1540[3]建议,主要为IP丢包率、IP包时延、IP包抖动及其相关参数。

●链路层质量:根据不同的链路层类型,需要采集不同的性能指标。由于这个层次的质量保障是面向全业务而不仅仅是IPTV业务,本文不做详述。

主观QoE主要是用户对IPTV业务使用中的主观感受,这些感受是对服务接入速度、内容质量、使用操作便利性等多方面的综合,至少可以包含以下参数:

●开机进入IPTV主界面的速度;

●用户鉴权频道浏览(加入/离开时延);

●视频内容的清晰度和流畅程度;

●直播频道的切换速度;

●VOD节目进行快进、快退和暂停操作的响应速度;

●业务请求的响应速度、业务内容的完整性等。

3、业务质量监测需求

IPTV业务质量监测应包含两部分,即监控和测试,二者相互关联但又相对独立。其中监控技术主要是面向IPTV运维部门使用,协助IPTV平台及网络运维部门监控网络运行中的质量状态,帮助定位故障和解决问题,因此要求监控技术能够覆盖整个IPTV业务质量领域。测试主要面向IPTV产品研发、性能评估和故障排查等应用,因此测试技术往往针对与IPTV业务质量相关的某一个领域或层面,重点解决某一类问题。

如前所述,IPTV业务质量监控应该覆盖整个IPTV业务领域,是面向IPTV业务的端到端全网监测,具体应满足以下需求。

●满足IPTV业务的7×24 h不间断监测,同时不对正在运营的IPTV系统产生影响。

●监测范围能够覆盖整个IPTV网络的各个环节,并能根据各环节采集的参数进行对比分析。这些环节至少包括:内容头端系统、系统核心平台出口、边缘节点出口、关键网络节点等。

●当IPTV质量发生劣化时,系统能够自动采集质量劣化的技术参数,并作详细记录;能够通过对比分析各节点参数,进行故障点分析和快速定位。

●能够根据采集参数进行平台及服务器的性能分析等。

●能够完成图2中质量模型各层次的分析。

而IPTV业务质量测试主要针对与IPTV业务质量相关的某一个领域或层面,如在实验室进行质量验证或问题和故障发生后进行定位和排障,或针对IPTV某个网元设备进行测试。因此IPTV业务质量测试往往可以借助原来各层面的相关测试工具进行,下面举几个例子。

●内容质量的测试:主要在实验室或内容上线前,采用专门的质量检测工具进行图像质量、伴音质量、字幕质量、元数据质量等的测试,主要针对直播频道、时移节目、VOD节目、图片、文字等内容的品质和业务控制的性能指标。

●流媒体层的测试:主要在系统上线前对流协议的规范性进行测试和验证。

●网络传输层、网络层和链路层质量测试:主要采用与应用无关的专用测试软件或仪表测试目前IPTV承载网络的质量状况。

4、标准及产业链现状

如前所述,IPTV作为一个新兴的融合性业务,目前还没有非常完备的国际规范。虽然包括ITU IPTV GSI、ATIS(alliance for telecommunication industry solution,电信行业解决方案联盟)、IPTV论坛、DSL论坛、DVB(digital video broadcasting,数字视频广播)等多家国际标准化组织已开始相关的标准化推进工作,但目前尚未正式发布。尽管如此,在IPTV业务质量监测的系统架构、参数建议等方面已取得了较大进展。

●ITU IPTV GSI:已经初步完成了IPTV业务质量相关的需求草案和IPTV业务性能监测的草案,目前ITU的相关工作组正在进行后续的工作,计划在2008年底能够成为国际规范。

●ATIS:起步较早,在2006年就开始了IPTV QoS指标体系、IPTV QoE模型等相关的制定工作,计划在2008年完成。

●DSL论坛:主要关注机顶盒侧与业务质量相关的参数定义,目前已经完成了机顶盒数据模型技术报告(DSL Forum TR135)、可应用于机顶盒的终端广域网管理协议技术报告(DSL Forum TR069)等。

在产业链支持方面,尽管还没有完整的IPTV业务质量监测技术标准可供参考,但由于IPTV业务的快速部署和运营商对质量监测需求的迫切,市场上已经有多家测试仪表厂商能够提供IPTV质量监测仪表。如前所述,IPTV业务质量监测包含测试和监控两部分,因此这些仪表也可对应地分为测试和监控两大类。

在测试仪表方面,主要是针对某个层面的专用测试工具,例如美国IneoQuest公司提供的Singulus G1-T系列测试仪表,其主要特征是支持RFC4445定义的MDI指标值,可应用于IPTV数据的模拟、捕捉、数据流监控以及视频质量的分析;思博伦公司提供的IPTV测试解决方案包括宽带网络测试、频道切换测试、频道内容验证等;泰克公司则提供了较为完备的视频质量测试和分析工具,如能够分析H.264编解码参数的MTS4EA,能够测试视频主观质量的PQA仪表等。

在监控系统方面,目前还没有很完备的、能完全满足运营商需求的解决方案。美国JDSU公司提供的QT系列仪表可应用于IPTV直播频道的7×24 h质量监控,监控的内容包括了网络质量、传输层质量等。因此,目前国内的IPTV运营商开始根据运维需求自主或与合作伙伴联合开发IPTV业务质量监测系统。例如中国电信上海研究院就和国内的中创信测合作开发了IPTV业务质量监测系统,该系统已能够支持现网应用的主流IPTV系统,支持从业务层到网络层的端到端业务质量监测。

5、IPTV端到端业务质量监测方案

以下以中国电信上海研究院与中创信测合作开发的IPTV业务质量监测系统为例,介绍IPTV端到端的质量解决方案。该系统是一个独立的分布式系统,叠加在现有IPTV业务网络中,通过部署监测代理或测试探针的方式来获得IPTV业务运行时各个网络节点的相关质量参数数据,并由监测平台进行集中采集、分析和统计,以获得IPTV业务总体质量情况。

值得一提的是,该方案的系统架构与目前ITU IPTV GSI正在制定的IPTV性能监测标准一致,均采用了“分布部署、集中采集”的系统架构,如图3所示,其中PT指监测点。

目前ITU IPTV GSI定义的业务质量系统架构

图3 目前ITU IPTV GSI定义的业务质量系统架构

如图3所示,整个系统主要包括监测管理平台、监测代理。

监测管理平台:负责管理监测代理和采集所有代理上传的监测数据,并执行统计和分析,是整个系统的核心组件。

监测代理:主要完成业务质量参数的采集和上传,根据部署的监测点不同,又可以分为3种工作模式。

●仿真模式:即主动模式,仿真用户的IPTV业务登录、认证及基本业务流程,能够通过预定义的脚本文件,自动进行相关的测试,记录并形成业务质量参数记录文件,上传给监测管理平台所有的性能参数。在图3中,该模式可以部署在PT4和PT5的位置。

●监测模式:即被动模式,通过数据镜像或备份的方式获得用户业务数据,分析质量参数,并记录和上传给监测管理平台所有参数。在图3中,该模式可以部署在PT1、PT2和PT3的位置。

●机顶盒内嵌模式(STB embedded test agent,STB-TA):在机顶盒内部嵌入测试客户端软件,能够将机顶盒运行中的业务质量参数记录并上传到监测管理平台。在图3中,该模式可以部署在PT1、PT2和PT3的位置。

当然,从系统角度来看,IPTV监测系统在不同的节点所关注的质量是不同的,因此当监测代理工作在不同的模式下或部署在不同的节点时,所采集的质量参数也不尽相同,这里就不详述了。

从整个系统的架构可以看出,上述系统基本覆盖了IPTV端到端各个环节,所采集的参数能够帮助完成图2中质量模型客观QoE各个层面的分析,能够协助IPTV平台及网络运维部门监控网络运行中的质量状态,从而帮助定位故障和解决问题。

6、结束语

IPTV是一个跨广电网、IP网、电信网的复杂应用,其业务质量监测需要综合考虑视音频内容质量、网络质量、用户最终感受等多重因素。本文对IPTV业务质量监测相关技术进行了研究,并提出了IPTV业务质量模型及性能监测的系统框架。

但是对于IPTV运维部门来说,需要一整套IPTV业务质量指标体系,希望能够通过类似主观评测分的等级划分来衡量整个IPTV系统质量,并提供可操作的监测手段。因此,后续还需要研究IPTV业务质量指标体系,量化和评估每个指标对最终用户感受的影响,并研究各业务质量指标的采集方法,从而构建完整的IPTV业务质量监测体系,保证IPTV业务的顺利运营。

参考文献

1 ITU-T E.800.Terms and definitions related to quality of service and network performance including dependability,August 1994

2 ITU-T P.10/G.100.Vocabulary for performance and quality of service,July 2006

3 ITU-T Y.1540.Internet protocol data communication service-IP packet transfer and availability performance parameters,Nov、2007

4 DSL Forum.www.dslforum.org

作者:罗斯青 段保通   来源:电信科学

2 juin

GCC笔记

转载自: zzzppp.cublog.cn

 

The History of GCC


1984年,Richard Stallman发起了自由软件运动,GNU (Gnu's Not Unix)项目应运而生,3年后,最初版的GCC横空出世,成为第一款可移植、可优化、支持ANSI C的开源C编译器。
GCC最初的全名是GNU C Compiler,之后,随着GCC支持的语言越来越多,它的名称变成了GNU Compiler Collection。
这里介绍的gcc是GCC的前端,C编译器.

警告信息


    -Wall : 显示所有常用的编译警告信息。
    -W    : 显示更多的常用编译警告,如:变量未使用、一些逻辑错误。
    -Wconversion : 警告隐式类型转换。
    -Wshadow : 警告影子变量(在代码块中再次声明已声明的变量)
    -Wcast-qual :警告指针修改了变量的修饰符。如:指针修改const变量。
    -Wwrite-strings : 警告修改const字符串。
    -Wtraditional : 警告ANSI编译器与传统C编译器有不同的解释。
    -Werror : 即使只有警告信息,也不编译。(gcc默认:若只有警告信息,则进行编译,若有错误信息,则不编译)

C语言标准


你可以在gcc的命令行中通过指定选项来选择相应的C语言标准: 从传统c到最新的GNU扩展C. 默认情况下, gcc使用最新的GNU C扩展.
    -ansi : 关闭GNU扩展中与ANSI C相抵触的部分。
    -pedantic          : 关闭所有的GNU扩展。
    -std=c89           : 遵循C89标准
    -std=c99           : 遵循C99标准
    -std=traditional : 使用原始C
注意:后4个选项可以与-ansi结合使用,也可以单独使用。
可在gcc中使用大量GNU C扩展.

生成特定格式的文件


以hello.c为例子,可以设置选项生成hello.i, hello.s, hello.o以及最终的hello文件:
    hello.c : 最初的源代码文件;
    hello.i : 经过编译预处理的源代码;
    hello.s : 汇编处理后的汇编代码;
    hello.o : 编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义。
    hello / a.out : 最终的可执行文件
    (还有.a(静态库文件), .so(动态库文件), .s(汇编源文件)留待以后讨论)

如果你不通过-o指定生成可执行文件名,那么会默认生成a.out. 不指定生成文件名肯能覆盖你上次生成的a.out.

e.g.
$ gcc hello.c
在不给gcc传递任何参数的情况下, gcc执行默认的操作: 将源文件编译为目标文件--> 将目标文件连接为可执行文件(名为a.out) --> 删除目标文件.

-c生成.o文件时,默认生成与源代码的主干同名的.o文件。比如对应hello.c生成hello.o. 但也可在生成目标文件时指定目标文件名(注意同时要给出.o后缀): $ gcc -c -o demo.o demo.c

    $ gcc -Wall -c hello.c              : 生成hello.o
    $ gcc -Wall -c -save-temps hello.c  : 生成hello.i, hello.s, hello.o
    注意-Wall 选项的使用场合:仅在涉及到编译(即会生成.o文件时,用-Wall)  

多文件编译、连接


如果原文件分布于多个文件中:file1.c, file2,c
    $ gcc -Wall file1.c file2.c -o name

若对其中一个文件作了修改,则可只重新编译该文件,再连接所有文件:
    $ gcc -Wall -c file2.c
    $ gcc file1.c file2.o -c name

注意:若编译器在命令行中从左向右顺序读取.o文件,则它们的出现顺序有限制:含有某函数定义的文件必须出现在含有调用该函数的文件之后。好在GCC无此限制。

编译预处理


以上述的hello.c为例, 要对它进行编译预备处理, 有两种方法: 在gcc中指定-E选项, 或直接调用cpp.gcc的编译预处理命令程序为cpp,比较新版本的gcc已经将cpp集成了,但仍提供了cpp命令. 可以直接调用cpp命令, 也可以在gcc中指定-E选项指定它只进行编译预处理.
$ gcc -E hello.c                            ==  $ cpp hello.c
上述命令马上将预处理结果显示出来. 不利于观看. 可采用-c将预处理结果保存:
$ gcc -E -c hello.i hello.c              ==  $ cpp -o hello.i hello.c
注意, -c指定名称要给出".i"后缀.
另外, gcc针对编译预处理提供了一些选项:
(1) 除了直接在源代码中用 #define NAME来定义宏外,gcc可在命令行中定义宏:-DNAME(其中NAME为宏名),  也可对宏赋值: -DNAME=value 注意等号两边不能有空格! 由于宏扩展只是一个替换过程,也可以将value换成表达式,但要在两边加上双括号: -DNAME="statement"
e.g. $ gcc -Wall -DVALUE="2+2" tmp.c -o tmp
如果不显示地赋值,如上例子,只给出:-DVALUE,gcc将使用默认值:1.
(2) 除了用户定义的宏外, 有一些宏是编译器自动定义的,它们以__开头,运行: $ cpp -dM /dev/null, 可以看到这些宏. 注意, 其中含有不以__开头的非ANSI宏,它们可以通过-ansi选项被禁止。
查看宏扩展
1, 运行 $ gcc -E test.c ,gcc对test.c进行编译预处理,并立马显示结果. (不执行编译) 2, 运行 $ gcc -c -save-temps test.c ,不光产生test.o,还产生test.i, test.s,前者是编译预处理结果, 后者是汇编结果.
利用Emacs查看编译预处理结果
针对含有编译预处理命令的代码,可以利用emacs方便地查看预处理结果,而不需执行编译,更为方便的是,可以只选取一段代码,而非整个文件:
1,选择想要查看的代码
2,C-c C-e (M-x c-macro-expand)
这样,就自动在一个名为"Macroexpansion"的buffer中显示pre-processed结果.
生成汇编代码
使用"-S"选项指定gcc生成以".s"为后缀的汇编代码:
$ gcc -S hello.c
$ gcc -S -o hello.s hello.c
生成汇编语言的格式取决于目标平台. 另外, 如果是多个.c文件, 那么针对每一个.c文件生成一个.s文件.

包含头文件


在程序中包含与连接库对应的头文件是很重要的方面,要使用库,就一定要能正确地引用头文件。一般在代码中通过#include引入头文件, 如果头文件位于系统默认的包含路径(/usr/includes), 则只需在#include中给出头文件的名字, 不需指定完整路径.  但若要包含的头文件位于系统默认包含路径之外, 则有其它的工作要做: 可以(在源文件中)同时指定头文件的全路径. 但考虑到可移植性,最好通过-I在调用gcc的编译命令中指定。

下面看这个求立方的小程序(阴影语句表示刚开始不存在):

#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{
  double x = pow (2.0, 3.0);
  printf("The cube of 2.0 is %f\n", x);
  return 0;
}

使用gcc-2.95来编译它(-lm选项在后面的连接选项中有介绍, 这里只讨论头文件的包含问题):
$ gcc-2.95 -Wall pow.c -lm -o pow_2.95
pow.c: In function `main':
pow.c:5: warning: implicit declaration of function `pow'

程序编译成功,但gcc给出警告: pow函数隐式声明。
$ ./pow_2.95
The cube of 2.0 is 1.000000

明显执行结果是错误的,在源程序中引入头文件(#include <math.h>),消除了错误。

不要忽略Warning信息!它可能预示着,程序虽然编译成功,但运行结果可能有错。故,起码加上"-Wall"编译选项!并尽量修正Warning警告。

搜索路径

首先要理解 #include<file.h>和#include"file.h"的区别:
#include<file.h>只在默认的系统包含路径搜索头文件
#include"file.h"首先在当前目录搜索头文件, 若头文件不位于当前目录, 则到系统默认的包含路径搜索头文件.

UNIX类系统默认的系统路径为:

头文件,包含路径: /usr/local/include/  or  /usr/include/
库文件,连接路径: /usr/local/lib/          or  /usr/lib/   

对于标准c库(glibc或其它c库)的头文件, 我们可以直接在源文件中使用#include <file.h>来引入头文件.

如果要在源文件中引入自己的头文件, 就需要考虑下面的问题:

1, 如果使用非系统头文件, 头文件和源文件位于同一个目录, 如何引用头文件呢?
——我们可以简单地在源文件中使用 #include "file.h", gcc将当前目录的file.h引入到源文件. 如果你很固执, 仍想使用#include <file.h>语句, 可以在调用gcc时添加"-I."来将当前目录添加到系统包含路径. 细心的朋友可能会想到: 这样对引用其它头文件会不会有影响? 比如, #include<file.h>之后紧接着一个#include<math.h>, 它能正确引入math.h吗? 答案是: 没有影响. 仍然能正确引用math.h. 我的理解是: "-I."将当前目录作为包含路径的第一选择, 若在当前目录找不到头文件, 则在默认路径搜索头文件. 这实际上和#include"file.h"是一个意思.

2, 对于比较大型的工程, 会有许多用户自定义的头文件, 并且头文件和.c文件会位于不同的目录. 又该如何在.c文件中引用头文件呢?
—— 可以直接在.c文件中利用#include“/path/file.h", 通过指定头文件的路径(可以是绝对路径, 也可以是相对路径)来包含头文件. 但这明显降低了程序的可移植性. 在别的系统环境下编译可能会出现问题. 所以还是利用"-I"选项指定头文件完整的包含路径.

针对头文件比较多的情况, 最好把它们统一放在一个目录中, 比如~/project/include. 这样就不需为不同的头文件指定不同的路径. 如果你嫌每次输入这么多选项太麻烦, 你可以通过设置环境变量来添加路径:
$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
$ export C_INCLUDE_PATH
$ LIBRART_PATH=/opt/gdbm-1.8.3/lib
$ export LIBRART_PATH
可一次指定多个搜索路径,":"用于分隔它们,"."表示当前路径,如:
$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib
(可以添加多个路径,路径之间用:相隔,.代表当前目录,若.在最前头,也可省略)
当然,若想永久地添加这些路径,可以在.bash_profile中添加上述语句.

3, 还有一个比较猥琐的办法: 系统默认的包含路径不是/usr/include或/usr/local/include么? 我把自己的头文件拷贝到其中的一个目录, 不就可以了么? 的确可以这样, 如果你只想在你自己的机器上编译运行这个程序的话.

前面介绍了三种添加搜索路径的方法,如果这三种方法一起使用,优先级如何呢?
命令行设置 > 环境变量设置 > 系统默认

与外部库连接


前面介绍了如何包含头文件. 而头文件和库是息息相关的, 使用库时, 要在源代码中包含适当的头文件,这样才能声明库中函数的原型(发布库时, 就需要给出相应的头文件).
和包含路径一样, 系统也有默认的连接路径:
头文件,包含路径: /usr/local/include/  or  /usr/include/
库文件,连接路径: /usr/local/lib/          or  /usr/lib/  
同样地, 我们想要使用某个库里的函数, 必须将这个库连接到使用那些函数的程序中.

有一个例外: libc.a或libc.so (C标准库,它包含了ANSI C所定义的C函数)是不需要你显式连接的, 所有的C程序在运行时都会自动加载c标准库.

除了C标准库之外的库称之为"外部库", 它可能是别人提供给你的, 也可能是你自己创建的(后面有介绍如何创建库的内容).
外部库有两种:(1)静态连接库lib.a
                     (2)共享连接库lib.so

两者的共同点:
    .a, .so都是.o目标文件的集合,这些目标文件中含有一些函数的定义(机器码),而这些函数将在连接时会被最终的可执行文件用到。

两者的区别:
    静态库.a  : 当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中. 静态库有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.

    共享库.so : 与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中, 这样就使可执行文件比较小, 节省磁盘空间(更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用).共享库还有个优点: 若库本身被更新, 不需要重新编译与它连接的源程序。

静态库

下面我们来看一个简单的例子,计算2.0的平方根(假设文件名为sqrt.c):

#include <math.h>
#include <stdio.h>
int
main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}

用gcc将它编译为可执行文件:
$ gcc -Wall sqrt.c -o sqrt
编译成功,没有任何警告或错误信息。执行结果也正确。
$ ./sqrt
The square root of 2.0 is 1.414214
下面我们来看看刚才使用的gcc版本:
$ gcc --version
gcc (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

现在我用2.95版的gcc把sqrt.c再编译一次:
$ gcc-2.95 -Wall sqrt.c -o sqrt_2.95
/tmp/ccVBJd2H.o: In function `main':
  sqrt.c:(.text+0x16): undefined reference to `sqrt'
     collect2: ld returned 1 exit status
编译器会给出上述错误信息,这是因为sqrt函数不能与外部数学库"libm.a"相连。sqrt函数没有在程序中定义,也不存在于默认C库 "libc.a"中,如果用gcc-2.95,应该显式地选择连接库。上述出错信息中的"/tmp/ccVBJd2H.o"是gcc创造的临时目标文件,用作连接时用。

使用下列的命令可以成功编译:
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95
它告知gcc:在编译sqrt.c时,加入位于/usr/lib中的libm.a库(C数学库)。

C库文件默认位于/usr/lib, /usr/local/lib系统目录中; gcc默认地从/usr/local/lib, /usr/lib中搜索库文件。(在我的Ubuntu系统中,C库文件位于/urs/lib中。

这里还要注意连接顺序的问题,比如上述命令,如果我改成:
$ gcc-2.95 -Wall /usr/lib/libm.a sqrt.c -o sqrt_2.95
gcc会给出出错信息:
/tmp/cc6b3bIa.o: In function `main':
sqrt.c:(.text+0x16): undefined reference to `sqrt'
collect2: ld returned 1 exit status

正如读取目标文件的顺序,gcc也在命令行中从左向右读取库文件——任何包含某函数定义的库文件必须位于调用该函数的目标文件之后!

指定库文件的绝对路径比较繁琐,有一种简化方法,相对于上述命令,可以用下面的命令来替代:
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95
其中的"-l"表示与库文件连接,"m"代表"libm.a"中的m。一般而言,"-lNAME"选项会使gcc将目标文件与名为"libNAME.a"的库文件相连。(这里假设使用默认目录中的库,对于其他目录中的库文件,参考后面的“搜索路径”。)

上面所提到的"libm.a"就是静态库文件,所有静态库文件的扩展名都是.a!
$ whereis libm.a
libm: /usr/lib/libm.a /usr/lib/libm.so

正如前面所说,默认的库文件位于/usr/lib/或/usr/local/lib/目录中。其中,libm.a是静态库文件,libm.so是后面会介绍的动态共享库文件。

如果调用的函数都包含在libc.a中(C标准库被包含在/usr/lib/libc.a中,它包含了ANSI C所定义的C函数)。那么没有必要显式指定libc.a:所有的C程序运行时都自动包含了C标准库!(试试 $ gcc-2.95 -Wall hello.c -o hello)。

共享库

正因为共享库的优点,如果系统中存在.so库,gcc默认使用共享库(在/usr/lib/目录中,库文件以共享和静态两种版本存在)。 

运行:$ gcc -Wall -L. hello.c -lNAME -o hello
gcc先检查是否有替代的libNAME.so库可用。   

正如前面所说,共享库以.so为扩展名(so == shared object)。

那么,如果不想用共享库,而只用静态库呢?可以加上 -static选项
$ gcc -Wall -static hello.c -lNAME -o hello
它等价于:
$ gcc -Wall hello.c libNAME.a -o hello

$ gcc-2.95 -Wall sqrt.c -static -lm -o sqrt_2.95_static
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95_default
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95_a
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.so -o sqrt_2.95_so

$ ls -l sqrt*
-rwxr-xr-x  1 zp zp  21076 2006-04-25 14:52 sqrt_2.95_a
-rwxr-xr-x  1 zp zp   7604 2006-04-25 14:52 sqrt_2.95_default
-rwxr-xr-x  1 zp zp   7604 2006-04-25 14:52 sqrt_2.95_so
-rwxr-xr-x  1 zp zp 487393 2006-04-25 14:52 sqrt_2.95_static

上述用四种方式编译sqrt.c,并比较了可执行文件的大小。奇怪的是,-static -lm 和 /lib/libm.a为什么有区别?有知其原因着,恳请指明,在此谢谢了! :)

如果libNAME.a在当前目录,应执行下面的命令:
$ gcc -Wall -L. hello.c -lNAME -o hello
-L.表示将当前目录加到连接路径。

利用GNU archiver创建库

$ ar cr libhello.a hello_fn.o by_fn.o
从hello_fn.o和by_fn.o创建libihello.a,其中cr表示:creat & replace
$ ar t libhello.a
列出libhello.a中的内容,t == table
(也可创建libhello.so)

关于创建库的详细介绍,可参考本blog的GNU binutils笔记

调试


一般地,可执行文件中是不包含任何对源代码的参考的,而debugger要工作,就要知道目标文件/可执行文件中的机器码对应的源代码的信息(如:哪条语句、函数名、变量名...). debugger工作原理:将函数名、变量名,对它们的引用,将所有这些对象对应的代码行号储存到目标文件或可执行文件的符号表中。

GCC提供-g选项,将调试信息加入到目标文件或可执行文件中。
$ gcc -Wall -g hello.c -o hello
注意:若发生了段错误,但没有core dump,是由于系统禁止core文件的生成!
$ ulimit -c  ,若显示为0,则系统禁止了core dump

解决方法:
$ ulimit -c unlimited  (只对当前shell进程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一劳永逸)

优化


GCC具有优化代码的功能,代码的优化是一项比较复杂的工作,它可归为:源代码级优化、速度与空间的权衡、执行代码的调度。

GCC提供了下列优化选项:
    -O0  : 默认不优化(若要生成调试信息,最好不优化)
    -O1  : 简单优化,不进行速度与空间的权衡优化;   
    -O2  : 进一步的优化,包括了调度。(若要优化,该选项最适合,它是GNU发布软件的默认优化级别;
    -O3  : 鸡肋,兴许使程序速度更慢;
    -funroll-loops  : 展开循环,会使可执行文件增大,而速度是否增加取决于特定环境;
    -Os  : 生成最小执行文件;
一般来说,调试时不优化,一般的优化选项用-O2(gcc允许-g与-O2联用,这也是GNU软件包发布的默认选项),embedded可以考虑-Os。

注意:此处为O!(非0或小写的o,-o是指定可执行文件名)。
检验优化结果的方法:$ time ./prog

time测量指定程序的执行时间,结果由三部分组成:
    real : 进程总的执行时间, 它和系统负载有关(包括了进程调度,切换的时间)
    user: 被测量进程中用户指令的执行时间
    sys  : 被测量进程中内核代用户指令执行的时间

user和sys的和被称为CPU时间.

注意:对代码的优化可能会引发警告信息,移出警告的办法不是关闭优化,而是调整代码。

GNU binutils笔记

转载自: zzzppp.cublog.cn

 

GNU binutils是一组二进制工具集。包括:addr2line   ar   gprof   nm   objcopy   objdump   ranlib   size   strings   strip. 本文归纳他们的常用法。
ar


      ar用于建立、修改、提取档案文件(archive)。archive是一个包含多个被包含文件的单一文件(也称之为库文件),其结构保证了可以从中检索并得到原始的被包含文件(称之为archive中的member)。member的原始文件内容、模式(权限)、时间戳、所有着和组等属性都被保存在 archive中。member被提取后,他们的属性被恢复到初始状态。
    ar主要用于创建C库文件(关于.o目标文件的生成和共享库的详细介绍,参考gcc笔记)
创建静态库
    (1) 生成目标文件:  

$ gcc -Wall -c file1.c file2.c file3.c

    不用指定生成.o文件名(默认生成file1.o, file2.o, file3.o)。
    (2) 从.o目标文件创建静态连接库:

$ ar rv libNAME.a file1.o file2.o file3.o

    ar生成了libNAME.a库,并列出库中的文件。
r : 将flie1.o, file2,o, file3.o插入archive,如故原先archive中已经存在某文件,则先将该文件删除。
v : 显示ar操作的附加信息(如被处理的member文件名)
注: 对于BSD系统, 还需要在创建静态库之后创建索引: $ ranlib libNAME.a Linux中不需要这一步(运行它也是无害的).
创建动态库(利用gcc,未用ar)
(1) 生成目标文件

$ gcc -Wall -c -fpic file1.c file2.c file3.c

-fpic: 指定生成的.o目标文件可被重定址. pic是position idependent code的缩写: 位置无关代码.
(2)生成动态库文件

$ gcc -shared -o libNAME.so file1.o file2.o file3.o

一般地, 连接器使用main()函数作为程序入口. 但在动态共享库中没有这样的入口. 所以就要指定-shared选项来避免编译器显示出错信息.
实际上, 上述的两条命令可以合并为下面这条:

$ gcc -Wall -shared -fpic -o libNAME.so file1.c file2.c file3.c

此后,将main函数所在的程序与libNAME.so连接(注意库连接路径和头文件包含路径,以及连接顺序!参考gcc笔记
至此,与动态库连接的函数编译成了一个可执行文件。貌似成功了,但还差最后一步。如果直接运行该程序,会给出这样的错误信息:

error while loading shared libraries: libhello.so:
cannot open shared object file: No such file or directory

这是因为与动态库连接的程序在运行时,首先将该动态库加载到内存中,而gcc默认加载动态库文件所在目录为/usr/local/lib, /usr/lib。刚才的程序虽然能编译成功,但如果我们自己建立的动态库没有位于默认目录中,则执行时会应为无法找到它而失败。
解决办法:改变加载路径对应的环境变量,然后再执行。

export LD_LIBRARY_PATH=动态库所在目录:$LD_LIBRARY_PATH

查看archive内容

$ ar tv archiveNAME

t : 显示archive中member的内容,若不指定member,则列出所有。
v : 与t结合使用时,显示member的详细信息。
要想进了解ar的详细选项,参考ar的on-line manual
nm


      nm用来列出目标文件中的符号,可以帮助程序员定位和分析执行程序和目标文件中的符号信息和它的属性。
    如果没有目标文件作为参数传递给nm, nm假定目标文件为a.out.
    这里用一个简单的示例程序来介绍nm的用法:
main.c:

int main(int argc, char *argv[])
{
  hello();
  bye();
  return 0;
}

hello.c:  

void hello(void)
{
  printf("hello!\n");
}

bye.c:

void bye(void)
{
  printf("good bye!\n");
}

    运行下列命令:
$ gcc -Wall -c main.c hello.c bye.c
    gcc生成main.o, hello.o, bye.o三个目标文件(这里没有声明函数原型,加了-Wall,gcc会给出警告)
$ nm main.o hello.o bye.o
结果显示如下:  

main.o:
                 U bye
                 U hello
00000000 T main
hello.o:
00000000 T hello
                 U puts
bye.o:
00000000 T bye
                 U puts

    结合这些输出结果,以及程序代码,可以知道:
    对于main.o, bye和hello未被定义, main被定义了
    对于hello.o, hello被定义了, puts未被定义
    对于bye.o, bye被定义了,puts未被定义
几个值得注意的问题:
    (1)"目标文件"指.o文件, 库文件, 最终的可执行文件
    .o  : 编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义.
    (2)如果用nm查看可执行文件, 输出会比较多, 仔细研究输出, 可以对nm用法有更清醒的认识.
    (3)在上述hello.c, bye.c中, 调用的是printf(), 而nm输出中显示调用的是puts(), 说明最终程序实际调用的puts(), 如果令hello.c或bye.c中的printf()使用格式化输出,则nm显示调用printf(). ( 如: printf("%d", 1); )
    关于nm的参数选项,参考on-line manual
objcopy


      objcopy可以将一种格式的目标文件转化为另外一种格式的目标文件. 它使用GNU BFD库进行读/写目标文件.使用BFD, objcopy就能将原格式的目标文件转化为不同格式的目标文件.
    以我们在nm中使用的hello.o目标文件和hello可执行为例:

$ file hello.o hello

    file命令用来判别文件类型, 输出如下:
hello.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
hello:  ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), not stripped
    现在运行objcopy来改变hello的文件类型: 原先它是ELF格式的可执行程序, 现将它转换为srec格式. srec格式文件是Motolora S-Record格式的文件, 主要用来在主机和目标机之间传输数据.

$ objcopy -O srec hello hello_srec
$ file hello.o hello

    file命令结果: hello_srec: Motorola S-Record; binary data in text format
    注意objcopy的格式, "-O"指定输出文件类型; 输入文件名和输出文件名位于命令末尾. 关于objcopy命令的详细选项, 参考on-line manual
objdump


      objdump用来显示目标文件的信息. 可以通过选项控制显示那些特定信息. objdump一个最大的用处恐怕就是将C代码反汇编了. 在嵌入式软件开发过程中, 也可以用它查看执行文件或库文件的信息.
    下面我们用上文提到的hello可执行文件和hello_srec可执行文件为例, 介绍objdump的简单用法:

$ objdump -f hello hello_srec

输出如下:
hello:     file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482c0
hello_srec:     file format srec
architecture: UNKNOWN!, flags 0x00000000:
start address 0x00000000080482c0
-f : 显示目标文件的头文件概要信息.
生成反汇编代码:

$ objdump -d hello.o

显示如下:
hello.o:     file format elf32-i386
Disassembly of section .text:
00000000 <hello>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   83 ec 0c                sub    $0xc,%esp
   9:   68 00 00 00 00          push   $0x0
   e:   e8 fc ff ff ff          call   f <hello+0xf>
  13:   83 c4 10                add    $0x10,%esp
  16:   c9                      leave
  17:   c3                      ret
    -d : 显示目标文件中机器指令使用的汇编语言. 只反汇编那些应该含有指令机器码的节(显示.text段); 如果用-D, 则反汇编所有节的内容.
    关于objcopy命令的详细选项, 参考on-line manual
readelf


      readelf用来显示ELF格式目标文件的信息.可通过参数选项来控制显示哪些特定信息.(注意: readelf不支持显示archive文档, 也不支持64位的ELF文件).
    下面利用先前的hello可执行文件演示readelf的简单用法:

$ readelf -h hello

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                                           ELF32
  Data:                                            2's complement, little endian
  Version:                                        1 (current)
  OS/ABI:                                          UNIX - System V
  ABI Version:                                   0
  Type:                                              EXEC (Executable file)
  Machine:                                        Intel 80386
  Version:                                          0x1
  Entry point address:                       0x80482c0
  Start of program headers:              52 (bytes into file)
  Start of section headers:                 3848 (bytes into file)
  Flags:                                               0x0
  Size of this header:                          52 (bytes)
  Size of program headers:                32 (bytes)
  Number of program headers:          7
  Size of section headers:                  40 (bytes)
  Number of section headers:            34
  Section header string table index:   31
注意: readelf只能用于ELF格式目标文件, 且选项中至少要指定一个(除V, H外)的选项!
gprof


      gprof被用来测量程序的性能. 它记录每个函数被调用的次数以及相应的执行时间. 这样就能锁定程序执行时花费时间最多的部分, 对程序的优化就可集中于对它们的优化.
    用一个简单的数值计算程序来掩饰gprof的用法:
collatz.c:

#include <stdio.h>
/* Computes the length of Collatz sequences */
unsigned int step (unsigned int x)
{
     if (x % 2 == 0)
     {
      return (x / 2);
     }
     else
     {
      return (3 * x + 1);
     }
}
unsigned int nseq (unsigned int x0)
{
     unsigned int i = 1, x;
     if (x0 == 1 || x0 == 0)
      return i;
     x = step (x0);
     while (x != 1 && x != 0)
     {
      x = step (x);
      i++;
     }
     return i;
}
int main (void)
{
     unsigned int i, m = 0, im = 0;
     for (i = 1; i < 500000; i++)
     {
      unsigned int k = nseq (i);
      if (k > m)
      {
           m = k;
           im = i;
           printf ("sequence length = %u for %u\n", m, im);
      }
     }
     return 0;
}

    先将collatz.c编译成目标文件collatz.o, gcc通过 -pg选项来打开gprof支持:

$ gcc -Wall -c -pg collatz.c

$ gcc -Wall -pg -o collatz collatz.o

    注意:两条命令都要加 "-pg"选项。前一条命令生成collatz.o目标文件。后一条命令生成可执行文件,该可执行文件中包含了记录函数执行时间的指令。
    生成collatz可执行文件后,现执行它,结果与一般程序的执行无疑。但此时在PWD目录生成一个名为"gmon.out"的文件,gprof通过它来分析程序的执行。
    如果不现执行程序,而直接用gprof来分析它,会提示“gmon.out: No such file or directory”。
    gprof用法:

$ gprof ./collatz

关于gprof更多的描述,参考gprof的on-line manual

C语言出错信息速查

Ambiguous operators need parentheses
不明确的运算需要用括号括起
Ambiguous symbol ``xxx``
不明确的符号
Argument list syntax error
参数表语法错误
Array bounds missing
丢失数组界限符
Array size toolarge
数组尺寸太大
Bad character in paramenters
参数中有不适当的字符
Bad file name format in include directive
包含命令中文件名格式不正确
Bad ifdef directive synatax
编译预处理ifdef有语法错
Bad undef directive syntax
编译预处理undef有语法错
Bit field too large
位字段太长
Call of non-function
调用未定义的函数
Call to function with no prototype
调用函数时没有函数的说明
Cannot modify a const object
不允许修改常量对象
Case outside of switch
漏掉了case 语句
Case syntax error
Case 语法错误
Code has no effect
代码不可述不可能执行到
Compound statement missing{
分程序漏掉"{"
Conflicting type modifiers
不明确的类型说明符
Constant expression required
要求常量表达式
Constant out of range in comparison
在比较中常量超出范围
Conversion may lose significant digits
转换时会丢失意义的数字
Conversion of near pointer not allowed
不允许转换近指针
Could not find file ``xxx``
找不到XXX文件
Declaration missing ;
说明缺少";"
Declaration syntax error
说明中出现语法错误
Default outside of switch
Default 出现在switch语句之外
Define directive needs an identifier
定义编译预处理需要标识符
Division by zero
用零作除数
Do statement must have while
Do-while语句中缺少while部分
Enum syntax error
枚举类型语法错误
Enumeration constant syntax error
枚举常数语法错误
Error directive :xxx
错误的编译预处理命令
Error writing output file
写输出文件错误
Expression syntax error
表达式语法错误
Extra parameter in call
调用时出现多余错误
File name too long
文件名太长
Function call missing )
函数调用缺少右括号
Fuction definition out of place
函数定义位置错误
Fuction should return a value
函数必需返回一个值
Goto statement missing label
Goto语句没有标号
Hexadecimal or octal constant too large
16进制或8进制常数太大
Illegal character ``x``
非法字符x
Illegal initialization
非法的初始化
Illegal octal digit
非法的8进制数字
Illegal pointer subtraction
非法的指针相减
Illegal structure operation
非法的结构体操作
Illegal use of floating point
非法的浮点运算
Illegal use of pointer
指针使用非法
Improper use of a typedefsymbol
类型定义符号使用不恰当
In-line assembly not allowed
不允许使用行间汇编
Incompatible storage class
存储类别不相容
Incompatible type conversion
不相容的类型转换
Incorrect number format
错误的数据格式
Incorrect use of default
Default使用不当
Invalid indirection
无效的间接运算
Invalid pointer addition
指针相加无效
Irreducible expression tree
无法执行的表达式运算
Lvalue required
需要逻辑值0或非0值
Macro argument syntax error
宏参数语法错误
Macro expansion too long
宏的扩展以后太长
Mismatched number of parameters in definition
定义中参数个数不匹配
Misplaced break
此处不应出现break语句
Misplaced continue
此处不应出现continue语句
Misplaced decimal point
此处不应出现小数点
Misplaced elif directive
不应编译预处理elif
Misplaced else
此处不应出现else
Misplaced else directive
此处不应出现编译预处理else
Misplaced endif directive
此处不应出现编译预处理endif
Must be addressable
必须是可以编址的
Must take address of memory location
必须存储定位的地址
No declaration for function ``xxx``
没有函数xxx的说明
No stack
缺少堆栈
No type information
没有类型信息
Non-portable pointer assignment
不可移动的指针(地址常数)赋值
Non-portable pointer comparison
不可移动的指针(地址常数)比较
Non-portable pointer conversion
不可移动的指针(地址常数)转换
Not a valid expression format type
不合法的表达式格式
Not an allowed type
不允许使用的类型
Numeric constant too large
数值常太大
Out of memory
内存不够用
Parameter ``xxx`` is never used
能数xxx没有用到
Pointer required on left side of ->
符号->的左边必须是指针
Possible use of ``xxx`` before definition
在定义之前就使用了xxx(警告)
Possibly incorrect assignment
赋值可能不正确
Redeclaration of ``xxx``
重复定义了xxx
Redefinition of ``xxx`` is not identical
xxx的两次定义不一致
Register allocation failure
寄存器定址失败
Repeat count needs an lvalue
重复计数需要逻辑值
Size of structure or array not known
结构体或数给大小不确定
Statement missing ;
语句后缺少";"
Structure or union syntax error
结构体或联合体语法错误
Structure size too large
结构体尺寸太大
Sub scripting missing ]
下标缺少右方括号
Superfluous & with function or array
函数或数组中有多余的"&"
Suspicious pointer conversion
可疑的指针转换
Symbol limit exceeded
符号超限
Too few parameters in call
函数调用时的实参少于函数的参数不
Too many default cases
Default太多(switch语句中一个)
Too many error or warning messages
错误或警告信息太多
Too many type in declaration
说明中类型太多
Too much auto memory in function
函数用到的局部存储太多
Too much global data defined in file
文件中全局数据太多
Two consecutive dots
两个连续的句点
Type mismatch in parameter xxx
参数xxx类型不匹配
Type mismatch in redeclaration of ``xxx``
xxx重定义的类型不匹配
Unable to create output file ``xxx``
无法建立输出文件xxx
Unable to open include file ``xxx``
无法打开被包含的文件xxx
Unable to open input file ``xxx``
无法打开输入文件xxx
Undefined label ``xxx``
没有定义的标号xxx
Undefined structure ``xxx``
没有定义的结构xxx
Undefined symbol ``xxx``
没有定义的符号xxx
Unexpected end of file in comment started on line xxx
从xxx行开始的注解尚未结束文件不能结束
Unexpected end of file in conditional started on line xxx
从xxx 开始的条件语句尚未结束文件不能结束
Unknown assemble instruction
未知的汇编结构
Unknown option
未知的操作
Unknown preprocessor directive: ``xxx``
不认识的预处理命令xxx
Unreachable code
无路可达的代码
Unterminated string or character constant
字符串缺少引号
User break
用户强行中断了程序
Void functions may not return a value
Void类型的函数不应有返回值
Wrong number of arguments
调用函数的参数数目错
``xxx`` not an argument
xxx不是参数
``xxx`` not part of structure
xxx不是结构体的一部分
xxx statement missing (
xxx语句缺少左括号
xxx statement missing )
xxx语句缺少右括号
xxx statement missing ;
xxx缺少分号
xxx`` declared but never used
说明了xxx但没有使用
xxx`` is assigned a value which is never used
给xxx赋了值但未用过
Zero length structure
结构体的长度为零

给ECOS新手和想大致了解ecos的人!

eCos最大的特点是内核可配置。它出生于1997年,相对其他的系统来说是非常年轻的,但是也正是因为出身的晚,所以在设计理念上面是比较新颖的。其全部代码使用C++编写。
eCos可以说是嵌入式领域的一颗新星,全称是Embedded Configurable Operating System。绝大多数代码使用C++写作完成。最早是Cygnus公司开发(是不是想到Cygwin了?),不久被RedHat收购,现在RedHat 又放弃了RedHat项目,解雇了eCos的开发人员,将他踢到了Free Found Org(这是我坚决不用RedHat的原因,太功利了)。
eCos最大的特点是模块化,内核可配置。如果说嵌入式Linux太庞大了,那么eCos可能就能够满足要求。它是一个针对16位、32位和64位处理器的可移植开放源代码的嵌入式RTOS。和嵌入式Linux不同,它是由专门设计嵌入式系统的工作组设计的。ECOS具有相当丰富的特性和一个配置工具,后者能够让你选取你所需要的特性。Linux兼容的嵌入式系统在内核裁减后编译出来的二进制代码大小在500k字节以上,这还只包含最简单的内核模块,几乎没有加载任何其他的驱动与协议栈。
但是eCos最小版本只有几百个字节,一般,一个完整的网路应用,其二进制的代码也就100K字节左右。而且更为重要的是,eCos提供的Linux兼容的API能让开发人员轻松的将linux应用移植(这点和RTEMS很相似),与此同时,应用程序不用跑在Linux复杂的内核机制上(这套机制,对于大型服务器也许还凑合,但是对于短小精干的嵌入式应用,太浪费了),大大节省了你的晶振和RAM。
eCos 中字面上C(configurable) 表示的“高可配置性”。eCos 可以让开发者像在玩积木般地自由选择其执行期的元件,应用程序开发者可以针对自己的应用程序来设迟一个对其最小的RTOS环境,这跟以往应用程序就是跑在一个完整的RTOS上本质上不同,在嵌入式系统資源与内存寸土寸金的环境上,这样的开发方式是很重要的。在以往的嵌入式开发方式都是自己手工的将RTOS 作缩减,对经验不足或对该RTOS不夠熟悉的人将会花去许多时间,或是根本很难将RTOS拆开,但在eCos 上,由于设计之初就是朝向可设迟的原則,各种元件都遵守著模块化的开发方式,而应用程序开发者只要使用eCos 中的配置,即可轻松简单的对eCos 元件作量身打造,也不需对其內部实作有所了解即时RTOS的核心并提供标准系统API。
eCos 的核心支持一般OS 常見的项目如驱动程序(Device Driver)、内存管理(Memory managemant)、异常处理(exception handling)、中断处理(exception handling)、线程的支持(thread support)、计时器(Timer)、计数器(Counter),对于即时RTOS的支持如完全优先(full preemptability)、最小中断延迟(minimal interrupt latencies )、线程同步(synchronization primitive)、可自定的调度原则(schedule policies)。
此外也支持POSIX 等操作系统的标准API 及ANSI C 与常用的数学函数。支持常用的周边及通讯协议( networking stacks)支持以太网络卡,串口,USB slave等常用周边。并支持一般常用的通讯协议如IP、IPV6、ICMP、UDP、TCP、SNMP、HTTP、TFTP、FTP 等。网络设迟部分,可支持静态IP 与DHCP 。GDB支持可支持主控端使用GDB 远端透过串口或是以太网络对应用程序除错。
此外, eCos另一个优点是他支持非常多的平台和CPU,尤其是比较新的CPU比如ARM的各个系列,DSP(BlackFin)等。并且也支持很多硬件平台。目前支持的CPU包括: ARM, CalmRISC, FR-V, H8, IA32, M68K, Matsu****a AM3x, MIPS, NEC V8xx, PowerPC, SPARC, SuperH支持的硬件平台设备包括: Flash, Ethernet, 串口, USB, 时钟等。其已直接支持了时下绝大部分的硬件,可在eCos 官方网站上找到支持列表。具体的硬件支持情况可以参考http://ecos.sourceware.org/hardware.html,里面有长长的一个列表,大家可以根据自己的情况去看看。需要说明的是,这个硬件列表可能很久没有更新过了,最新的硬件列表可能需要访问开发者的邮件列表。
ECos的Licence:
eCos的专利受eCos license 所保护,这是一个GPL license 的修改版,其准许开发者在其上开发的应用程序(eCos 以外自行撰写的部分)可以不用跟著GPL 一起发布。应用程序开发者可免費的取得其完整的源码(buyout-free),并针对其作任意的修改与在其上开发自己的应用程序并发布,唯一的限制只是若有修改到eCos 本身,其需将修改的源码回报給eCos 开发小組。当开发者将其当为产品时,也不需支付版税(royalty-free)。可以看出,eCos的Licence比GPL要宽松。
eCos 上开发的应用程序架构图中File system 指的是对文件系统如ext2 等的支持,library 是上节所提包括POSIX,ANSI C 等的函数库。这张图,由上到下,表示从高层到底层的eCos架构。最底层的是我们的硬件,在硬件上面有HAL 与裝置驱动程序,而我们大部分会利用eCos 工具去设中间kernel、networking stack、library 层(OS层),只留下我们需要的部分。最上层的应用程序就是我们自行撰写的部分,通过中间OS 层的辅助来达成我们的目的。
我们可以看出,Redboot 是一个架构在eCos HAL 与Device Driver 上的一套应用程序。其中与硬件最关系密切的就是HAL,可以用“最接近硬件的软件”来形容,HAL 将所有与硬件相关的地方对外隱藏在里面。针对不同的硬件时,只需换掉HAL,换上针对新硬件而撰写的HAL 即可。

嵌入式操作系统uClinux和eCos的比较

摘要 uClinux和eCos操作系统是两种性能优良、源码公开且被广泛应用的免费嵌入式操作系统。本文通过对uclinux和eCos的对比,分析和总结了嵌入式操作系统应用中的若干重要问题,归纳出嵌入式系统开发中操作系统的选型依据。
关键词 嵌入式 操作系统 eC0s uClinux

1 两种开源嵌入式操作系统介绍
uClinux是一种优秀的嵌入式Linux版本。 uClinux是micro-Conrol-linux的缩写。与标准Linux相比,它集成了标准Linux操作系统的稳定性、强大网络功能和出色的文件系统等主要优点。但是由于没有MMU(内存管理单元),故其多任务的实现需要一定技巧。
    eCos(embedded Configurable operating system),即嵌入式可配置操作系统,是RedHat的产品,但eCos并不是Linux或Linux的派生。eCos弥补了Linux在嵌入式应用领域的不足,是一个源码开放的可配置、可移植、无版税、面向深嵌入式应用的实时操作系统。eCos的核心部分是由不同的组件组成的,包括内核、C语言库和底层运行包等。每个组件能提供大量的可配置选项,利用eCos提供的配置工具可以很方便地进行配置。通过不同的配置使得eCos能够满足不同的嵌入式应用。
    对于以上两种源码公开的实时操作系统,主要从以下几个方面进行比较。通过比较,能够为大家选择适合自己系统的RTOS提供参考。

2 基本操作性能的比较
2.1 应用程序的运算能力
在Linux 和uClinux操作系统启动的时候,都会有这样一句话——Calibrating delay 1oop..0k—xxx BogoMips,这一过程叫作BogoMips(读作bogumips)。Linus Torvalds引入BogoMips主要有两个目的:①给用户一个大概的系统运算能力的概念;②由于系统中有许多代码需要精确的软件延时,通过 BogoMips来获得软件延时每个周期消耗的时间。BogoMips的过程就是一个简单计数循环,看ls可以循环多少次,然后除以500000就得到了 BogoMips的数值。
    表1是分别在目标硬件平台上运行eCos和uClinux下的BogoMips应用程序得到的结果。我们使用了不同的测试条件,激活和非激活AT76C120的存储器缓冲控制器。

    从表1可知,打开缓冲存储器。对eCos的应用程序性能影响较uClinux的大;反之,关闭缓冲,eCos的应用程序的性能就下降很多。

2.2 存储器访问能力
采用一种同时能够测试缓冲控制器和标准存储器访问函数的测试方法来测试存储器访问能力。在这里,选用田纳西大学的Philip J.Mucci等人提出的CacheBench方法。其工作原理是,重复顺序读/写一定长度的存储器块的数据,记录重复n次所用的时问,用总的读/写数据除以耗时,得到读/写每一字节所用的时间;同时,通过调整数据块的长度和不同的读写方法(使用标准函数或者使用直接代码读写),获得不同条件对存储器读/写的影响。
    在实验中,对于每一种测试模式使用4种不同的块长度(分别为256、512、1024、2048字节),以观察不同的抉长度对存储器访问性能的影响。表2 是实验的结果:横向比较,eCos的存储器访问性能从总体上都优于uClinux;纵向比较,5种模式下性能关系大致为缓冲读>缓冲读,改写/写 >缓冲写>mcmset>mcmcpy。在同一种测试模式下,对于缓冲读,越大的块长度,其表现的存储器访问性能越好;而其他模式下,存储器访问性能基本与块长度无关。

    基于以上结果的分析如下:①造成eCos存储器访问能力优于uClinux的原因是,eCos的应用程序获得的处理器时间较长;②造成读缓冲模式下,存储器访问性能随块长度增长而变好,而其他模式下不变的原因是,与AT76C120的缓冲控制器的回写模式有关。由于AT76C120的缓冲控制器采用了直接回写的缓冲回写模式,缓冲控制器对存储器写操作没有任何缓冲作用,因此当处理器写存储器时基本不会享受到由缓冲控制器带来的好处,相当于直接访问外部存储器。

2.3 驱动程序性能测试
为了测试系统的驱动程序性能,选择CF卡驱动程序作为测试对象。我们的测试方法简单,就是在应用程序中打开一个大文件(10MB),然后调用fread读文件,每次读512字节到缓冲中,直至将文件读完。
    表3是测试结果:uClinux的性能优于eCos。这主要是由于uClinux的块驱动有一个叫集簇的功能,它可以将对块设备的多个请求归并在一起执行,这样对于像磁盘这样反应较慢的设备可以提高整体的读/写速度。

3 综合应用性能比较
    我们知道,一个图像压缩和解压缩的程序往往需要大块的存储器访问操作、密集的数学运算和大量的磁盘访问。由于现在手持的嵌入式设备大多需要有这方面的应用需求,因此一个图像压缩和解压缩的应用程序既符合理论研究的要求,又符合实际应用的需求。为此我们选择gif图片的编解码的程序作为综合性能测试的测试程序。测试结果如表4所列。

    我们看到,eCos和uClinux解码速度都很低,主要是因为完全使用了软件解压缩;而且由于AT76C120的图像显示格式是YCrCb的,而 giflib的解压缩结果是RGB的,因此必须使用浮点运算将RGB的数据转换到YCrCb。AT76C120的ARM7TDMI不支持浮点指令,因此不得不使用软件仿真来完成浮点运算,这其中大部分时间被用在了从RGB到YCrCb的转换上。测试结果基本与前面基本操作系统测试的结果是一致的—— eCos在整体上是优于uClinux的。

4 可移植性
eCos的系统一J移植性应该明显比uClinux的好。在eCos系统中,每一个硬件平台都用一个单独的目录存放针对这一硬件平台的硬件抽象层的代码和配置信息,较容易让用户理解。而uClinux的硬件抽象层的代码分布在好几个目录中,而且各个平台的代码混合在一个源文件中,通过#ifdef+#end的方式来选择不同的硬件平台的代码。另外,eCos在移植时所要更改的源代码文件数少于uClinux。
    可移植性不应仅仅是操作系统的移植,还应该包含应用程序的移植性。程序的可移植性,是由两方面决定的。首先,应用程序必须被编写得可以移植。关于这方面, A.Dolenc,A.Lemmke和D.Keppel在其Notes On WritingPortable Programs In C一文中给出了很好的解释。其次是嵌入式操作系统提供较丰富的系统函数和标准函数库。一个系统提供的函数库越丰富,则越多的应用程序不用进行较大的更改就能直接在其上运行。在标准函数方面,eCos只提供了较为简单的C标准函数库和IEEE浮点运算数学库,uClinux则提供了,与Linux下的 glibc相兼容的函数库,而glibc是大部分开放源代码项目的构建基础。由此可以看出,在应用程序的可移植性上,uClinux的兼容性更好。

5 开发模式和开发难易度
eCos的开发模式是一套更接近传统单片机的开发模式(如应用程序静态链接),uClinux的开发模式则更接近Linux的开发模式。因此可以预见,eCos更受一批从8位单片机系统开发转到32位嵌入式系统开发设计人员的欢迎.而uClinux更受熟悉Linux的设计人员的青睐。

6 总 结
通过以上比较可知,由于eCos从一开始设汁时就是以嵌入式系统为目标的,因此在性能上,有较大优势;反之,uClinux则是由Linux进化而来的,因此在以速度和优化为主题的嵌入式系统环境中,并不占优势。但是由于有Linux的强大后盾,其功能的强大和兼容性是非常突出的。如果应用程序是从其他系统中移植过来的,或者开发人员有Linux的背景,或者开发成本占总成本的比例较高,则uClinux比较适合;反之,eCos比较适合。

——信息来源:杭州启扬智能科技有限公司

14 mai

SubVersion Log & Stat 统计工具 - StatSVN

最新的STATSVN可以从其官网上下载: http://www.statsvn.org

 

StatSVN能够从Subversion版本库中取得信息,然后生成描述项目开发的各种表格和图表。

比如:

代码行数的时间线;

针对每个开发者的代码行数;

开发者的活跃程度;

开发者最近所提交的;

文件数量;

平均文件大小;

最大文件;

哪个文件是修改最多次数的;

目录大小;

带有文件数量和代码行数的Repository tree。

StatSVN当前版本能够生成一组包括表格与图表的静态HTML文档。

StatSVN使用JFreeChart来生成chart。

简易使用流程是:
1:checkout 一份干净的工程
svn checkout –username yourname –password yourpasswd “svn://size/repos/src” c:/checkout

2:生成log
svn log –username yourname –password yourpasswd -v –xml c:/checkout > c:/checkout/src.log

3:生成统计结果
java -jar statsvn.jar -title yourtitle -username yourname  -password yourpasswd  -output-dir c:/report -include **/*.java;**/*.jsp;**/*.js;**/*.css;**/*.c;**/*.cpp;**/*.cs;**/*.vm;**/*.h;**/*.hpp;**/*.asp;**/*.xml;**/*.pas;**/*.dfm;**/*.php;**/*.pl;**/*.py -exclude **/*.gif;**/*.jpg;**/*.png;**/*.bmp;**/*.zip;**/*.rar -threads 50 c:/checkout/src.log c:/checkout

注意:

由于SVN的diff的计算算法问题,如果第一次执行statsvn可能会耗费很长时间的,我自己的一个20w行左右的项目,第一运行就花掉了1个多小时,所以请耐心等待,以后再执行就很快了。

附上几张统计结果的图片:

Lines of Code

image

image

image

image

2 avril

交叉编译场景分析(arm-linux)--序

转载自:http://blog.csdn.net/absurd

 

去年花了一个多月时间,为arm-linux平台编译程序库,其中包括zlib、readline、ncurses、tslib、TinyX、libpng、jpeg、cairo、pango、glib、atk、gtk+、match系列、SCIM、GPE系列。由于之前没有经验,走了不少弯路,虽然从中学到了一些知识,大部分时间都浪费了。最近一些同事和朋友常问我一些关于交叉编译的问题,我想有必要总结一下,和大家分享一些心得。

什么是交叉编译呢?在回答这个问题前,我们先解释两个概念:

主 机:运行编译过程的计算机。

目标机:运行编译结果(可执行文件)的计算机。

一般情况下,主机和目标机是同一类型的计算机,这就是正常的编译,没有什么好说的。所谓交叉编译就是在主机上为目标机编译,比如在PC上编译,然后在手机上运行,这种编译就叫交叉编译。

交叉编译需要交叉编译器,不同的目标机(主要是看芯片类型)需要不同的交叉编译器,比如我们这里要介绍的arm-linux交叉编译,所用的交叉编译器就是arm-linux-gcc系列。

构建一个交叉编译器(toolchain),说简单也简单,说复杂也复杂。原理上很简单,实际情况常常比较复杂,原因是编译器一直处于开发状态,你要了解某个版本的稳定性,要去找patch。有时候还要看你的运气好不好,折腾一个星期才搞定也是很常见的。

网上已经有不少已经构建好了的交叉编译器(toolchain),除非你想了解如何构建交叉编译器,否则直接下载一个来用是比较明智的做法。这里不打算介绍如何构建交叉编译器的知识。

在做交叉编译前,你最好了解autoconf系统工具的用法,遇到问题时,可以快速定位。先找一本autoconf的书看看,可以说是磨刀不识砍柴功,否则后面会浪费更多的时间。

31 mars

Bugzilla 安装错误 (Undefined subroutine &DBD::mysql::db::_login called at lib/i386-linux-thread-multi/DBD/mysql.pm line 142, line 228)

在安装Bugzilla的过程中,安装好了必须的perl module后 用checksetup.pl检查了一直pending在connect mysql的连接中。Google Serach后发现这个的错误发生情况还不少,但是没有一个适合我用的解决方案。所以经过摸索,写下帮助,或许能减少后来人,走一些弯路:

环境:

OS: CentOS 5.1

Bugzilla: 3.1.3

MySQL: 5.0.22

Perl: 5.8.8

 

前面的安装步骤如下:

Step 1: Mysql

#groupadd mysql
#useradd mysql
# yum install mysql
# yum install mysql-devel
# yum install mysql-server
#mysql_install_db
#chown -R root:mysql /usr/local/mysql
#chown -R mysql:mysql /usr/local/mysql/var
#chgrp -R mysql /usr/local/mysql
#cp support-files/my-medium.cnf /etc/my.cnf
启动服务方法
#mysqld_safe --user=mysql &
停止服务
#mysqladmin shutdown

为mysql添加用户bugs

mysql> GRANT SELECT,INSERT,UPDATE,DELETE,INDEX, ALTER,CREATE,DROP,REFERENCES ON bugs.* TO bugs@localhost IDENTIFIED BY 'bugs_password';

mysql> FLUSH PRIVILEGES;

mysql> create database bugs DEFAULT CHARACTER SET utf8;

 

Step 2: Apache

# yum install httpd

修改apache配置/etc/httpd/conf/httpd.conf添加如下内容:

Alias /bugzilla/ "/var/www/bugzilla/"

<Directory "/var/www/bugzilla">
      AddHandler cgi-script .cgi
      Options +Indexes +ExecCGI
      DirectoryIndex index.cgi
      AllowOverride Limit
      Order allow,deny
      Allow from all
</Directory>

 

Step 3:bugzilla

解压bugzilla的tar包到/var/www/buzilla下

利用bugzilla的脚本#/usr/bin/perl install-module.pl --all 可以自动下载所需的perl module。

修改localconfig
server's host: "localhost"
database name: "bugs"
MySQL username: "bugs"
Password for the "bugs" MySQL account above

[root@localhost bugzilla-3.1.3]# ./checksetup.pl
* This is Bugzilla 3.1.3 on perl 5.8.8
* Running on Linux 2.6.18-53.el5 #1 SMP Mon Nov 12 02:22:48 EST 2007

Checking perl modules...
Checking for                 CGI (v2.93)   ok: found v3.15
Checking for            TimeDate (v2.21)   ok: found v2.22
Checking for           PathTools (v0.84)   ok: found v3.12
Checking for                 DBI (v1.41)   ok: found v1.604
Checking for    Template-Toolkit (v2.15)   ok: found v2.19
Checking for          Email-Send (v2.00)   ok: found v2.192
Checking for Email-MIME-Modifier (any)     ok: found v1.442

Checking available perl DBD modules...
Checking for              DBD-Pg (v1.45)    not found
Checking for           DBD-mysql (v4.00)   ok: found v4.006
Checking for          DBD-Oracle (v1.19)    not found

The following Perl modules are optional:
Checking for                  GD (v1.20)    not found
Checking for               Chart (v1.0)     not found
Checking for         Template-GD (any)      not found
Checking for          GDTextUtil (any)      not found
Checking for             GDGraph (any)      not found
Checking for            XML-Twig (any)      not found
Checking for          MIME-tools (v5.406)  ok: found v5.426
Checking for         libwww-perl (any)     ok: found v2.033
Checking for         PatchReader (v0.9.4)  ok: found v0.9.5
Checking for          PerlMagick (any)      not found
Checking for           perl-ldap (any)     ok: found v0.34
Checking for          RadiusPerl (any)     ok: found v0.13
Checking for           SOAP-Lite (any)     ok: found v0.71
Checking for         HTML-Parser (v3.40)   ok: found v3.55
Checking for       HTML-Scrubber (any)     ok: found v0.08
Checking for Email-MIME-Attachment-Stripper (any)     ok: found v1.314
Checking for         Email-Reply (any)     ok: found v1.202
Checking for            mod_perl (v1.999022)  not found
Checking for                 CGI (v3.11)   ok: found v3.15

* NOTE: You must run any commands listed below as root.

**********************************************************************
* OPTIONAL MODULES                                                   *
**********************************************************************
* Certain Perl modules are not required by Bugzilla, but by          *
* installing the latest version you gain access to additional        *
* features.                                                          *
*                                                                    *
* The optional modules you do not have installed are listed below,   *
* with the name of the feature they enable. If you want to install   *
* one of these modules, just run the appropriate command in the      *
* "COMMANDS TO INSTALL" section.                                     *
**********************************************************************

***********************************************************************
* MODULE NAME * ENABLES FEATURE(S)                                    *
***********************************************************************
*          GD * Graphical Reports, New Charts, Old Charts             *
*       Chart * New Charts, Old Charts                                *
* Template-GD * Graphical Reports                                     *
*  GDTextUtil * Graphical Reports                                     *
*     GDGraph * Graphical Reports                                     *
*    XML-Twig * Move Bugs Between Installations                       *
*  PerlMagick * Optionally Convert BMP Attachments to PNGs            *
*    mod_perl * mod_perl                                              *
***********************************************************************
COMMANDS TO INSTALL:

             GD: /usr/bin/perl install-module.pl GD
          Chart: /usr/bin/perl install-module.pl Chart::Base
    Template-GD: /usr/bin/perl install-module.pl Template::Plugin::GD::Image
     GDTextUtil: /usr/bin/perl install-module.pl GD::Text
        GDGraph: /usr/bin/perl install-module.pl GD::Graph
       XML-Twig: /usr/bin/perl install-module.pl XML::Twig
     PerlMagick: /usr/bin/perl install-module.pl Image::Magick
       mod_perl: /usr/bin/perl install-module.pl mod_perl2

To attempt an automatic install of every required and optional module
with one command, do:

  /usr/bin/perl install-module.pl --all

Reading ./localconfig...

OPTIONAL NOTE: If you want to be able to use the 'difference between two
patches' feature of Bugzilla (which requires the PatchReader Perl module
as well), you should install patchutils from:

    http://cyberelk.net/tim/patchutils/

Checking for           DBD-mysql (v4.00)   ok: found v4.006
Had to create DBD::mysql::dr::imp_data_size unexpectedly at lib/i386-linux-thread-multi/DBI.pm line 1211, <DATA> line 228.
Use of uninitialized value in subroutine entry at lib/i386-linux-thread-multi/DBI.pm line 1211, <DATA> line 228.
Had to create DBD::mysql::db::imp_data_size unexpectedly at lib/i386-linux-thread-multi/DBI.pm line 1241, <DATA> line 228.
Use of uninitialized value in subroutine entry at lib/i386-linux-thread-multi/DBI.pm line 1241, <DATA> line 228.
There was an error connecting to MySQL:

    Undefined subroutine &DBD::mysql::db::_login called at lib/i386-linux-thread-multi/DBD/mysql.pm line 142, <DATA> line 228.

This might have several reasons:

* MySQL is not running.
* MySQL is running, but there is a problem either in the
  server configuration or the database access rights. Read the Bugzilla
  Guide in the doc directory. The section about database configuration
  should help.
* Your password for the 'bugs' user, specified in $db_pass, is
  incorrect, in './localconfig'.
* There is a subtle problem with Perl, DBI, or MySQL. Make
  sure all settings in './localconfig' are correct. If all else fails, set
  '$db_check' to 0.

这个错误是由于DBD::mysql在编译过程中出错导致的,需要重新编译DBD::mysql,另外需要用最新编译生成的mysql.so替换bugzilla目录下的同名文件,再次运行./checksetup.pl就可以看到让你配置管理员账号的部分了。

 

#cp /DBD-mysql-4.006/blib/arch/auto/DBD/mysql/mysql.so /bugzilla-3.1.3/lib/i386-linux-thread-multi/auto/DBD/mysql/mysql.so

EMail 联络我

你是第web page hit counter个访问者

28 mars

安装DBD::mysql的错误解决

在安装Bugzilla过程中遇到一些关于Perl方面的问题,总结了一些经验如下:

===================
make test output :
===================
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/00base.............install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/00base.t line 38
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 4-5
Failed 2/5 tests, 60.00% okay
t/10dsnlist..........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/10dsnlist.t line 45
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-9
Failed 9/9 tests, 0.00% okay
t/20createdrop.......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/20createdrop.t line 45
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-5
Failed 5/5 tests, 0.00% okay
t/30insertfetch......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/30insertfetch.t line 48
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-11
Failed 11/11 tests, 0.00% okay
t/35limit............install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/35limit.t line 50
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-113
Failed 113/113 tests, 0.00% okay
t/35prepare..........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/35prepare.t line 37
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-30
Failed 30/30 tests, 0.00% okay
t/40bindparam........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 5) line 3
Compilation failed in require at (eval 5) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40bindparam.t line 64
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-28
Failed 28/28 tests, 0.00% okay
t/40bindparam2.......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 5) line 3
Compilation failed in require at (eval 5) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40bindparam2.t line 64
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-13
Failed 13/13 tests, 0.00% okay
t/40blobs............install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40blobs.t line 64
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-11
Failed 11/11 tests, 0.00% okay
t/40listfields.......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40listfields.t line 57
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-18
Failed 18/18 tests, 0.00% okay
t/40nulls............install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40nulls.t line 50
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-11
Failed 11/11 tests, 0.00% okay
t/40numrows..........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/40numrows.t line 59
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-25
Failed 25/25 tests, 0.00% okay
t/41bindparam........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/41bindparam.t line 37
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-11
Failed 11/11 tests, 0.00% okay
t/41blobs_prepare....install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/41blobs_prepare.t line 71
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-24
Failed 24/24 tests, 0.00% okay
t/42bindparam........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/42bindparam.t line 37
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-11
Failed 11/11 tests, 0.00% okay
t/50chopblanks.......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/50chopblanks.t line 57
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-35
Failed 35/35 tests, 0.00% okay
t/50commit...........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/50commit.t line 64
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-30
Failed 30/30 tests, 0.00% okay
t/60leaks............skipped
all skipped: $ENV{SLOW_TESTS} is not set or Proc::ProcessTable not installed
t/dbdadmin...........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/dbdadmin.t line 74
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-21
Failed 21/21 tests, 0.00% okay
t/insertid...........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/insertid.t line 13
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-12
Failed 12/12 tests, 0.00% okay
t/param_values.......install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/param_values.t line 16
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-8
Failed 8/8 tests, 0.00% okay
t/prepare_noerror....install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/prepare_noerror.t line 22
dubious
Test returned status 2 (wstat 512, 0x200)
t/texecute...........install_driver(mysql) failed: Can't load '/usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/home/uscannenberg/.cpan/build/DBD-mysql-3.0007/blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: mysql_stmt_free_result at /usr/local/perl/lib/5.8.7/i686-linux/DynaLoader.pm line 230.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at t/texecute.t line 17
dubious
Test returned status 2 (wstat 512, 0x200)
DIED. FAILED tests 1-9
Failed 9/9 tests, 0.00% okay
Failed Test Stat Wstat Total Fail Failed List of Failed
-------------------------------------------------------------------------------
t/00base.t 2 512 5 4 80.00% 4-5
t/10dsnlist.t 2 512 9 18 200.00% 1-9
t/20createdrop.t 2 512 5 10 200.00% 1-5
t/30insertfetch.t 2 512 11 22 200.00% 1-11
t/35limit.t 2 512 113 226 200.00% 1-113
t/35prepare.t 2 512 30 60 200.00% 1-30
t/40bindparam.t 2 512 28 56 200.00% 1-28
t/40bindparam2.t 2 512 13 26 200.00% 1-13
t/40blobs.t 2 512 11 22 200.00% 1-11
t/40listfields.t 2 512 18 36 200.00% 1-18
t/40nulls.t 2 512 11 22 200.00% 1-11
t/40numrows.t 2 512 25 50 200.00% 1-25
t/41bindparam.t 2 512 11 22 200.00% 1-11
t/41blobs_prepare.t 2 512 24 48 200.00% 1-24
t/42bindparam.t 2 512 11 22 200.00% 1-11
t/50chopblanks.t 2 512 35 70 200.00% 1-35
t/50commit.t 2 512 30 60 200.00% 1-30
t/dbdadmin.t 2 512 21 42 200.00% 1-21
t/insertid.t 2 512 12 24 200.00% 1-12
t/param_values.t 2 512 8 16 200.00% 1-8
t/prepare_noerror.t 2 512 ?? ?? % ??
t/texecute.t 2 512 9 18 200.00% 1-9
1 test skipped.
Failed 22/23 test scripts, 4.35% okay. 437/440 subtests failed, 0.68% okay.
make: *** [test_dynamic] Error 2

 

===============

      Solution

===============

由于DBD::mysql的安装需要基于Mysql的安装,所以需要确保mysql_config中的show的路径都能在系统中找到。如果是tar.gz编译安装的mysql需要记住--prefix的路径;如果是RPM安装的话需要确认是否安装了mysql,mysql-server,mysql-devel,因为它们都会在DBD::mysql的安装中用到。

 

===============

    Example

===============

[root@localhost DBD-mysql-4.006]# perl Makefile.PL
I will use the following settings for compiling and testing:

  cflags        (mysql_config) = -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fwrapv
  embedded      (mysql_config) =
  libs          (mysql_config) = -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto
  mysql_config  (guessed     ) = mysql_config
  nocatchstderr (default     ) = 0
  nofoundrows   (default     ) = 0
  ssl           (guessed     ) = 1
  testdb        (default     ) = test
  testhost      (default     ) =
  testpassword  (default     ) =
  testsocket    (default     ) =
  testuser      (default     ) =

To change these settings, see 'perl Makefile.PL --help' and
'perldoc INSTALL'.

Using DBI 1.52 (for perl 5.008008 on i386-linux-thread-multi) installed in /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/auto/DBI/
Writing Makefile for DBD::mysql
[root@localhost DBD-mysql-4.006]# make
gcc -c  -I/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/auto/DBI -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fwrapv -DDBD_MYSQL_WITH_SSL -DDBD_MYSQL_INSERT_ID_IS_GOOD -g  -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables   -DVERSION=\"4.006\" -DXS_VERSION=\"4.006\" -fPIC "-I/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE"   dbdimp.c
dbdimp.c: In function 鈖arse_params?
dbdimp.c:464: warning: implicit declaration of function 鈖arse_number?
dbdimp.c: In function 鈊bd_discon_all?
dbdimp.c:1946: warning: unused variable 鈏mp_xxh?
gcc -c  -I/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/auto/DBI -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fwrapv -DDBD_MYSQL_WITH_SSL -DDBD_MYSQL_INSERT_ID_IS_GOOD -g  -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables   -DVERSION=\"4.006\" -DXS_VERSION=\"4.006\" -fPIC "-I/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE"   mysql.c
mysql.xs: In function 釾S_DBD__mysql__db_do?
mysql.xs:239: warning: unused variable 鈙tatement_ptr?
mysql.xs: In function 釾S_DBD__mysql__st_more_results?
mysql.xs:550: warning: implicit declaration of function 鈓ysql_st_next_results?
mysql.xs:549: warning: unused variable 鈘etval?
mysql.xs: In function 釾S_DBD__mysql__GetInfo_dbd_mysql_get_info?
mysql.xs:686: warning: implicit declaration of function 鈏s_prefix?
Running Mkbootstrap for DBD::mysql ()
chmod 644 mysql.bs
rm -f blib/arch/auto/DBD/mysql/mysql.so
/usr/bin/perl myld gcc  -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -L/usr/local/lib dbdimp.o mysql.o  -o blib/arch/auto/DBD/mysql/mysql.so  \
           -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto       \
chmod 755 blib/arch/auto/DBD/mysql/mysql.so
cp mysql.bs blib/arch/auto/DBD/mysql/mysql.bs
chmod 644 blib/arch/auto/DBD/mysql/mysql.bs
Manifying blib/man3/DBD::mysql.3pm
Manifying blib/man3/DBD::mysql::INSTALL.3pm
Manifying blib/man3/Bundle::DBD::mysql.3pm

 

[root@localhost DBD-mysql-4.006]# make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/00base..............ok                                                    
t/10connect...........ok                                                    
t/20createdrop........ok                                                    
t/25lockunlock........ok                                                    
t/30insertfetch.......ok                                                    
t/35limit.............ok                                                    
t/35prepare...........ok                                                    
t/40bindparam.........ok                                                    
t/40bindparam2........ok                                                    
t/40blobs.............ok                                                    
t/40catalog...........ok                                                    
t/40keyinfo...........ok                                                    
t/40listfields........ok                                                    
t/40nulls.............ok                                                    
t/40numrows...........ok                                                    
t/40server_prepare....ok                                                    
t/40types.............ok                                                    
t/41bindparam.........ok                                                    
t/41blobs_prepare.....ok                                                    
t/42bindparam.........ok                                                    
t/50chopblanks........ok                                                    
t/50commit............ok                                                    
t/60leaks.............skipped
        all skipped: $ENV{SLOW_TESTS} is not set
t/65types.............ok                                                    
t/70takeimp...........skipped
        all skipped: test feature not implemented
t/75supported_sql.....ok                                                    
t/80procs.............ok                                                    
t/insertid............ok                                                    
t/multi_statement.....ok                                                    
t/param_values........ok                                                    
t/prepare_noerror.....ok                                                    
t/texecute............ok                                                    
t/utf8................ok                                                    
t/warnings............ok                                                    
All tests successful, 2 tests skipped.
Files=34, Tests=656,  7 wallclock secs ( 0.75 cusr +  4.69 csys =  5.44 CPU)


[root@localhost DBD-mysql-4.006]# make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Writing /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/DBD/mysql/.packlist
Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod

EMail 联络我

你是第web page hit counter个访问者

25 mars

配置开发支持高并发TCP连接的Linux应用程序全攻略

转自:http://blog.tom.com/blogger2007/article/1263.html
1、修改用户进程可打开文件数限制
   在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:
   [speng@as4 ~]$ ulimit -n
   1024
   这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。
   对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。
   修改上述限制的最简单的办法就是使用ulimit命令:
   [speng@as4 ~]$ ulimit -n <file_num>
   上述命令中,在<file_num>中指定要设置的单一进程允许打开的最大文件数。如果系统回显类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是因为在<file_num>中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。
   第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:
   speng soft nofile 10240
   speng hard nofile 10240
   其中speng指定了要修改哪个用户的打开文件数限制,可用'*'号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。
   第二步,修改/etc/pam.d/login文件,在文件中添加如下行:
   session required /lib/security/pam_limits.so
   这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。
   第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:
   [speng@as4 ~]$ cat /proc/sys/fs/file-max
   12158
   这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:
   echo 22158 > /proc/sys/fs/file-max
   这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。
   完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的最大文件数限制设为指定的数值。如果重启后用 ulimit-n命令查看用户可打开文件数限制仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit -n命令已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的最大数限制时,新修改的值只能小于或等于上次 ulimit-n设置的值,因此想用此命令增大这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了ulimit-n限制了用户可同时打开的最大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。
   通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。
2、修改网络内核对TCP连接的有关限制
   在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。
   第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can't assign requestedaddress”。同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为“Can't assignrequested address”。有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:
   static int tcp_v4_hash_connect(struct sock *sk)
   请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文件中的如下函数中设置:
   void __init tcp_init(void)
   内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。
   第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
   net.ipv4.ip_local_port_range = 1024 65000
   这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。
   第二步,执行sysctl命令:
   [speng@as4 ~]$ sysctl -p
   如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。
   第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对最大跟踪的TCP连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpdump工具监视网络,也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对最大跟踪的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:
   第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
   net.ipv4.ip_conntrack_max = 10240
   这表明将系统对最大跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量小,以节省对内核内存的占用。
   第二步,执行sysctl命令:
   [speng@as4 ~]$ sysctl -p
   如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。
3、使用支持高并发网络I/O的编程技术
   在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。
   可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O。在高TCP并发的情形下,如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用同步 I/O是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O。非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO。
   从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用“轮询”机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分TCP连接上的I/O出现“饥饿”现象。而如果使用epoll或AIO,则没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个 I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
   综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。
Date: 2007-01-31
OS: Red Hat Enterprise Linux AS release 4 (kernel version 2.6.9-5.EL)

EMail 联络我

你是第web page hit counter个访问者

18 mars

音乐文件格式:MP2 MP3 RM AAC AAC+ AC-3 AC-3+ WMA

目前,音乐文件常见的网络上流传模式主要是MP2 MP3 RM AAC AAC+ AC-3 AC-3+ WMA WAV这几种,其他几个还好,就是对AAC AC3系列一直以来不是很清楚,趁工作需要,恶补一下。

 

AAC
AAC实际上是高级音频编码的缩写,目前只有苹果的硬盘式MP3支持这一种格式。AAC是由Fraunhofer IIS-A、杜比和AT&T共同开发的一种音频格式,它是MPEG-2规范的一部分。AAC所采用的运算法则与MP3的运算法则有所不同,AAC 通过结合其他的功能来提高编码效率。AAC的音频算法在压缩能力上远远超过了以前的一些压缩算法(比如MP3等)。它还同时支持多达48个音轨、15个低频音轨、更多种采样率和比特率、多种语言的兼容能力、更高的解码效率。总之,AAC可以在比MP3文件缩小30%的前提下提供更好的音质。


AAC+
它是MPEG-2 AAC和SBR(Spectral Band Replication)带宽延伸修订版的技术组合。HE-AAC不是要取代AAC,而是要延伸MPEG-4的语音品质,能够以更低的速率传输(32 kbps)。而且,HE-AAC译码器可以对AAC解码。
若要产生48 kbps的HE-AAC立体声,HE-AAC编码器会产生两种信号:一个是42 kbps的MPEG AAC信号,另一个是6 kbps的SBR信号。然后,此SBR信号置于MPEG AAC的辅助字段内(该字段是MPEG-4定义的)。最后,构成一个完整48 kbps的MPEG-4 HE-AAC串流。SBR代表高频的成份,而AAC代表低频的成份。HE-AAC译码器使用AAC和SBR信号,产生全频信号;而AAC译码器只使用 AAC信号,亦即,只有低频成份被它解码。
HE-AAC能传输48 kbps的CD立体声,或128 kbps、5.1声道的“环场声”(surround sound)。这样的效率,使它适用于Internet传输,或移动数字广播。不过,由于HE-AAC的高延迟特性,使它不适用于双向的通信应用。
AAC技术已经被使用于2G和2.5手机中。而AAC+、EAAC+则被使用于3G手机中。

 

AC-3 
1994年,日本先锋公司宣布与美国杜比实验室合作研制成功一种崭新的环绕声制式,并命名为“杜比AC-3”(Dolby Surround Audio Coding-3)。1997年初,杜比实验室正式将“杜比AC-3环绕声”改为“杜比数码环绕声”(Dolby Surround Digital),我们常称为Dolby Digital。
杜比AC-3提供的环绕声系统由5个全频域声道和1个超低音声道组成,被称为5.1声道。5个声道包括左前、中央、右前、左后、右后。低音声道主要提供一些额外的低音信息,使一些场景,如爆炸、撞击等声音效果更好。6个声道的信息在制作和还原过程中全部数字化,信息损失很少,全频段的细节十分丰富。(这个是看Divx高清晰电影中最常见的声音模式之一了)

 

AC-3+

AC3的升级版本:AC3+。这种全新的压缩技术不但升华了AC3强劲压缩率和高质音声效果,而且AC3音声压缩技术是索尼专为便携式随身听而研制出来的,如使用Walkman产品并以AC3+形式播放音频文件,只需耗用很少的电源。以索尼 Network Walkman产品为例,在使用了低功耗的AC3+编解码芯片之后,实现了长达50个小时以上的连续播放时间。从而让真正热爱音乐的随身听用户能够享受到近乎完美的天籁之音
索尼在数字音乐技术上的孜孜以求,无疑为人类欣赏高品质的数字音乐开辟了道路。随着科技的发展,人们的观念从简单的听音乐将发展为最方便地听最优质的音乐,试想一下,如果两个随身听播放器有同样的存储空间,使用AC3+技术你可以欣赏到更高质量、更多数量的音乐,还不用担心经常要充电换电池,那么我们还有什么犹豫

 

WMA

WMA的全称是Windows Media Audio,是微软力推的一种音频格式。WMA格式是以减少数据流量但保持音质的方法来达到更高的压缩率目的,其压缩率一般可以达到1:18,生成的文件大小只有相应MP3文件的一半。这对只装配32M的机型来说是相当重要的,支持了WMA和RA格式,意味着32M的空间在无形中扩大了2倍。此外,WMA 还可以通过DRM(Digital Rights Management)方案加入防止拷贝,或者加入限制播放时间和播放次数,甚至是播放机器的限制,可有力地防止盗版。

 

MP3

MP3的全称是Moving Picture Experts Group Audio Layer III。简单的说,MP3就是一种音频压缩技术,由于这种压缩方式的全称叫MPEG Audio Layer3,所以人们把它简称为MP3。MP3是利用 MPEG Audio Layer3 的技术,将音乐以1:10 甚至 1:12 的压缩率,压缩成容量较小的file,换句话说,能够在音质丢失很小的情况下把文件压缩到更小的程度。而且还非常好的保持了原来的音质。正是因为MP3体积小,音质高的特点使得MP3格式几乎成为网上音乐的代名词。每分钟音乐的MP3格式只有1MB左右大小,这样每首歌的大小只有3-4兆字节。使用MP3 播放器对MP3文件进行实时的解压缩(解码),这样,高品质的MP3音乐就播放出来了。

 

MP2

MPEG 2Layer是MP3前的技术,目前很少能有用了。

 

RM

Real Networks公司所制定的音频视频压缩规范,主要包含RealAudio、RealVideo和RealFlash三部分。网络上常见的RM格式通常为Real Media,它的特点是文件小,但画质仍能保持的相对良好,适合用于在线播放。用户可以使用RealPlayer或RealOne Player对符合RealMedia技术规范的网络音频/视频资源进行实况转播并且RealMedia可以根据不同的网络传输速率制定出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放。
这种格式的另一个特点是用户使用RealPlayer或RealOne Player播放器可以在不下载音频/视频内容的条件下实现在线播放。另外,RM作为目前主流网络视频格式,它还可以通过其Real Server服务器将其它格式的视频转换成RM视频并由Real Server服务器负责对外发布和播放。

 

EMail 联络我

你是第web page hit counter个访问者

15 mars

美六电影公司状告迅雷侵权

出来混,迟早都要还的!
看来近期那些影音公司终于对那些P2P网站发起维权手段了。一直以来,讯雷,VeryCD等一大批视频资源下载的站点迅速起来,而且还是似乎拿到了不少VC,终于还是会被自身能否存活下去的最重要因素--版权问题,击溃。

美国电影协会六大电影制片公司联手将中国知名的P2P下载服务商迅雷公司告上了上海浦东新区法院,要求其立即停止对《霹雳娇娃2》、《蜘蛛侠3》等32部电影的侵权,并赔偿各类经济损失共计人民币700万元(约140万新元)。

  据《南方都市报》报道,状告迅雷侵权的六家电影公司分别为华纳兄弟、迪士尼公司、哥伦比亚电影工业公司、派拉蒙影片公司、环球城市制片公司、二十世纪福克斯。

   在诉状上,六家电影公司称,2007年迅雷通过其经营的网站向公众提供《绝密飞行》、《霹雳娇娃2》、《神奇遥控器》等多部影片的介绍、预览、搜索和下 载链接服务。电影公司曾要求其在24小时内删除侵权文件,屏蔽或断开链接,但至今仍未实行。电影公司还发现有些影片在该网站中能“在线观看”。

  关于盗版问题,迅雷公司发言人张玉波曾对媒体表示,他们只是提供了一个下载的工具而并没有在网络上提供影片,那些影视资源和文件都是公司的用户和合作伙伴上传的,并不存在盗版问题。

  稍早前,迅雷网链接了可以免费下载的电影《伤城》。以人民币60万元买下影片网络传播权和收益权的上海优度公司将要求迅雷赔偿其经济损失15万元。今年2月,上海浦东新区法院判处迅雷赔偿15万元。

EMail 联络我

你是第web page hit counter个访问者

13 mars

Subversion与CVS的对比——功能性对比

一、Subversion包含绝大部分CVS功能

Subversion 作为CVS 的重写版和改进版,其目标就是作为一个更好的版本控制软件,取代目前流行的CVS。Subversion 的主要开发人员都是业界知名的CVS 专家。Subversion支持绝大部分的CVS 功能/命令;Subversion 的命令风格和界面也与CVS 非常接近。当然,不同的地方正是对CVS 的改进。

二、全局性的版本编号

一个新的版本,并得到一个自增量的版本号N+1,该版本号并不针对某个特定的文件,而是全局性的、针对整个版本库的。因此,我们可以将Subversion 的版本库看作是一个文件系统或文件目录树的数组。

从技术的角度来说,在Subversion 中,“文件foo.c 的第5 版本”这个说法是错误的;正确的说法应该是:”文件foo.c 在版本库被修改了5 次,即执行5 次commit 后是什么样子?”。显然,在Subversion 中,版本库被修改5 次后foo.c 的内容,和被修改了6 次后foo.c 的内容很可能完全一样,因为版本库的第6 次修改很可能只修改了版本库的其他部分,而并没有对foo.c 的进行修改。相反,在CVS 中,文件foo.c 的第1.1 版本和第1.2 版本总是不同的。

Subversion 的全局性版本编号为Subversion 带来了诸多的优势:如对目录或文件执行拷贝,无论涉及多少文件,Subversion 不需要对单个文件依次执行拷贝命令,仅仅需要建立一个指向相应的全局版本号的一个指针即可。

三、目录的版本控制

CVS 只能对文件进行版本控制,不能对目录进行版本控制,因此CVS 没有任何关于文件“移动”(move) 操作的概念。当人为进行文件移动操作时,CVS 只能注意到,一个文件在一个位置被删除了,而在一个新位置创建了另外一个文件。由于它不会连接两个操作,因此也很容易使文件历史轨迹丢失。设置 CVS 存储库时,必须非常谨慎地为每个文件选择准确的位置,因为在设置之后,几乎就要一直使用这个位置了。

同样由于CVS 不记录目录的版本历史,CVS 不支持对文件的“重命名”(rename),人为的对文件进行重命名会使得命名前后的文件失去历史联系,而记录历史本来是版本管理的主要目的。

还有,CVS 不支持对文件的“拷贝”(copy),人为的拷贝对CVS 而言,只能看到新的文件的增加,而不能记录拷贝源文件和目标文件之间的联系。

综上所述,缺乏对文件“移动”、“重命名”、“拷贝”的支持的根源在于CVS 不能记录目录的版本历史,而这些操作在当前的软件开发过程中经常发生,这正是Subversion被开发并取代CVS 的主要原因之一。

Subversion 将目录作为一类特殊的文件来处理(事实上,从文件系统的角度来看,目录确实是一类特殊的文件,当目录中的子目录/文件被删除、重命名、或新的子目录/文件 被创建时,目录的内容将发生改变)。因此,Subversion 象记录普通文件的修改历史一样记录对目录的修改历史,当发生文件/目录的移动、重命名或拷贝操作时,Subversion 能够准确记录操作前后的历史联系。同样,象对文件的不同历史版本进行比较一样,Subversion支持对目录的不同历史版本的比较,清晰展现目录的变化 历史。


四、原子性提交

从使用者的角度来看,CVS 和Subversion 都支持对多个文件修改的批量提交,但二者在实现方式上存在本质的区别。

CVS 采用线性、串行的批量提交,即依次地,一个接一个地执行提交,每成功提交一个文件,该文件的一个新的版本即被记录到版本库中,提交时用户提供的日志信息被重复地存储到每一个被修改的文件的版本历史中。

CVS 串行批量提交模式的弊端在于 - 当任何原因造成批量操作的中断时(典型原因包括:网络中断、客户端死机等),版本库往往处于一个不一致的状态:原本应该全部入库的文件只有一部分入库,很 有可能版本库中的最新版本不能顺利编译,更为严重的是,随着其他的用户执行cvs update 操作,该不一致性将迅速在开发团队中扩散,从而严重影响团队的开发效率,并存在质量隐患。另外,假如该批量提交的中断没有被及时发现,开发团队往往要花更 多的时间进行软件调试和排错。

 

CVS 即使在批量提交不发生中断时也会造成不一致:假设用户A 启动一个需要较长时间才能完成的批量提交;与此同时,用户B 执行cvs update 操作。此时,用户B 很有可能得到一个不一致的更新,即用户B 通过“更新”操作,得到用户A 的部分修改文件。


Subversion 彻底消除了CVS 的以上弊端。无论批量提交包含多少文件修改,只有当全部文件修改都成功入库,该提交才变得有效,才对其他用户可见;否则,无论任何原因造成中断, Subversion 都会自动执行“回滚”(rollback)操作。换一个说法,Subversion 保证所有的修改要么全部入库生效,要么一个也不入库,即对版本库不作任何的修改。这就是Subversion 的原子性提交(atomic commit)。

由于Subversion 的原子性提交特性和全局版本编号方式,当提交成功完成时,一个唯一的、新的全局版本编号产生,而提交时用户提供的日志信息与该新的版本编号关联,只进行一次存储(区别于CVS 的按文件重复存储)。

 

五、支持变更集概念

由于Subversion 的所有提交是原子性的,每次成功提交形成的唯一的全局版本号对应此次批量提交的所有文件修改,也就是说,一个Subversion 版本号其实对应了一个逻辑上的变更集(change set),该变更集可能对应于对一个BUG 的修复,或者对应于对一个已有功能的改进,或者对应于一个新功能的实现。可以说,变更集是一个软件开发活动的逻辑结果,该变更集可以通过其对应的版本号在 软件开发的其他过程中(如软件合并/集成过程,软件发布管理,变更管理系统,缺陷追踪系统)被引用。因此,Subversion 将版本管理从单纯的、单个的文件修改的层次通过逻辑上的抽象,上升到更便于理解和交流的开发活动的层次。


六、差异化的二进制文件处理

由于历史原因,CVS 主要是为早期的程序员设计的,CVS 能够有效处理文本文件(或ASCII文件,源代码文件),可以对文本文件进行差异化的存储、 新旧版本的比较,文件合并等;但对于二进制文件,CVS 则明显力不从心。在CVS 的版本库中,对于二进制文件的历史版本,CVS 唯一能做的就是对不同的版本进行独立的、冗余的存储,哪怕版本之间其实只存在微小的差异。举例而言,一个10M 的二进制文件(照片、图形文件、机械设计文件、电子设计文件)假如每周修改一次,无论每次修改的大小,一年下来,仅该文件就要消耗500M 以上的存储空间。而且,客户端每次获取该文件的新版本都要消耗10M 的网络流量。

对于目前的开发团队,无论是软件开发,Web 站点的开发,手机等电子产品的研发,需要进行版本管理的不仅是源代码等文本文件,还需要管理需求文档、设计文档、测试文档、用户手册,图形图像文件,机械/电子设计文件等诸多的二进制文件,CVS 显然不是一个好的选择。


与CVS 不同,Subversion 采用统一的二进制差异算法(binary differencing algorithm),即对文本文件和二进制文件采用相同的差异比较算法,并以相同的方式在版本库中进行存储:每次提交后版本库中只存储相对于先前版本的 差异,从而可以节省大量的存储空间。


该二进制差异算法不仅应用在版本的存储上,更为重要的是,Subversion 对二进制文件与文本文件一视同仁,当客户端需要获取新的版本时(如执行svn update),在网络上只有版本的差异被传输,从而大大减少对网络带宽的消耗。更多细节参见“七、双向的差异化-压缩网络传输”。

 

七、 双向的差异化-压缩网络传输

如上所述,CVS 对二进制文件不能进行有效的差异化处理。对于文本文件,CVS 仅仅支持单向的差异化传输:从CVS 服务器到客户端的传输是差异化的,即执行cvs update 时,只有差异的部分从服务器传输到客户端;而当执行cvs commit 时,无论代码变化多少,CVS 都需要从客户端向服务器完整传输被修改文件的全部内容,不能只传输差异。

相反,无论是文本文件还是二进制文件,Subversion 都进行双向的差异化传输,并且差异化内容还要进行压缩/解压缩的过程:在服务器端获 取差异显而易见,与CVS 类似;Subversion 在客户端获取差异的秘密在于 — Subversion 在客户端的工作拷贝中隐含了每个文件的一个“只读的、干净的”副本(该副本隐藏在隐含目录.svn 里,通常不可见,该副本还有更多的妙用,参见“十二、更多的本地/离线操作”),通过比较用户在客户端的修改和该隐含的副本,Subversion 获取需要真正传送到服务器的差异,并对差异进行压缩后才进行网络传输。

对CVS 而言,操作的成本(网络带宽消耗是最大的操作成本)与被修改的文件的大小成比例,而与修改本身的大小无关;对Subversion 而言,操作成本只与修改本身的大小成比例,而与被修改的文件的大小无关。因此,与CVS 相比,Subversion 消耗更少的网络带宽(以客户端的存储空间换取更少的带宽消耗在目前的计算环境下应该是个相当不错的选择!)。Subversion 更加适合基于互联网(或广域网)进行协作开发的地理上分布的团队 — 版本服务器集中、单一;客户端广泛分布。


八、高效、快捷创建分支和基线

CVS 和Subversion 都支持分支(branch)和基线(tag),通过分支与合并,可以有效支持大项目的并行开发模式;通过基线管理,可以准确标识一组文件的版本,有效进行软件发布管理和必要时的历史回溯。

但CVS 和Subversion 在实现分支和基线的方式上存在很大的不同。CVS 在创建分支的时候,需要对所有进行分支的文件进行依次的操作,因此分支的建立成本(主要是建立分支所需的时间,或消耗的计算资源)与参与分支的文件数量成 比例,项目越大,版本库越大,文件越多,分支的建立成本越高;基线(tag)的建立与此类似。

Subversion 的分支和基线是通过执行“拷贝”来建立的:回想一下在没有引入版本管理工具的时候我们是如何进行所谓的“分支”和“基线”管理的?答案显然是“拷贝” — 我们通过“拷贝”或“备份”来建立基线;同样,为支持多个开发人员可以同时进行开发,我们为每个开发人员创建一份“拷贝”。由此看来, Subversion 通过“拷贝”来建立分支和基线显得非常自然,有点“返朴归真”的意思。

由于Subversion 的全局版本号特性,Subversion 中分支或基线的创建过程,或Subversion中的“拷贝”过程,真正的操作是在版本库中创建一个到某一全局版本号的指针(pointer),不再需要 针对众多的单个文件依次执行操作。因此,该操作的成本为一个很小的常数,与项目大小,版本库大小,文件数目的多少无关;并且,分支或基线的建立不需要进行 版本的冗余存储,新建立的分支或基线基本不占用版本库空间,分支的后续存储空间的开销也只与修改的大小有关。


九、集成Apache Web Server,提供更多的特性

Subversion 通过与Apache Web Server 的集成,可以提供基于http/https 协议的版本库访问机制,从而支持Subversion 跨越防火墙的安全访问。 除此以外,Subversion 还可以利用更多的Apache 特性,包括但不限于:Apache 丰富的用户认证机制(包括通过LDAP服务器如Windows Active Directory 服务器的用户认证),基于目录路径的精细粒度的访问控制,对传输的网络流量进行压缩/解压缩,浏览版本库目录结构等等。

 

十、支持WebDAV

WebDAV(Web-based Distributed Authoring and Versioning)是一种基于 HTTP 1.1 协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD 等几个HTTP 标准方法以外添加了一些新的方法,使应用程序可直接对Web Server 直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。

Microsoft windows2000/XP 及IE, Office 还有Adobe/MicroMedia 的DW 等都支持WebDAV,这又大大增强了Web 应用的价值,以及效能。对于需要大量发布内容的用户而言,应用WebDAV 可以降低对CMS 系统的依赖,而且能够更自由的进行创作。上传、下载变得轻松自如。

Subversion 通过与Apache Web Server 的集成,支持WebDAV 协议,使得业务用户(business users)或非技术用户在不安装任何版本管理客户端的情况下轻松访问Subversion 版本库,不改变业务用户已有使用习惯,支持分布的业务用户对文档的评审、修改并实现版本控制,真正将软件开发的生命周期从开发/技术团队扩展到项目的全部干系人(stakeholder),避免通过电子邮件传递文档的混乱与无序、通过Windows 操作系统共享造成的安全漏洞、病毒攻击、历史版本被覆盖或丢失、审计困难等诸多典型问题。


十一、更好的冲突标识与处理


CVS 和Subversion 都支持通过分支与合并进行并行开发,并可以自动检测到合并时的冲突(conflicts),并在合并结果中以<<<<<< … >>>>>>标识合并的冲突部分。

在CVS 中,经常会出现由于用户的疏忽(如,没有注意到冲突,或没有完全处理好冲突)而将仍然带有<<<<<< … >>>>>>冲突标识符号的文件直接进行提交(commit),从而在版本库中产生垃圾版本。

Subversion 有效解决了CVS 的以上问题:Subversion 记录并保持文件的冲突状态,只有当用户明确执行svn resolved 命令后,该冲突状态标识才被复位,该文件才能被提交,从而大大减少了将仍然带有<<<<<< … >>>>>>冲突标识符号的文件直接进行提交的可能性。

十二、 更多的本地/离线操作

众所周知,CVS 客户端的工作拷贝中包含了一个隐含目录CVS,该目录中记录了客户端需要的一些管理信息;与此类似,Subversion 的客户端工作拷贝中也包含了一个隐含目录.svn,该目录中同样记录了客户端需要的一些管理信息,如版本库URL,当前访问版本号等。

与CVS 不同的是,Subversion 的.svn 目录中还包含了工作拷贝中每一个文件的一个“只读的、干净的”副本。正是由于该副本的存在,使得Subversion 与CVS 相比,可以执行更多的本地/离线操作,即某些操作不需要访问版本库服务器,因此不需要存在从客户端到服务器的网络链接,当然也不消耗任何网络带宽,这进一步增强了Subversion 对广域网的友好支持。

Subversion 的以下命令可以进行离线操作:
svn status - 显示工作拷贝上的本地修改概况;
svn diff -显示工作拷贝上的本地修改细节,比较修改前后的内容;
svn revert - 撤销工作拷贝上的本地修改;

十三、 对符号链接进行版本管理

在Unix 文件系统中,符号链接(symbolic links,包括硬链接和软链接)是一种重要的文件系统元素。CVS 不能对符号链接进行版本管理;Subversion 则可以对符号链接进行版本管理。

十四、 元数据管理

与CVS 相比,Subversion 增加了元数据(metadata)管理机制。即可以对版本库中的文件或目录附加任意的“属性”(property),并记录属性的变化历史,也就是对元数 据进行版本管理。一个Subversion 属性是一个“属性名称/属性值”的二元组,如“BugNumber= 100”就是一个属性,可以将该属性附加到版本N 上,以说明版本N 改正了编号为100的BUG。

Subversion 元数据的目的是提供附件的信息以满足流程或过程自动化的需要,以增强Subversion 的管理能力和自动化程度。Subversion 自身就通过“属性”来存储一些特殊的信息。一个使用Subversion 元数据的例子:可以在一些批处理的脚本程序或Subversion的钩子程序(hooks)中创建、访问、修改“属性”元数据来满足流程自动化的要求。

EMail 联络我

你是第web page hit counter个访问者

4 mars

别了,ZyXEL!别了,ZyXELer!

ZyXEL的各位同事:

 

         本人自从2005年的愚人节进入公司正式报到至今,已经3个年头过去了,凑巧了离开合勤的日子又是那么好记,学习雷锋的日子。

         感谢3年来能有机会和众位相处,共努力,共奋斗,共甘苦,共欢乐。也相当荣幸能结识这么多朋友在这短短的几年时间里,这将是我从合勤带走的最大的财富。

         感谢ZyXEL,感谢SW2,感谢CMS,感谢Vantage Access Team Members(现在的,曾经的,离职的),感谢ACS,感谢TR069 。。。。。。

 

         留下个人的一些联系方式:

         msn:

         email:

         blog: http://wekeywu.spaces.live.com

         RSS: http://wekeywu.spaces.live.com/feed.rss

         手机: 13656***184 (1-2个月不会更换,因为里面还有好几百余额未用完,如果被打爆了就只能更换了,所以也期待着提前换卡,欢迎大家骚扰!更换卡后MSNSMS通知)

 

Best Regards

Wekey Wu

2 juillet

再向美国行

6月23日出发,途经旧金山,洛杉矶,波士顿,经过近30小时的跋涉,在美国北部小镇Durham呆了一周,然后原路返回,目前在享受加州阳光(实际上是被加州阳光洒的皮肤发红),先一些照片,日志后续补发。

7 juin

温州的隔离政策

最近在网络中看到一个开放城市的封闭政策,感觉十分的诧异。那就为向来民营经济闻名全国的温州地区,实行了一个比较“落后”的封闭政策--也就是驱赶那些暂住在温州,没有当地户口,并有案底的外地人离开温州。

回想一下,温州经济的起步,很大得益于改革开放后,精明勤劳的温州人,走南闯北,可以说温州商贩的足迹遍及神州大陆,甚至海外也有不少温州商人,那么为何思想外向的温州人,居然制定出如此的“闭关自守”的隔离政策?

我想官方可能出发点是,是否最新一系列社会案件中,发现了一些外籍的、有案底的外地人比例比较高。可是即使如此也不能依次为由,牵连众多在温州的外地人阿!

另外,国家一直在喊的一个口号--户口制度改革,看起来也是非执行不可,一直以来,以国家大、地缘辽阔、人口众多为目前户口制度的借口,可是长年累月积累下来的社会问题越来越突出:农村和城市的落差、农民工在城市的福利待遇、小孩子的入学、医疗、乃至每年春运……等等这些,都或多或少由于从封建社会一直以留下来的户口制度在作祟。

如果,以后无所谓暂住证,无所谓农村户口、城市户口,无所谓户籍,那么国家将来的人才流动,社会稳定,人民的生活待遇,或许都能像更好的方向发展。

4 juin

最近Google的品质又有提升

看不懂标题的话,请在google搜索引擎中输入"个人空间 MSN"或者"MSN 个人空间"。

其实,记得从05年在MSN Space开博以来,一直到06年初,这2个关键字搜索的,我的博客基本上都在前几位,最好的时候,甚至连“个人空间”的关键字首页上也能看到。不过,06年后半年,一段时间里面博客的更新有所懈怠,所以Google的品质有所下降,不过最近看到统计资料显示来自Google的连接又有提升的趋势,自己尝试一下,还真是又提升了。

看来,Google也是一个负责的“监工者”。勤劳一些,品质就提升一些。

3 juin

摩托罗拉 (Moto) A1200R

很早就计划换一个手机了,可是一直没有找到合适的理由。也没有在眼花缭乱的众多品牌中,看上中意的款式。
上周末,在陪老婆购物的同时,老婆为了掩饰她自己的购物的“内疚”--已经刷了不少的Money,在边上好几次鼓动我买新手机,本来看中了的Nokia的5300,不过自从在《爱情呼叫转移》中看到黄圣依也是用的这款,我就把她定位为女式手机,显然就不适合了。但是,老婆看的很中意。也差一点就在无锡的国网手机店把她买下来了。

http://img2.zol.com.cn/product/8/432/ceM5rMhlmPCng.jpg
犹豫一下,总觉得只看一家,就买下来,万一价格不合适,不是很亏。就又逛了几家手机店,结果在第三家的时候,那个柜台小伙,看我只是问完价格后没有多少表示,实际上我们是觉得他的报价,还不如第一家的实惠,结果他大力推介差不多价格的三星一款类似手机,并拿Nokia的直接作比较。本来对三星手机是一点兴趣也没有的了,因为知道三星的水货到处都是,起码可以便宜一半的价格都可以拿到,何必买柜台的货。但是,却在柜台小伙的再三揭露Nokia的不足之后,对5300的兴趣可以说全部打消了。

所以,已经打消了升级手机的念头之后,又去逛了新世界百货。好在老婆比较体谅我的微薄薪水,还好没有在那里看中什么咚咚,因为我看那里衣服的起价都是4位数。hoho

不过,逛到4楼,本来是为了看看宏图三胞的本本价格,也好琢磨一下,6月份去美国到底买个什么本本回来,主要是想多赚一些差价。结果,宏图三胞的本本不多,顺便倒是又逛那里的手机柜台。自从办了信用卡以后,还一直没有机会尝试一下分期刷卡,看到宏图三胞就是招商的分期商家之一,心里已经是痒痒的了。

最后看到了已经买下来的这款Moto A1200r。具体的这款手机的性能和一个星期以来的使用效果,后续再报道。总体感觉这款手机已经从5000附近的价位下落到现在2000多,基本上还算可以接受。而且从外表看到的除了内存小了一些以外,也还算符合我的需求。

http://img.pconline.com.cn/images/product/1317/131716/mobile_moto_a1200_1l_m.jpg

附上younet的资料:
v 规格参数
网络频率:GSM/GPRS;850/900/1800/1900MHz
可选颜色:毅黑、逸白、醇红
尺寸/体积:95.7×51.7×21.5mm
重 量 :122 克
屏幕参数:26万色TFT彩色屏幕;240×320像素,2.4英寸;
操作系统:Linux
处理器:Intel® XScale 312MHz
通话时间:270-420 分钟
待机时间:160-200 小时
WAP上网:支持飞笺
上市时间:2006年02月
标准配置:锂电池(850mAh),旅行充电器,根数据线,一个立体声耳机,一根手写笔,一个手机套,一个腰夹,两张CD光盘,一张128M闪存卡
参考报价:  2388元

v 基本功能
『时钟』『内置振动』『录音』『MP3铃声』
『情景模式』『待机图片』『触摸屏』
8 可选铃声:短信铃声也继续支持用户自定义,存储卡上的音乐能够直接调用设置为铃声使用
8 和弦铃声: 40 和弦;支持40 Poly MIDI, MP3, WAV, AMR, WMA, AAC+ 格式
8 加密保护:语音密码锁
8 图形菜单:提供了屏幕亮度的调整,支持主题元素的下载和切换,能够调节三种不同状态的文字大小
8 手写输入:新一代手写技术,在手写状态下写入拼音,无需切换至拼音输入平台,即可获得相应的备选汉字,真正实现了手写汉字与手写拼音输入的无缝切换

v 通信功能
『内置天线』『中文输入』『中文短信』『EMS短信』
『话机通讯录』『通话记录』『EFR STK服务』
8 多媒体短信:支持多媒体彩信(MMS)
8 电子名片:名片扫描功能,A1200独特名片识别功能,只需使用内置数码相机及微距功能直接拍摄名片,手机即能将名片信息识别成文字后存入电话号码本
8 免提通话:高清晰免提扬声器

v 多媒体娱乐
『下载图铃游戏』『实时流媒体播放』

8 内置游戏: 4 个
8 内存容量: 11MB
8 多媒体卡扩展:最大支持1GB Micro-SD(TF)卡,不支持热插拔
8 Java扩展:MIDP 2.0
8 摄像头:内置
  摄像头像素:200万像素;手动微距调节
  传感器类型:CMOS
  照片分辨率:最大支持拍摄1600×1200分辨率的照片
  拍摄模式:支持夜景拍摄,提供了普通、阳光、灯光、荧光的白平衡调整
  照片特效:在色彩特效方面则提供了黑白、褐色、曝光、负片的选择
  视频拍摄:有声视频拍摄;支持有声视频的3GP格式录像
  视频分辨率:最大能够拍摄分辨率为176×144像素的视频片段,拍摄的时间仅受存储卡的剩余空间限制,录像同样能够进行与拍照一样的参数设置
8 图像编辑器:内置了一个图像编辑器,能够对图片进行边框、图像、文字的添加,旋转以及大小、亮度、对比度、锐度、颜色等等多方面的调整,弥补了拍摄功能的种种不足
8 视频播放:内置real Player多媒体播放器,支持的格式也同样为以往的MP3、WMA、RealAudio、RMVB、3GP、MPEG4、MIDI、WAV、AAC和AMR等,支持全屏以及后台播放
8 MP3播放器: 内置 ;支持 MP3,MP4, AAC+ 等多种格式
8 收音机: 内置;内置FM调频收音机
8 电子书:支持Word,Excel,Powerpoint 文件浏览

v 网络与数据传输
8 WAP浏览器:WAP 2.0
8 WWW浏览器:WML, xHTML, HTML (Opera7)
8 蓝牙接口: 内置;支持A2DP蓝牙立体声,支持蓝牙1.2的传输标准,支持蓝牙打印,蓝牙智能语音拨号
8 数据线接口:标准的USB数据接线接口
8 E-Mail:支持POP3, IMAP4, SMTP

v 个人助理
『闹钟』『日历』『计算器』『记事本』
『日程表』


8 电子字典:光盘预置中英文金山词霸电子词典

v 更多信息
8GPRS Class 10
8全透明的浅灰色翻盖,黑色磨砂软胶覆盖的外壳表层,转轴之处采用了电镀表层金属的技术制造
8翻盖扬声器设计
8多媒体个人信息管理
8中国移动定制手机
8电话会议功能(可支持七人同时通话)
8在无须开盖的情况下依然可以轻松完成阅读来信、回复消息(只能回复预存范本短信)、播放MP3、切换来电提示模式和拍照等诸多操作
8全新智能自动语音识别,语音命令,语音密码锁
8屏幕高亮功能,长按“通话记录”键启动高亮功能,可在阳光下清晰阅读
8支持在线音乐购买、下载,支持数字版权保护(OMA DRM1.0)
8另外有A1200r版本:增加挂绳孔;增加蓝牙打印功能;增加在线音乐下载功能;增加对数字版权音乐播放的支持;增强了音乐均衡器
81200软件版本:59P
81200R软件版本:25P




12 mai

股歌

股歌顾名思义乃是号召大家共同进入股市,在股市遨游时互相激励的歌曲。

最近网上流行一个特殊版本,虽然有“猥亵”国歌的嫌疑,不过好在目前还有没有法律限制这样一条,如果那天真有这个条款,本人郑重声明,此股歌乃是转载,非本人创作。:-) (转载时也请注明此条)

"起来,
还没开户的人们,
把你们的资金全部投入诱人的股市,
中华民族到了最疯狂的时刻,
每个人都激情地发出买入的吼声!
快涨、快涨、快涨!
我们万众一心,
怀暴富的梦想,
前进!
前进!
前进!
进!
进!"

EMail 联络我

你是第web page hit counter个访问者