Doc freebsd
来自 ChinaUnix Wiki
自由文档
给后来者:用FREEBSD作开发的一些实现方式
Version: 0.8.3
作者: gnuisv@hotmail.com
Article Opition
FREEBSD是现代UNIX的分支之一,系统稳定可靠、源码结构清晰、发展强劲。在FREEBSD上做开发,则直接基于一个稳定、先进的平台,拥有了运行环境的企业级的支持。可以在任务繁重的情况下,支撑应用的平滑、稳定的运行,支撑重要的企业计算功能。
* FREEBSD作开发中,总是存在很多的误区和不清晰的地方,本文进行一些经验的讲述。
* 开发中存在的很多的结构性和细节的问题,进行了备忘性的注释。
* 一般开发的有趣的问题,本文试图进行一些抛砖引玉的回答。
* 本文还拥有更多的内容,需要注意新版本的更新。
关于本自由文档
本文介绍
本文概括了FREEBSD作为开发平台的一些一般的作法或者选择。在本文中,关注的是项目工程和管理上的问题,并且涉及的是基础性而非技术性的问题。
作者开发FREEBSD具有了一段时间,并且拥有一定的经验,这些经验不一定具有普遍的意义。但是,作者愿意写出来,是为了给后来者作为一个参考,并且希望读者能够看到弯路并且规避这些问题。
这篇文档作为一个自由文档,或者是一个自由文档工程,将总是处于测试和发展的阶段。读者需要关注版本的更新,获得更正和加入更多的信息。希望对本文档提出意见和看法。
关于阅读本文档的声明:本文档是自由文档,属于FSF自由软件基金会之GNU工程自由文档工程GDL许可证的限制。本文的所有的内容、信息、数据都属于免责的范围,并且作者不承担任何所谓使用本文档所带来的任何损失、错误。作者不承担因为本文的疏漏、失误、错误带来的任何影响及损失,并且不承担通知版本升级的责任,请读者遵照执行。
Copyrigh 2002 GDL gnuisv@hotmail.com
有任何疑问,请访问本文作者的网站: http://people.freebsdchina.org/million
“中国人再也不能停留在给Mirc写bot的水平上了”
---网客留言
Warning:
警告:
1. LICENSE: BSD License
1、许可证:BSD许可
2、NOTICE: Under Freebsd/Linux, this document maybe including unreadable and blank area
2、注意:本文章使用中文,可能在freebsd/linux下有乱码和空白
背景:Background
做了一段时间的FREEBSD的开发工作,以FREEBSD为开发平台和开发对象都有。拥有了一些经验和弯路,一并写出,希望大家有所获益。
主要内容: Overview
简要介绍FREEBSD系统的一些开发经验和设计实现模式,希望有所反馈。
如何参与发展本文档? Join us
根据BSD许可证,您可以自由的修改和发布本文档,也欢迎将意见传递给lwen@freebsdchina.org
发展计划:To-Do List:
1、以几个实际的项目为例,实例说明FREEBSD环境下开发的技术细节和解决方式。
2、编写本文章的续节:代码分析,编写代码,代码排错的一般过程。
让我们从零开始…
A、开发环境 1、FREEBSD平台
1.1 FreeBSD 最小安装 + 所有的源码
1.2 安装ports目录环境
1.3 选择sh作为基本的shell,这样符合GNU编码标准
2、准备开发环境
2.1 cvsd;
2.2 apache;
2.3 postgresql;
2.4 autoconf;
2.5 automake;
2.6 emacs / vi.
3、启动开发环境,设置相应的CLIENT用户
B、开发初始化 第一步:建立开发项目环境
1、建立project目录;
2、建立research目录;用来记录项目进程的问题分析、解决文档
3、建立doc目录;用来记录已经成型的系统设计文本;
4、建立GNU目录;用来存放基本的GNU文件、许可、README;
5、建立src0目录;用来编写最为原始的程序和实现测试程序;
6、建立src1目录;用来存放比较完整的库程序和程序;
7、建立src2目录;用来存放最终的产品程序。
8、建立plab目录;你也许需要对自己或者其它的程序进行解剖,这里就是“手术台”。
第二步:实现系统分析
1、推荐首先设计开发系统的库文件:ProjectAPI,这样开发软件比较容易,并且容易扩展;也容易让第三方开发自己的系统;
2、推荐设计测试程序,这样软件可以通过比较容易的方式进行测试,包括测试环境、测试负载、功能测试(宏测试),程序最好留出测试接口;
3、采用GNU编码标准,建立自己的编码标准,并且尽量进行提高;
第三步:协同开发(同步开发/异步开发)
1、采用local的cvs服务控制自己的开发进程,并且拥有私有记录,便于回溯;
2、利用网络的cvs服务器进行比较完整的程序的版本控制,并且可以协作。
第四步:项目测试
1、测试程序测试、宏测试;
2、测试环境测试;
3、实际环境测试;
4、压力环境测试。
第五步:项目打包、发布
1、采用*.tar.gz2(压缩比更大),可以包含源码,让更多的了解和参与;
2、写出可以顺利使用的交互式方式,例如:电子邮件;
3、指出你的项目帮助文档所在的位置。
C、项目开发模版: 1、分析自己的项目;
2、寻找可以借鉴的开源项目源码;
3、寻找合适的开发工具;
4、充分利用win界面环境;
5、快速反馈的渠道;
6、充足的时间面对屏幕。
现在进行逐条的解释:
-1:对于项目进行分析,评价可行性和可用性,这样可以坚定信心,并且让项目拥有一个持续扩展的潜力;
-2:借鉴源码,可以让系统一开始就拥有一个比较成熟的结构,特别是可测试性,这个非常关键,往往成为下一阶段开发的灵感源泉和动力;
-3:合适的开发工具:开源项目拥有非常多的开发工具(tons of...),选择是非常关键的,例如:cflow,sourcesight等等,需要开发者进行专业的选择;
-4:充分利用win界面:现阶段,很多的资源、联系方式,都通过win界面来进行,开发者也可以利用这些资源。通过ssh登陆,CVS提交,可以轻松的解决编码、编译、协作的问题,而不必处于一个不断变化的系统中;
-5:现阶段的反馈渠道经常变化,例如:电子信箱、论坛、IRC,聊天工具,开发者需要提供稳定而多样的反馈方式,否则导致反馈渠道不畅。
-6:进行开发,一定要拥有充足的时间面对屏幕,才能实现稳定的设计。一天耗费5-10个小时左右似乎比较普遍。
D、开发的一些技巧 1、宏功能和微功能( Macro Function and Micro Function )
在很多的情况下,我们的设计是基于宏功能的,而计算机的提供是微功能的,我们需要利用LIB的方式,将微功能组。合起来,实现宏功能,将宏功能组合起来,则形成我们所需要的软件。
2、多进程并发操作
操作缓冲是非常重要的,可以显著的提高效率,可能需要设计几个缓冲层(越多越复杂);对于高负载的进程并发操作,我们可能需要利用汇编来保证原子级操作,并且具有最好的速度。
3、分布式负载
算法非常重要
4、过于复杂的系统
对于庞大的系统,分割成为清晰、简单的层次结构非常重要。此时,简单似乎占据上风(这是我们愿意看到的:)。使用分层(layer)的方式,是最好的解决方案。甚至系统的成败取决于分层设计是否正确。
5、关于开发语言的选择
当然是C——允许有不同的观点。
以下仅仅是一些仅供参考的观点:
1、C++不推荐,主要是基于内存使用和运行的考虑;
2、对于CGI来说,C也是最好的选择。(也许不同的意见更多)。
6、程序设计,需要支持配置脚本
这样程序运行时,适用范围更广。
6.1、拥有一个脚本库直接获得配置脚本的支持。
6.2、如果是GUI界面,则需要对于这个脚本配置的工具程序
7、失落的档案:这是一个提醒
这是一个程序员常犯的错误。立刻准备一套光盘刻录设备,经常备份自己的成果(一次备份2张光碟,并且做好标记)。否则,xxMB的数据不见了,可来不及的。
8、无论如何,立刻标记上软件版本号,从0.0.1v开始
使用0.0.1v开始开发的程序具有一个有趣的特性,可能在你不知不觉中发展到0.7v,甚至v1.x,这是一个令人兴奋的过程,也许,这就是开发的乐趣所在。
9、编程与程序设计的矛盾如何解决?
一般来说,我们都在不改变软件宏功能的情况下,让我们的程序结构更好、更清晰、容易编写。这些细节的编程设计,常常拥有很多的设计方案,我们需要进行编程实践,让各式各样的设计,在程序代码中获得统一。
10、无缝拼凑
实际上,编程不一定需要一句一句的写代码,有的时候可以用拼凑的方式,利用成熟的框架或者代码段,可以大大加快编程的进程,并取得不错的效果。
11、请参考官方站点的文档
这一方面因为官方文档更新更快,质量更好,更是因为官方站点可能提供专业的文档反馈信息,让你对文档的具体解释、实例、漏洞具有更专业的认识,这是其它的指南文档所无法替代的。
E、知识准备: 首先大致描述一下,细节待续
1、熟悉FREEBSD的系统数据结构。包括系统数据结构和网络相关的数据结构。
1.1 进程相关 :进程、线程、IPC
1.2 I/O相关 :管道、Socket
1.3 Net相关 :TCP/IP
1.4 编程语言相关:编译器、语言库
1.5 软件环境相关:UML、CORBA、SGML等基本知识
2、调整MAKE参数,支持相关的函数库,并且打开调试选项,可以更好的支持调试,并且简单通过make可以编译程序
3、参照系统设计,建立与系统进行I/O的LIB。
4、完善程序以构件模块为主,实现程序的更多扩展功能。
5、编译系统的选择:
5.1、对于大多数的项目,编译器系统几乎是任意的,选择一个稳定的编译器,对于项目也是非常重要的;
5.2、相信对于编译器、调试器的熟悉,也是一个成功项目的基础。
6、项目中间测试:
5.1、寻找典型的测试环境。这是非常重要的。在系统设计中,就需要这样的准备工作,并且保持这个测试环境的稳定,才能获得第一手的数据;
5.2、利用CVS进行测试版本的控制工作,防止测试版本的混乱;
5.3 虚拟测试环境(这是一个前卫的项目)
7、项目开发环境选择
7.1、推荐字符界面,相信大家喜欢一个干净的环境;
7.2、开发采用client/server的方式,也是一种较好的方案。Client采用win或bsd,在server上进行编译,在单机进行测试或者在server进行测试;
7.3、推荐开发者不要维护一个GUI界面,这样会浪费大量的时间。最好拥有一个独立的GUI测试平台;
7.4、相信一个reference目录是非常重要的。里面拥有的文档、书籍、例程在缺乏灵感的时候可以助你一臂之力,并且保持你的项目的标准。
F、软件项目快速分析 1、密集度分析模型
相信大家一定使用了某种软件项目分析技术来分析我们需要从事的编程项目。下面介绍一种快速、实用的分析模型:密集度分析模型。
实际上,对于编程人员来说,不需要掌握非常精确的分析方式,使用密集度模型,可以轻松的定义软件的特性,并且安排好一个项目的任务分配和开发进度。
密集度分析模型,可以用来快速分析软件项目,也可以分析软件的不同的模块,以下为软件项目为例:
首先,我们将软件项目分类为如下的类别:
Table 1:
类别名称
特征
实例
开发特性
界面密集类
繁多的界面反馈
GUI应用程序、终端前端
需要良好的用户设计以及界面功能的支持。
功能密集类
对于各种功能要求齐备和多样
数字编辑软件
需要编写大量的功能函数以及插件,对于界面要求相对低
理论密集类
要求程序体现很多编程理论
概念程序、C++复写程序、软件的第一实现版、B/S、C/S软件、算法程序
要求理论基础扎实,并且对于各种理论的实现具有经验。这类项目,非常依赖文档。
工作密集类
需要大量的工作时间和效率
成熟的应用软件
设计一般比较成熟,功能比较简单,需要花费时间去完善。可能依赖项目管理。
执行密集类
要求短时间执行的软件
网络响应、高速算法
需要优化和代码短小,往往是为了解决某些速度瓶颈问题。
I/O密集类
在短时间拥有大量的I/O操作
大规模数据传输、索引、数据存储处理
需要更多的缓冲,并且处理好多线程的问题
异常处理密集类
防止各种错误出现,并且试图从错误中恢复
硬件驱动、控制、系统软件
对于异常的捕捉、处理、恢复,以及对于新的异常的处理补丁。测试的成本相当高。
我们拿到一个软件项目(模块),只需要进行简单的判断,我们就可以确定个人需要作的主要的工作,确定工作的计划。
2、清晰度分析模型
清晰度分析模型,就是看相关的开发人员,对于需要开发的项目的清晰程序。一般来说,清晰度越高,包括设计、编程、经验,则项目的成功率越高。项目的进展速度也会更快。清晰度,实际上也反映了项目的难易度。
这样,利用一个简单的清晰度分析,就可以大致的清晰开发组成员的能力和发展方向。对于新加入的成员,也会产生良好的效果。
更多的,如果有些成员的清晰度不高,则需要重新的测试技术和培养能力,则可能需要一段时间进行适应。
3、确立高级的最终产品设计
对于开发产品而言,我们需要借鉴各种国际上的开源产品的代码。我们往往会发现很多产品,哪怕是非常简单的编辑软件,都可能使用了高级的编程技术。例如:CORBA、 C/S、XML、嵌入式汇编、编译器适应、非公开的调用、多进程文件锁、多CPU总线锁、分布式构件以及独特的C++设计视角等等。
我们需要借鉴和利用这些流行的技术,不一定非要在项目的0.0.1版上应用,但是我们需要清晰软件项目的发展方向。
这样做,将会让我们从一个简单的0.0.1版开始,最终实现最好的软件系统。
4、确定整体项目的开发模型。
实际上,开发一般分为两种模式:
1、从一开始就设计和实现一个合格的系统;(以3.0版进行发布)
2、首先建立一个系统(0.0.1版),然后找一批人完善和升级这个系统。
从费用上讲,两种模型可能差不多。大家按照自己的情况选择吧。
G、雏形: 虚拟执行
虚拟执行的概念:实际上就是我们常用的确定界面法。这个界面,就是我们的程序对于运行环境的适应的第一步。
对于GUI程序,实际上就是简单的设计一个窗口,执行一个空的工作;
对于Deamon程序,就是设计一个空的独立进程,什么也不做;
对于module程序,就是实现一个虚拟的设备、工作,什么也不做。
这样,就拥有了一个基础,并且可以进行新功能的调试。并且是软件项目实现的开始。
下一个阶段,就是不断地加入新的功能。对于每一个功能来收,实际上也是从一个独立的虚拟执行开始,首先具有这个功能的界面,然后具有功能的细节(类似原型开发模型)。
I、下一步怎么做? 驾驭你的代码
这一步,需要利用自己全部的知识,来驾驭自己的代码。
A阶段:一个良好的设计文档
B阶段:结构代码设计——主结构
C阶段:真正的考验开始啦——子结构。其中包含数据结构、算法、系统调用、C++/C函数库、死锁分析等等。
D阶段:调试并且发布测试版。
A、B阶段:软件设计工程师的主要工作内容,工作成果的水准,将会影响整个的项目。经验和理论是非常重要的。
C、D阶段:软件代码工程师的主要工作内容,需要我们充分发挥自己的水平,驾驭代码,完成设计。尝试、灵感、基本功、想象力是非常重要的。
在实际的应用中,应当还有:
E阶段:排除一些编译器警告和移植到其他的系统中。
1、在一些版本中,包括freebsd-stable/current或者使用不同的编译器,也许还有一些五花八门的安装环境。会导致编译器的表现不一致。或许不会导致程序运行的问题,但却是令人烦恼的。
2、我们可能需要将程序移植到Linux或者win32下,早作准备是一个好主意。
遭遇任何的困难,按照以下的“标准工作手册”
1、阅读各种参考手册中的相关内容,获得基础结构,其他的不明白的地方,与其去google搜索,不如编一个小程序获得答案。
2、参考具有相同工作的软件代码,可能会获得经典的答案,比如:关闭文件的经典做法。对于系统编程,则参看内核级源码,对于应用编程,则参看应用软件的代码。
3、参考其他项目成员的程序,或者朋友自己编写的程序,可以获得具有相当价值的答案。
4、搜索一些常见的论坛、论文站点的有用信息。
5、实在不行,就在论坛、IRC、ICQ上大叫“help”? :) 也可以向资深的朋友求教。
6、调整心态,勇敢的(或者硬着头皮)写下去。 :)
FAQ:
1、C/C++如何作出取舍?
这一点不要看的绝对,实际上,C/C++可以混合使用,共同发挥各自的优点。C也可以借鉴C++的思想,编写出来类似C++的C程序(参看OOP with ANSI-C)。
2、程序结构不佳怎么办?
在实现与清晰的结构之间,实际上是难以取舍的,不如就以实现为主。程序的结构可以渐渐地进行修改。
3、我编写的程序值得发布吗?
实际上,在计算机程序世界,实现就是一个标准。有的时候可能有几种实现方式,各自具有优势和劣势。但是发布你的产品和代码,则是一个真实的进展。
4、项目存在各种困难,进行不下去啦!?
实际上,这是一个错误的判断,除非你需要转移到其他的项目中去。否则,持续的研究下去,你将会发现,其中衍生的研究成果,可以应用到很多的项目中。一个完整的项目,与一个半途而废的项目相比,给你提供的资讯要多的多。
5、是否程序最好做成 FrontEnd / MiddleModule / BackEnd 的结构形式?
在这里,本文是推荐这样进行设计和编程的(或者你拥有更好的设计),该项目基于一个先进的结构,可能获得良好的扩展。这样,简单的项目,也可能发展成为一个较先进的软件系统。
6、为什么有些代码是用复杂的(非正规的)变量声明或者处理?
一般的,可能为了让生成的二进制代码更加符合原子操作或者提升效率,这是C语言的灵活特性所决定的,它可以这样做,并且会做的更好。
当然,也有一些是兼容的需要或者其它的未知原因。
7、我必须要选择一个IDE环境吗?
答案:否!IDE仅仅适合编写演示程序(允许有不同意见),而对于开发真正专业的程序,IDE几乎是画蛇添足。
J、高级的优化 这里有一些参考性的意见:
1、简单的使用gcc优化参数;
2、使用egcc(目前egcc和gcc又合并了)的较高版本,这个版本具有更好的优化效果;
3、使用objdump反汇编,修改源代码,试图产生实用的汇编代码;
4、使用更为顶级的专业工具,例如:商业工具codesight(需要购买)。
K、一些注意事项 还没有完美无缺:
1、如果你需要发布你的程序,程序中借鉴了FREEBSD系统的源码,请注意相关程序的许可证(License)。特别对于PORTS程序,往往具有各种不同的许可证。
2、如果你发布的程序,拥有一个大的数据文件,最好与程序分开发布。这样便于别人迅速的下载你的程序进行研究,他们的本地往往不需要一个完整的数据文件(仅供测试即可)。并且数据文件单独维护,可以较好的适应升级策略。
3、注意留出i18n的界面语言通道文件,对可能的国际化产生良好的作用。
L、密密麻麻的代码? 直接面对密密麻麻的代码。
当进行Open Source软件开发的时候,我们将会面对铺天盖地的代码:
1、教科书中存在的实例代码;
2、已经存在的系统内核代码,应用软件代码;
3、项目成员编写的代码;
4、自己编写的代码;
5、未来的代码研究。
当面对这些看起来类似天书的代码的时候,我们将要怎么做呢?
源码的基础理解:
当我们分析一段高级的系统代码时,我们可以发现,程序源码核心层次是数学,我们可以这样将源代码的层次分为:
1、核心层:数字层;包括外界所有的信息的数字化,而不是按照字符进行处理,一般的,认为按照字符处理的,不是底层的编程或者高级的编程;
2、算法层:数字处理层,运用逻辑、数学算法,对于数字进行处理;
3、表述层:将数字处理的结果,表述成具体的信息;
4、界面层:该层次包括人机界面、软件接口界面、数据存储界面等。
于是,看到这里,我们就会明白一个源码体系所要表述的信息了。
这里需要注意的是数据存储界面,对于现代数据存储系统而言,是一个复杂的体系,需要又有更多的研究。
* 简单的代码研究……图解程序
就是重画系统的流程图,实现对程序大致结构的清晰。
* 全面的研究……数据结构+算法
这是一个细致的工作,你必须拥有数据结构的入口列表、出口列表、算法中列表。
* 代码的深入理解……试图修改
你需要建立一个独立的实验目录,对于所要研究的程序进行解析。重新,加入解析代码,用调试器查看运行细节。这样,你会对于这个程序进行系统的剖析,甚至会加强其功能。
深入的对于优秀的程序进行剖析,你将会学到任何教科书都无法传授的细节内容。BSD代码就是这种优秀的范本。
M、如何阅读源代码? 实际上,我们看到的最终代码融合了如下的知识层:
1. 原理
2. 程序主要功能流程
3. 编程技巧
4. 程序效率/强壮/移植的优化
5. 系统发布/编译/安装/卸载/管理实用程序
6. 对语言代码文件结构的组织/优化
7. 版本控制的优化
8. 其他的处理(例如:错误处理,安全处理等等)
9. 各种高手用各种语言写的服务程序(例如:perl,shell等等)
这也是为什么设计与编程几乎完全不同的原因。设计上关心的功能流程结构,在源代码中几乎找不到。源代码中到处充斥着各种技巧,对于编译器的妥协,对于源代码结构的处理(例如抽象各种封装库)。
对于源代码的分析,一行一行的分析,几乎什么也得不到。还是需要从如下的几个方面进行:
1. 原理,这是一个基础
2. 软件主要功能结构(源代码中,这个都被奇怪的函数名称所代替)
3. 编程技巧
4. 如何适应特定的操作系统
5. 系统开发接口
6. 系统运行的缺陷
7. 进一步优化、加入新的功能设计(例如:ToDoList的实现)
这样就是从源代码中获得的知识。源代码实际上是一种产品。我们分析源代码,是一种反向工程。
1、明白作者是如何思考和运用原理的;
2、思考作者是如何解决现实存在的问题和采取的措施;
3、明白作者对于计算机科学的思考和尝试。
一般的,阅读BSD的代码你将会很舒服的获得简洁而清晰的代码,从FreeBSD站点cvs co是一个好主意。
这张图将告诉你怎样获得CVS的FreeBSD源码
N、编写C代码的奥秘
* 简单的知识准备,就是明白:
1、你的工作就是调用系统的C编程接口库;
2、你必须以符合C接口库的数据结构安排你的数据类型。
* 下一步的工作,就是提供你的算法:
1、程序=数据结构+算法,这是永恒的定义;
2、随时要注意的是,你需要明白数据在内存的什么地方。
* 高级的要求,就是你必须基于基本库写你自己的项目库,这是一个比较大的C项目开发基础。

