关在屋子里骂街

Death is inevitable,but the qulity of life is optional

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  183篇文章 :: 22篇收藏:: 325篇评论:: 5个Trackbacks

公告

我无法抗拒生活的强暴,只能想象她是薇诺娜赖德...

文章

收藏

相册

Design

Friendly Links

Tech Site

Web Development

存档


正在读取评论……


CS technology

datagrid的正反双向排序 (mikecat888原作) .NET 193 2004-4-14
DataGrid常见解决方案(四)---DataGrid删除确认及... (hbzxf原作) .NET 1226 2004-4-13
DataGrid常见解决方案(三)--在DataGrid中选择,确... (hbzxf收藏) .NET 638 2004-4-9
DataGrid常见解决方案(二)---使用DataGrid动态绑... (hbzxf原作) .NET 1059 2004-4-8
DataGrid常见解决方案(一)---在分页状态下删除纪... (hbzxf原作) .NET 964 2004-4-8
怎样使用DataGrid控件 (little119转贴) .NET 488 2004-4-5
DataGrid Web控件深度历险(3) part3 (chinapro翻译) .NET 2157 2004-4-3
DataGrid Web控件深度历险(3) part2 (chinapro翻译) .NET 1146 2004-3-30
DataGrid Web控件深度历险(3) part1 (chinapro翻译) .NET 1288 2004-3-30
datagrid分页《非控件版》 (rickjelly2004原作) .NET 1371 2004-3-24
datagrid分页问题(前后跳页)《控件版》 (rickjelly2004原作) .NET 771 2004-3-24
DataGrid Web控件深度历险(2) Part2 (chinapro翻译) .NET 2772 2004-3-22
DataGrid Web控件深度历险(2) Part1 (chinapro翻译) .NET 6786 2004-3-22
DataGrid Web控件深度历险(1) (chinapro翻译) .NET 1040 2004-3-18
如何在DataGrid里面产生滚动条而不滚动题头 (cuike519原作) .NET 2612 2004-3-12
使用在.net 框架上的DataGrid數據分頁控件 (99441dudu原作) .NET 1059 2004-3-10
将某一目录下的所有相同格式的 XML文件绑定到不同... (net_lover原作) .NET 710 2004-3-10
DataGrid连接Access的快速分页法(5)——实现快... (upto原作) .NET 2079 2004-3-6
DataGrid连接Access的快速分页法(4)——动态生... (upto原作) .NET 1417 2004-3-6
DataGrid连接Access的快速分页法(3)——SQL语句... (upto原作) .NET 1238 2004-3-6
DataGrid连接Access的快速分页法(2)——SQL语句... (upto原作) .NET 1292 2004-3-5
DataGrid连接Access的快速分页法(1)——需求与... (upto原作) .NET 2214 2004-3-5
显示DataGrid序号的一个适用的方法 (wangj2001原作) .NET 704 2004-3-2
常见 Datagrid 错误 (kwklover转贴) .NET 837 2004-2-19
常见 Datagrid 错误 (wrclub转贴) .NET 1646 2004-2-17
XP 风格的可拖动列、可排序、可改变宽度的DataGr... (net_lover原作) .NET 1878 2004-2-17
XP 风格的可拖动列、可排序、可改变宽度的DataGr... (net_lover原作) .NET 9891 2004-2-16
利用radio实现Datagrid的单选 (guoyan19811021原作) .NET 1034 2004-2-12
重画系列:DataGridColumnStyle之测试代码 (ganenpingsohucom原作) .NET 598 2004-2-10
将OleDbDataAdapter绑定到Winform下的DataGrid (SaSBYa原作) .NET 627 2004-2-9
去除Asp:DataGrid中无用ViewState的方法(2) (TomMax原作) .NET 546 2004-1-20
去除Asp:DataGrid中无用ViewState的方法(1) (TomMax原作) .NET 596 2004-1-20
datagrid保存时无法提交更新的问题 (zwq78原作) .NET 591 2004-1-12
将DBF,XLS,XML,MDB文件导入C#DataGrid的方法 (adonis2222原作) .NET 2063 2003-12-30
动态创建DataGrid的模版列 (cuike519原作) .NET 2749 2003-12-26
DataTable中数据记录的统计 (triout原作) .NET 827 2003-12-15
(ASP.NET)用动态属性和DataView实现DataGrid的... (zhongmao原作) .NET 1128 2003-12-2
如何同步滚动两个相同的DataGrid (cuike519原作) .NET 2772 2003-11-29
asp.net中DataGrid性能测试 (yzdy原作) .NET 815 2003-11-27
让Asp.NET的DataGrid可排序、可选择、可分页 (lihonggen0原作) .NET 6526 2003-11-21
DataGrid传统分页方式 (wsqsoft原作) .NET 788 2003-11-8
在后代码里创建DataGrid控件 (net_lover原作) .NET 1778 2003-11-4
实现类似Windows资源管理器的DataGrid (net_lover原作) .NET 4419 2003-11-4
ASP.net中的Datagrid自定义分页功能 (ninesong原作) .NET 1008 2003-10-31
在Pocket PC应用程序中使用DataGrid控件 (aawolf翻译) .NET 1007 2003-10-29
创建可拖动列的DataGrid(2) (net_lover原作) .NET 1068 2003-10-16
创建可拖动列的DataGrid (net_lover原作) .NET 1866 2003-10-16
DataGrid和CheckBox的混合使用 (cuike519原作) .NET 2327 2003-10-15
利用Session纪录datagrid模板列中CheckBox的状态 (guoyan19811021原作) .NET 1610 2003-9-26
DataGrid模板列中TextBox的焦点相应键盘事件 (guoyan19811021原作) .NET 3328 2003-9-26
给DataGrid添加确定删除的功能 (cuike519原作) .NET 2197 2003-9-5
如何给DataGrid添加自动增长列 (cuike519原作) .NET 1393 2003-9-5
如何利用RadioButtonList实现datagrid列的单选 (j99616原作) .NET 951 2003-8-30
锦上添花DataGrid! (cuike519原作) .NET 2463 2003-8-29
ASP.Net WebMatrix中Datagrid使用模板列对数据显... (ceocio原作) .NET 2194 2003-8-21
格式化 DataGrid 输出 (nxyc_twz翻译) .NET 2305 2003-8-7
如何实现单击在DATALIST(DATAGRID)的HEADER加入的... (j99616原作) .NET 747 2003-8-6
向datagrid中加横向 纵向的合计 (在datatable中... (dragonsuc原作) .NET 3724 2003-8-3
基于ADO+Adodc控件+DataGrid控件制作的一个数据库... (lshdic原作) Visual Basic
如何实现自定义及自动逐页打印DataGrid显示的内容 (maxchou原作) 网站制作技术 3015 2003-6-30
合并datagrid中内容相同的单元格 (jxf_yx原作) .NET 2376 2003-6-19
创建固定表头、表格体滚动的DataGrid (net_lover原作) .NET 2385 2003-6-11
创建跨多列、多行表头的DataGrid (net_lover原作) .NET 1678 2003-6-11
在DataGrid中添加一个合计字段 (nxyc_twz翻译) .NET 4188 2003-6-6
在DataGrid里添加确认删除的对话框 (net_lover原作) .NET 2289 2003-6-6
为DataGrid添加自动编号功能 (net_lover原作) .NET 1640 2003-6-3
格式化DataGrid的例子【将数据源中的0,1值转换成... (net_lover原作) .NET 1210 2003-6-3
Henry手记—Web Form中的Datagrid的自定义分页 (Latitude原作) .NET 4990 2003-6-1
创建完全可编辑的 DataGrid (nxyc_twz翻译) .NET 10288 2003-5-30
DataGrid控件通用打印类. (xiaochongsun原作) .NET 1991 2003-5-29
为DataGrid添加CheckBox控件 (net_lover原作) .NET 1508 2003-5-24
VB.NET中关于DataGrid颜色的自定义。 (yohomonkey收藏) .NET 1083 2003-5-20
在DataGrid快速添加新行 (net_lover翻译) .NET 1575 2003-5-19
Henry手记-Datagrid事件响应(二) (Latitude原作) .NET 6425 2003-5-7
datagrid技巧之一:代码控制选中行的颜色 (qieyj原作) .NET 2304 2003-4-7
在C#里实现DATAGRID的打印预览和打印 (qieyj原作) .NET 3157 2003-4-7
Binding a DataGrid to an ADO Recordset (qieyj翻译) .NET 1610 2003-4-7
Creating DataGrid Templated Columns Dynamical... (qieyj转贴) .NET 1130 2003-4-7
Creating DataGrid Templated Columns Dynamical... (qieyj转贴) .NET 1175 2003-4-7
DataTable,DataView和DataGrid中一些容易混淆的概... (chnking原作) .NET 3101 2003-4-7
动态的管理ASP.NET DataGrid数据列 (younther翻译) .NET 6687 2003-3-25
Henry手记-Datagrid键盘事件响应(二) (Latitude原作) .NET 6161 2003-3-11
Henry手记—从Datagrid的标题居中说起 (Latitude原作) .NET 4281 2003-2-20
用嵌套的DataGrid实现主从式表的显示 (janesnow原作) .NET 2004 2003-2-13
DataGrid中嵌套使用Repeater (ouyang76cn原作) .NET 1477 2003-2-7
Henry手记 - Datagrid键盘事件响应(一) (Latitude原作) .NET 5771 2003-1-19
给datagrid控件建立稳固的双向排序(asp.net) (ouyang76cn原作) .NET 1228 2003-1-18
我的asp.net笔记.(嘿嘿,试着来一下) (mint原作) .NET 1858 2003-1-15
添加一个下拉框到DataGrid (lihonggen0翻译)
DataSet导出CSV格式(ASP.NET,C#) (Not原作) .NET 1528 2003-1-3
Henry手记:Datagrid事件响应 (Latitude原作) .NET 6291 2002-12-31
Henry手记:WinForm Datagrid结构剖析(三)使用... (Latitude原作) .NET 4147 2002-12-18
Henry手记:WinForm Datagrid结构剖析(三)类代... (Latitude原作) .NET 3992 2002-12-18
Henry手记:WinForm Datagrid结构剖析(三) (Latitude原作) .NET 5536 2002-12-18
ADO在vb.net中的使用(与datagrid结合) (jatwu原作) .NET 1434 2002-12-9
Henry手记:WinForm Datagrid结构剖析(二)程序 (Latitude原作) .NET 4520 2002-12-5
Henry手记:WinForm Datagrid结构剖析(二) (Latitude原作) .NET 5607 2002-12-5
ASP.NET中的DataGrid的属性 (tingningpower原作) .NET 1190 2002-12-5
EnableViewState="false"的DataGrid分... (qiushuiwuhen原作) .NET 630 2002-12-5
Datagrid 链接数据库Access (tingningpower原作) .NET 2010 2002-11-29
DataGrid 链接Access数据库 (tingningpower原作) .NET 686 2002-11-29
Henry手记:WinForm Datagrid结构剖析(一) (Latitude原作) .NET 9010 2002-11-15
把Excel文件中的数据读入到DataGrid中 (net_lover原作) .NET 7751 2002-11-1
如何创建一个用弹出窗口来查看详细信息的超链接列 (FCloud翻译) .NET 2015 2002-10-25
DataGrid使用技巧(四) (dy_2000_abc原作) .NET 3927 2002-10-13
DataGrid使用技巧(三) (dy_2000_abc原作) .NET 5221 2002-10-3
DataGrid使用技巧(二) (dy_2000_abc原作) .NET 5878 2002-9-25
DataGrid使用技巧(一) (dy_2000_abc原作) .NET 5886 2002-9-23
神奇的 DataGrid (yellowwee翻译) .NET 10612 2002-6-11
使用c#+(datagrid控件)编辑xml文件 (ouyang76cn原作) Visual C++ 836 2002-4-15
在DataGrid中创建一个弹出式Details窗口 (songzx66转贴) .NET 1137 2002-1-31
在DataGrid中创建一个弹出式Details窗口 (cashcho翻译) .NET 3150 2002-1-24
vs.net beta 2中利用DataGrid分页详解 (carper原作) .NET 2993 2001-10-18
使用 ASP+ DataGrid 控件来创建主视图/详细资料视... (ghj1976转贴) ASP 1596 2000-12-5
使用 ASP+ DataGrid 控件来创建主视图/详细资料视... (ghj1976转贴)

GNU是一个充满梦想的世界,Linux是一个非常神奇的操作系统.系统应该开放,软件应该自由使用.自由的信念激发无数人的激情,为自由软件事业而奋斗.然而由于在Windows的统治下太长的时间,我们对自由软件,对Linux还非常的陌生.缺少应用软件支持,缺少用户.但这一切都无法阻挡自由软件事业的发展.让我们携起手来,为自由软件同盟而奋斗吧!


    程序是程序员交流的方式.可以在Linux下编写程序,为自由软件事业出一份力,是每一个Linux用户的愿望.我写这份教程的目的也在于此.以下是我的一些假定:                                                1.读者熟悉C语言;                                                2.读者已经安装了一份Linux操作系统,并且已经正在运行;
3.本教程的所有开发环境均在字符界面完成,并且十分简单,只是一份入门教程;
    让我们开始吧!

vi的使用(edit)
    vi是Unix/Linux下最经典的文本编辑器之一.Linux的用户必须熟悉它.
  vi filename // 打开/创建一个文件(如果文件不存在的话)
    这样,就进入了vi的界面了.理解vi的关键是理解vi的两种模式:编辑模式和命令模式.一开始进入的就是命令模式.在命令模式下,可以使用一些命令,如保存,退出等.在编辑模式下,可以对文挡进行编辑,修改.
在任何时候,按ESC键,将进入命令模式.在命令模式下,按a(append),i(insert)可以进入编辑模式.一般的使用i即可.在命令模式下,按':',再在:后输入wq(write and quit),就可以存盘退出了.如果不想存盘,则在:后输入q!(强行退出).在命令模式下,直接shift+ZZ,也可以直接存盘退出,而省去了输入:的麻烦.
    下面是一个完整的创建C语言代码的完整的例子.
  vi hello.c
  // 命令模式,按i键进入编辑模式
  // 输入一个测试代码
  // 按ESC进入命令模式
  // 存盘的两种方式:
  A: 输入:+wq
  B: shift+ZZ
  // 放弃存盘的方式(本次编辑修改的内容无效)
  输入:+q!

gcc的使用(?)
    gcc是GNU的拳头产品.世界上威力强大的C语言编译器.如果你熟悉命令行编译的话,这个工具非常适合你.在Windows下也有它的一个版本.
    在介绍gcc的使用之前,让我们先回顾一下C语言的编译过程:
  hello.c(编译)->hello.o(连接)->hello//linux
  hello.c(编译)->hello.obj(连接)->hello.exe//windows
    在前面的例子中,我门已经有了一个C语言源程序,hello.c,下面我们将它编译连接成可执行文件
  gcc -o hello.c// 结果:我们得到一个以默认名称命名的可执行文件a.out
  gcc hello.c -c hello.o// -c选项代表编译,结果为目标代码hello.o
  gcc hello.o -o hello// -o选项代表连接,结果为可执行文件hello(无后缀名)
  gcc hello.c -o hello// 常规用法,一步到位,直接得到可执行文件
    Linux里,当前目录下的可执行文件和系统命令是有严格区分的.你想执行一个系统命令,如拷贝命令cp,直接输入cp回车就可以了;如果想运行当前目录下的一个可执行文件hello,则需要输入./hello,才行.这也是Linux的安全措施之一吧.

gdb的使用(debug)
    gdb是Linux下一个常用的调试工具.要想使用它对程序进行调试,在编译的时候注意要加上选项 -g,
gcc -g hello.c -o hello.这样得到的可执行文件中就加入了调试信息,通常文件也会变得很大.下面是它的用法:
  gdb hello// 调试hello
  gdb break main// break,设置断点,此处断点设在程序的开头,main函数的入口处
  gdb r// 开始运行程序,在断点处停止,本处为程序的开始
  gdb s// step,开始单步调试程序了,同时会打印出此处程序的源代码
  gdb print var// 打印变量的当前值,程序不会向前执行,var为变量名
  gdb r或者gdb q// 错误排除,让程序直接运行结束或直接退出.(gdb r运行完也不会退出gdb,请再输入一个q)

makefile的使用(?)
    makefile是用于多源代码文件项目管理的.举例说明,一个可执行文件abc由a.o,b.o,c.o连接而成;而a.o由a1.c,a2.c,a3.c编译而成,b.o由b1.c,b2.c,b3.c编译而成,c.o由c1.c,c2.c,c3.c编译而成.够复杂的.我们需要
  gcc a1.c a2.c a3.c -c a.o
  gcc b1.c b2.c b3.c -c b.o
  gcc c1.c c2.c c3.c -c c.o
  gcc a.o b.o c.o -o abc
    如果仅仅一个源文件a1.c发生变化,我们必须重新编译其它没有发生变化的程序,做无用功.这里的例子仍然很小,如果是一个有数百个源代码组成的工程,简化编译过程将十分必要.makefile由此而生.
    makefile由依赖关系和编译命令组成.依赖关系的写法是
    目标 : 依赖的文件1,依赖的文件2,依赖的文件3...
    编译命令直接写在依赖关系的下一行,注意,以一个tab退格键开头,四个空格不行
    我们以上面的例子写一个makefile文件.(makefile的默认文件名就是makefile,无后缀名)
  vi Makefile
  abc : a.o b.o c.o
 gcc a.o b.o c.o -o abc
  a.o : a1.c a2.c a3.c
 gcc a1.c a2.c a3.c -c a.o
  b.o : b1.c b2.c b3.c
 gcc b1.c b2.c b3.c -c b.o
c.o : c1.c c2.c c3.c
 gcc c1.c c2.c c3.c -c c.o
  执行makefile,系统就会根据源文件的最后修改时间决定,那些需要重新编译,而哪些不要.


相比于传统程序,当前网络应用程序变得功能更加强大,然而也趋于更加复杂,而且这些网络应用程序不断更新,扩展,集成最新技术和商务处理。由于这些复杂性,很多问题应运而生,比如:“我或者整个开发团队如何管理这些应用程序?”使用Fusebox方法就能够解决这些问题。

Fusebox是什么?

Fusebox是管理复杂Web应用程序的一种方式,它通过将一个复杂的Web应用程序分成若干个比较小的模块而达到管理的目的。网页脚本语言,比如ColdFusion, ASP, JSP, 以及PHP很少提供分离程序的功能,因为脚本和HTML输出通常位于相同的页面上。而且,在执行过程中也没有处理程序流的标准。所以在链接和HTTP重新定位的时候,网页很容易碰到各种障碍。当网页数量增多时,这些问题也随着增大。

当没有处理程序流和分离程序处理的标准时,建立一个大型的应用程序相当困难。Fusebox提供了这样的标准。它是免费的,而且是开发性的方法,能够用于开发大型的,复杂的Web应用程序。使用Fusebox能带来以下的好处:

  • 更好的规划和建模

  • 快速开发

  • 更多的代码重用

  • 更少的错误

  • 更方便的调试

  • 更容易的维护

  • 更高效率的团队开发

  • 大型开发社区

     

    Fusebox最初是用于ColdFusion应用程序服务器,但它提供了连接到ASP,JSP,以及PHP的“接口”。这篇文章将涉及到ColdFusion,所以你应该具备ColdFusion的常用知识和概念。

    最新的Fusebox版本发布于2001年十月,名为“Fusebox 3”。本文我将讲述最初的Fusebox方法的基本概念,在以后的文章中我们再讲述到Fusebox 3的增强功能。

     

    Fusebox之外的概念

    当管理程序流的时候,网络开发人员通常会面临着挑战。因为在没有某些结构(不使用Fusebox)的情况下,程序中的任一页面都可能调用其他的页面,最终极有可能导致一个如图A所示的混乱无序的结果。

     

    “Fusebox文件”的概念是原始Fusebox之外的一个重要的概念,它是管理网页之间相互作用的一个中心文件。“Fusebox文件”的操作类似于一个交通警察,它按照执行的需要引导程序流。Fusebox文件使用CFINCLUDE来包含独立文件,或者执行一个特定操作的保险丝(fuses)。保险丝不会直接调用其它的保险丝以初始化一个新的请求,所有的操作都会集中到中心Fusebox文件。如果能正确使用Fusebox,我们会看到如图B的结果。

     

    图A和图B说明了使用Fusebox在管理上的改进。也许你的下一个问题是:“Fusebox如何知道应该包含哪些保险丝(fuses)?”这一问题的答案包括“fuseaction”的其它一些逻辑和概念。

    Fusebox文件每一次被调用,名为“fuseaction”的变量将会作为一个URL变量传递到Fusebox。Fusebox文件包含一个CFSWITCH/CFCASE语句,这一语句决定了所要包含执行特定fuseaction的保险丝。

    假设这样的URL形式,http://www.mysite.com/index.cfm?fuseaction=displaynews,Fusebox文件(index.cfm)使用Fuseaction(displaynews)的值并查找CFSWITCH/CFCASE语句以达到匹配。当查找到匹配时,Fusebox文件将包含必要的独立文件。表A包含了一个显示这一工作过程的简单的Fusebox文件。


  • 首先是下载工具:
      我建议初学者用Editplus+JDK,用JCreator也是一个不错的选择。我觉得如果用例如JB,Eclipse,虽然刚开始的时候比较方便,但是确使初学者门不知道怎样配置环境变量,反而不好。:)
        Jcreator:最新的是 2.5 了。呵呵
    http://www.jcreator.com  在国内网站搜索一下。。有 pro 版的注册机了。
      Editplus:http://hnpy.onlinedown.net/down/HAP_EditPlus211SR22.rar
      JDK : 最新版本是Jdk1.5了。快出来了,现在还是用 1.4.2 吧!:http://count.skycn.com/softdown.php?id=3116&url=http://sc-http.skycn.net/down/j2sdk-1_4_2-windows-i586.exe
      
      然后就是安装JDK,我是把它装到从c:\JDK目录下面:
      然后就是CLASSPATH的问题了:
      正如操作系统利用PATH来搜索可执行程序一样,Java运行环境也会遍历CLASSPATH来查找类,即便是HelloWorld这样简单的程序,JVM也会遍历
      CLASSPATH定义的每一个路径,直到找到相应的文件为止。
      相信大家用的系统不是2k就是XP,然后就应当如下设置Path:
      我的电脑->属性->高级->环境变量
      然后在环境变量的Path后面追加:C:\JDK\bin;.;C:\JDK\lib
      也可以这样配置:C:\JDK\bin;.;C:\JDK\lib\dt.jar;C:\JDK\lib\tools.jar
      warning:环境变量中的.切记不能少,它表示当前路径,如果少掉出现的错误等会就说!
      dt.jar是关于运行环境的类库,tools.jar是关于一些工具的类库
      如果没有配置:C:\JDK\bin,则会出现“javac'不是内部或外部命令,也不是可运行的程序或批处理文件。”这样的错误。
      然后下面就该写程序了:
      首先是(HelloWorld.java),打开Editplus,新建一个Java文件,请照着如下输入,要一字不漏,并且分清大小写:
      publicclassHelloWorld{
      publicstaticvoidmain(String[]args){
      System.out.println("Hello,World!");
      }
      }
      然后把这个文件保存(ctrl+s)到HelloWorld.java,记住大小写一定要分清,是HelloWorld.java不是helloworld.java或者其他的
      下面就该运行了,开始->运行->cmd
      在控制台中把目录切换到当前目录:
      javacHelloWorld.java
      javaHelloWorld
      你就会在控制台上看见输出的Hello,World!(没出来?我把电脑吃了:))
      javac是编译命令,它把HelloWorld.java编译成HelloWorld.class
      java就是解释命令,JVM把HelloWorld.class解释执行.

    在这个时候:
      1。如果出现Exceptioninthread"main"java.lang.NoClassDefFoundError:HelloWorld
      那就是你在环境变量中没有加上那个.(dot)
      2。如果出现Exceptioninthread"main"java.lang.NoSuchMethodError:main
      或者HelloWorld.java:1 ublicclasshelloworldmustbedefinedinafilecalled
      
      "HelloWorld.java".
      那就是你没有分清大小写的写入这个HelloWorld,或者保存得时候没有保存为HelloWorld.java
      这个名字一定要跟publicclass的名字一样
      
      对于环境变量的问题就说到这里,下面我先所说怎么在Editplus里面编译和运行,在Tools->参数设置->配置用户工具
      1.添加工具(添加应用程序)
      菜单文字:CompileJavaProgram
      程序:C:\JDK\bin\javac.exe
    参数:文件名称
        初始目录:文件目录


      2.添加工具(添加应用程序)
      菜单文字:RunJavaProgram
      程序:C:\JDK\bin\java.exe
      参数:文件名称(不含扩展名)
      初始目录:文件目录
      
      工具组名称可以随便添,比如DebugJavaProgram
      然后在Tools的下拉菜单中,你就会看见CompileJavaProgram以及RunJavaProgram这两个选项,以后你就可以利用ctrl+1编译和ctrl+2运行程序了
      
      下面就讨论Servlet的运行:
      首先要运行Servlet,则需要JSP/Servletcontainer,我建议初学者用Tomcat
      Tomcat(最新版本5.0):http://cvs.apache.org/builds/jakarta-tomcat-5/nightly/jakarta-tomcat-5-bin-20030725.zip
      然后把这个压缩包解压到:
      C:\Tomcat
      然后再配置环境变量:
      添加三个系统变量:
      JAVA_HOME:C:\JDK
      TOMCAT_HOME:C:\Tomcat
      CLASSPATH:%JAVA_HOME%\lib;%TOMCAT_HOME%\lib
      Tomcat的环境变量就配置完毕了,下面检验Tomcat是否能够运行:
      在控制台中转到C:\Tomcat\bin这个目录,运行startup,然后回出现一个窗口,连跳一大串东西,最后表示Server已经运行
      在浏览器中输入http://localhost:8080,出现欢迎界面,则表示Tomcat没问题了
      然后和上面一样,写入你的第一个Servlet
      import java.io.*;
      import javax.servlet.*;
      import javax.servlet.http.*;
      public class HelloWorld extends HttpServlet

    {
      public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)throws ServletException,IOException
      {
      
      response.setContentType("text/html");
      PrintWriterout=response.getWriter();
      out.println("<html><head><title>");
      out.println("ThisismyfirstServlet");
      out.println("</title></head><body>");
      out.println("<h1>Hello,World!</h1>");
      out.println("</body></html>");
      
      }
      }
      然后照样用javacHelloWorld.java来编译这个文件,如果出现无法importjavax.servlet.*
      那么就是应该把C:\Tomcat\common\lib里面的servlet.jar文件拷贝到C:\JDK\jre\lib\ext中,再次编译,就没有问题了!
      然后在Tomcat目录里面的C:\Tomcat\webapps\ROOT里面按如下的文件结构:
      ROOT\index.html
      ROOT\welcom.jsp
      ROOT\WEB-INF\lib\MyServlet.jar(如果你的servlet的.class打成了.jar文件,则放在lib下面)
      ROOT\WEB-INF\classes\HelloWorld.class(把上面生成的HelloWorld.class文件放在这个里面)
      
      然后在浏览器中输入http://localhost:8080/servlet/HelloWorld,于是Server众望所归的报错了:Error404--NotFound
      怎么回事呢?
      Servlet必须使用C:\Tomcat\webapps\ROOT\WEB-INF这个目录下面的web.xml文件进行注册,用EP打开这个web.xml文件,
      在里面加入
      <servlet>
      <servlet-name>HelloWorld</servlet-name>
      <servlet-class>HelloWorld</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>HelloWorld</servlet-name>
      <url-pattern>/servlet/helloworld</url-pattern>
      </servlet-mapping>
      
      这样的结构
      <servlet>
      <servlet-name>HelloWorld</servlet-name>
      <servlet-class>HelloWorld</servlet-class>
      </servlet>
    表示指定包含的servlet类.
      而以下的结构
      <servlet-mapping>
      <servlet-name>HelloWorld</servlet-name>
      <url-pattern>/servlet/HelloWorld</url-pattern>
      </servlet-mapping>
      表示指定HelloServlet应当映射到哪一种URL模式。
      在修改web.xml完毕过后,重新启动Server,然后再输入http://localhost:8080/servlet/HelloWorld,那么偌大一个Hello,World!等着你呢,恭喜你
      摆平了:)
      艾,手都打累了,就写到这儿吧,希望对初学者有一点作用!
      
      ================================
      如何建立一个连接数据库的应用?例如连接access、和sqlsever.
      听说有jdbcjdbc-odbc桥等方式。目前我的机器上只有jdk1.4,我想用jdbc的方式还需要装什么环境吗?
      如果要jdbc的驱动等环境那里可以下到?还有程序怎样写?
      --------------------------------
      
      如果用驱动桥的话就不需要另外安装别的东西
      在
      控制面版-->管理工具-->数据源(ODBC)-->SystemDSN
      中加入你的数据库映射,选好相应的数据库驱动
      然后就可以通过
      jdbc:odbc:设置好的DSN名
      的方式来连接数据库了
      ----------------------------------
      
      packageCBK00D.COMMON;
      /**
      *Title:
      *Description:
      *Copyright:Copyright(c)2001
      *Company:
      *@author
      *@version1.0
      */
      importjava.io.*;
      importjava.util.*;
      importjava.sql.*;
      importjava.lang.*;
      publicclassDBConnect{

    privateStringjdbcDriver=null;
      privateStringjdbcURL=null;
      privateStringuserName=null;
      privateStringpassword=null;
      publicDBConnect(){
      jdbcDriver="sun.jdbc.odbc.JdbcOdbcDriver";
      jdbcURL="jdbc:odbc:cbk";
      userName="system";
      password="manager";
      }
      publicConnectiongetConnection(){
      Connectionconnection=null;
      try{
      Class.forName(jdbcDriver);
      connection=DriverManager.getConnection(jdbcURL,userName,password);
      }catch(Exceptione){
      System.out.println(e);
      }
      returnconnection;
      }
      }
      这是普通的连接方法!只要修改一下就可以了。
      --------------------------------------
      
      似乎是这样的,要先rs.next()一下
      jdbc-odbc桥不好吗?
      
      JAVA连接数据库的方式有多种:
      根据所需要的不同数据库驱动分,分为四种:
      1:1类驱动。这就是JDBC-ODBC桥的方式。但这种方式不适合程序的重用与维护,不推荐使用。需要数据库的ODBC驱动。
      2:2类驱动。这就是JDBC+厂商API的形式。厂商API一般使用C编写,所以,这种方式也不长使用。
      3:3类驱动。这就是JDBC+厂商DatabaseConnectionServer+DataBase的形式。

    这种方法就是在JAVA与DATABASE之间价起了一台专门用与数据库连接的服务器(一般由数据库厂商提供)。他的好处在于能优化连接。
      4:4类驱动。这就是纯JDBC+DATABASE的连接方式。也是推荐的连接方式。这使得APPLICATION与数据库分开,开发者只需关心内部逻辑的实现而不需注重数据库连接的具体实现。在这其中有两种连接的方式:
      硬编码方式,就是在程序中硬性编入数据库连接的所须参数。
      JNDIDataSource方式。就是在程序运行的外布环境中又称(Context)设置一个datasource数据源,有一个jndi名称,程序只须查找此名称就可得到一个数据库连接的对象。
      =====================================
      jsp连接Oracle8/8i/9i数据库(用thin模式)
      testoracle.jsp如下:
      <%@pagecontentType="text/html;charset=gb2312"%>
      <%@pageimport="java.sql.*"%>
      <html>
      <body>
      <%Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
      Stringurl="jdbc:oracle:thin:@localhost:1521:orcl";
      //orcl为你的数据库的SID
      Stringuser="scott";
      Stringpassword="tiger";
      Connectionconn=DriverManager.getConnection(url,user,password);
      Statementstmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
      Stringsql="select*fromtest";
      ResultSetrs=stmt.executeQuery(sql);
      while(rs.next()){%>
      您的第一个字段内容为:<%=rs.getString(1)%>
      您的第二个字段内容为:<%=rs.getString(2)%>
      <%}%>
      <%out.print("数据库操作成功,恭喜你");%>
      <%rs.close();
      stmt.close();
      conn.close();
      %>
      </body>
      </html>
    JDK,Tomcat,Resin ... 配置 http://www.justjsp.com/main/sort.php/7
    Jsp,Servlet,JavaBean基础 http://www.justjsp.com/main/sort.php/2
    JDBC 数据库学习...    相关 http://www.justjsp.com/main/sort.php/3
    Struts    JSF...          框架 http://www.justjsp.com/main/sort.php/9

    目前网上的方法都是用一个mod_jk2.dll文件来整合,
    但我到官方网站却找不到,却找到mod_jk2.so的不同版本。
    http://apache.linuxforum.net/dist/jakarta/tomcat-connectors/jk2/binaries/win32/
    (jakarta-tomcat-connectors-jk2.0.4-win32-apache2.0.49.zip包)
    虽然mod_jk2.so有帮助文档,但E文一点也看不懂啊:)
    所以还是决定用mod_jk2.dll方法,在其它网站下载了mod_jk2.dll。
    结果花时一个晚上,用了网上近N个方法都以失败而告终!!!也许是各版本不同吧。
    今早灵感一来,用了mod_jk2.so一下子搞掂了。

    步骤:
    一、安装各软件包,并配置好环境变量。确认Tomcat5服务器的端口为8080,最好设有虚拟目录。
        安装Apahe Http Server2.0时,端口最好选:for All Users,onPort80--Recommended
        
    二、将mod_jk2.so复制到 [安装盘:]\Apache2\modules目录下

    三、打开[安装盘:]\Apache2\conf\httpd.conf
        将AddDefaultCharset ISO-8859-1改为

        LoadModule jk2_module modules/mod_jk2.so
        AddDefaultCharset GB2312
        DefaultLanguage GB2312
        AddLanguage zh-cn .cn

        使之自动支持中文并服务器启动时装载mod_jk2.so
     
    四、在 [安装盘:]\Apache2\conf目录下新建一个workers2.properties文件
        内容如下:
        [shm]
        file=${serverRoot}/logs/shm.file
        size=1048576
        # Example socket channel, override port and host.
        [channel.socket:localhost:8009]
        port=8009
        host=127.0.0.1
        # define the worker
        [ajp13:localhost:8019]
        channel=channel.socket:localhost:8009
        # Uri mapping
        [uri:/*]
        worker=ajp13:localhost:8009

    五、    
        启动Tomcat5
        IE输入http://localhost:8080测试是否成功
        或http://localhost:8080/(Tomact里设的虚拟目录)
        如果成功则完成99.9%了
       
        Restart再启动Apache Service.
        在IE输入http://localhost/
        应该显示的是http://localhost:8080/的页面
        测试是否整合成功:
        再次输入http://localhost/
               或http://localhost/(Tomact里设的虚拟目录)
        看是否跟http://localhost:8080
               或http://localhost:8080/(Tomact里设的虚拟目录)
        显示的效果一样
        如果一样则搞掂!!!
    总结:其实问题就是出在第四步中的[uri:/*] 设置
          很多方法在此设置虚拟目录如:[uri:/jsptest/*]
          然后在httpd.conf配置虚拟路径:
          增加:
          Alias /jsptest/ "C:/jsptest/"

          <Directory "C:/jsptest">
          Options Indexes MultiViews
          AllowOverride None
          Order allow,deny
          Allow from all
          </Directory>
          经测试用我的方法增加以上路径(前提是我用其它方法也不行哦)都是不行的!
          所以在第四步配置时应写:[uri:/*]
          改下都不行啊~~~~
    请问各位大侠,能够得到第五步的效果就算整合成功了吗???  为了证实能够得到第五步的效果(现在我只能这样说,
    因为我也不清楚现在是否真正整合成功没有?),
    我写完以上文章后,将Apache Service2.0卸载掉了,
    然后又把Apache Service2.0安装在其它目录,最后用本方法。
    同样能得到第五步的效果!!!    


    到网上下载以上三个软件并安装
    jdk1.4安装目录:D:/jdk14
    Tomcat5.0安装目录:D:/tomcat5
    SQL Server2000安装目录默认

    ///////////////////////////////////////////////

    一、设置环境变量

    Classpath

    D:\jdk14\lib\tools.jar;D:\jdk14\lib\dt.jar;
    D:\tomcat5\bin;D:\Program Files\
    Microsoft SQL Server 2000 Driver for JDBC\lib\msbase.jar;
    D:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\
    lib\mssqlserver.jar;
    D:\Program Files\Microsoft SQL Server 2000 Driver f or JDBC\
    lib\msutil.jar

    Java_home

    D:\jdk14

    Tomcat_home

    D:\tomcat5

    Path

    D:\Program Files\Microsoft SQL Server\80\
    Tools\BINN;D:\jdk14

    //////////////////////////////////////////////////

    二、Tomcat5的设置网站虚拟路径

    用记事本打开:[系统盘:]\tomcat5\conf\server.xml

    </host>之前加
    方法1:<Context path="/EnglishStars" docBase=
    "F:/strong_backup/work/EnglishStars" debug="0" reloadable="true">
    </Context>

    方法2:(为方便调试建议用此方法,网站端口设为80,
    如果你想保留Tomcat5的帮助信息网页,
    请用第一种方法):
    <Context path="" docBase="F:/strong_backup/work/EnglishStars"
    debug="0" reloadable="true"></Context>

    /////////////////////////////////////////////////

    三、端口设置

    Tomcat5网站端口默认为8080
    <Connector port="8080"   ………>
    为了调试方便,将它设为HTTP默认的端口80
    这时,请注意你的Internet 信息服务IIS
    (如果装有)已关闭。如果装有,它会每
    次跟着系统启动,将它设为手动即可!“控制面板”
    --->“管理工具”---->“组件服务”----->
    选中左边的“服务(本地)”----->打开右边
    “World Wide Web Publishing”的属性----->
    “常规”----->服务状态:点击“停用”----->
    在启动类型:选择“手动”--->“确定”

    ////////////////////////////////////////////////

    四、修改启用默认网页:

    用记事本打开:[系统盘:]\tomcat5\conf\server.xml
        <welcome-file-list>   
              <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    在此可以增删修默认网页文档

    为了调试方便,建议注释掉或删掉默认网页:
    <!--
          <welcome-file>index.jsp</welcome-file>
    -->
    打开网站时,会把当前文件夹下所有文件以列表形式显示
    点击相应的网页就可进行测试了。

    /////////////////////////////////////////////////

    五、启动Tomcat5

    打开:[系统盘:]\tomcat5\bin\startup.bat
    关闭:[系统盘:]\tomcat5\bin\shutdown.bat

    /////////////////////////////////////////////////

    六、测试网页:

    设置了虚拟目录方法1:
    <Context path="" docBase="F:/EnglishStars" ……>
    </Context>

    在地址栏输入(端口为80):http://localhost/
    在地址栏输入(端口为8080):http://localhost:8080/

    设置了虚拟目录方法2:
    <Context path="/EnglishStars" docBase="F:/EnglishStars" ……>
    </Context>
    在地址栏输入(端口为80):http://localhost/EnglishStars/
    在地址栏输入(端口为8080):http://localhost:8080/EnglishStars/

    ////////////////////////////////////////////////////

    七、测试与SQL server2000数据库连接代码

    数据库名:test
    表名:userinfo
    字段名:随便(本例3个以上)


    <%@    page  contentType="text/html;charset=gb2312"%>                 
    <%@    page  import="java.sql.*"%>         
    <html>                 
    <body>                 
    <%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver")
    .newInstance();                 
    String   
    url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test";         
    //user,password 分别为数据库的用户名及密码       
    String    user="sa";         
    String    password="";         
    Connection    conn=DriverManager.getConnection(url,user,password);                 
    Statement    stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);              
    String    sql="select  *  from  userinfo";                 
    ResultSet    rs=stmt.executeQuery(sql);                 
    while(rs.next())    {%>                 
    您的第一个字段内容为:<%=rs.getString(1)%><br>                 
    您的第二个字段内容为:<%=rs.getString(2)%><br> 
    您的第三个字段内容为:<%=rs.getString(3)%><br>                    
    <%}%>                 
    <%out.print("数据库连接成功!!!");%>                 
    <%rs.close();                 
    stmt.close();                 
    conn.close();                 
    %>                 
    </body>                 
    </html> 
    ////////////////////////////////////////////////////////


    WikiWiki 一词来源于夏威夷语?的“wee kee wee kee”,原本是“快点快点”的意思。在这里WikiWiki指一种超文本系统。这种超文本系统支持面向社群的协作式写作,同时也包括一组支持这种写作的辅助工具。我们可以在Web?的基础上对Wiki文本进行浏览、创建、更改,而且创建、更改、发布的代价远比HTML?文本为小;同时Wiki系统还支持面向社群的协作式写作,为协作式写作提供必要帮助;最后,Wiki的写作者自然构成了一个社群,Wiki系统为这个社群提供简单的交流工具。与其它超文本系统相比,Wiki有使用方便及开放的特点,所以Wiki系统可以帮助我们在一个社群内共享某领域的知识。

    1995年Cunningham?为了方便模式社群的交流建立了一个工具-波特兰模式?知识库(Portland Pattern Repository)。在建立这个系统的过程中,Ward Cunningham创造了Wiki的概念和名称,并且实现了支持这些概念的服务系统。这个系统是最早的Wiki系统。从1996年至2000年间,波特兰模式知识库围绕着面向社群的协作式写作,不断发展出一些支持这种写作的辅助工具,从而使Wiki的概念不断得到丰富。同时Wiki的概念也得到了传播,出现了许多类似的网站和软件系统。

    您现在访问的Wikipedia?是目前世界上最大的Wiki系统,它是一个基于Wiki和GNU FDL的百科全书网站系统。该系统于2001年1月投入运行,2001年2月超过1,000条条目,2001年7月超过10,000条条目,目前(2003年1月)已经接近100,000条条目。Wikipedia条目的迅速增长说明了Wikipedia系统的健壮,也说明了Wiki的概念是经得起验证的。

    Wiki的历史还不长,无论是Wiki概念自身,还是相关软件系统的特性,还都在热烈的讨论中;所以怎样的一个站点才能称得上是一个Wiki系统还是有争议的。与Wiki相关最近出现的技术还有blog/简|blog?,它们都降低了超文本?写作和发布的难度。这两者都与内容管理系统?关系紧密。

    Wiki的特点

    使用方便

    • 维护快捷:快速创建、存取、更改超文本页面(这也是为什么叫作 "wiki wiki" 的原因)。
    • 格式简单:用简单的格式标记来取代 HTML 的复杂格式标记。(类似所见即所得?的风格)
    • 链接方便:通过简单标记,直接以关键字名来建立链接(页面、外部连接、图像等)。
    • 命名平易:关键字名就是页面名称,并且被置于一个单层、平直的名空间中。

    有组织

    • 自组织的:同页面的内容一样,整个超文本的组织结构也是可以修改、演化的。
    • 可汇聚的:系统内多个内容重复的页面可以被汇聚于其中的某个,相应的链接结构也随之改变。

    可增长

    • 可增长:页面的链接目标可以尚未存在,通过点击链接,我们可以创建这些页面,从而使系统得到增长。
    • 修订历史:记录页面的修订历史,页面的各个版本都可以被获取。

    开放性

    • 开放的:社群的成员可以任意创建、修改、删除页面。
    • 可观察:系统内页面的变动可以被访问者观察到。

    参考文献

    External Linkhttp://c2.com/cgi/wiki?WikiHistory
    External Linkhttp://c2.com/cgi/wiki?WikiDesignPrinciples
    External Linkhttp://c2.com/cgi/wiki?WikiPrinciples
    External Linkhttp://c2.com/cgi/wiki?ElementsOfWikiEssence
    External Linkhttp://c2.com/cgi/wiki?WikiEssence
    External Linkhttp://c2.com/cgi/wiki?LinkNameIsPageName
    External Linkhttp://c2.com/cgi/wiki?WhyWikiWorks
    External Linkhttp://c2.com/cgi/wiki?WhyWikiWorksNot
    External Linkhttp://c2.com/cgi/wiki?InterWiki
    External Linkhttp://c2.com/cgi/wiki?WikiProgramming
    External Linkhttp://c2.com/cgi/wiki?WikiEngines

    Easy的大作:)

    近来设计模式风行,MVC随处可见,PHP领域也不例外,很多论坛都开始讨论在PHP中使用MVC。然而,MVCPHP中到底该如何实现?MVC真的适合PHP么?这里Easy给出一些自己的思考。

    MVC的原型

    MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将MV的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保MV的同步,一旦M改变,V应该同步更新。

    JAVA中的MVC

    JAVAMVC引入了Web领域,并在此基础上架构出了一套称为Model2的体系。由于Web的特殊性,JAVA中的MVCDesktop中的MVC并不完全一致。主要原因是Web中的V不是持续的,用户每访问一次,V就要重新生成一次,所以V始终是和M一致的,不需要C来控制同步。那么JAVA中的C在干什么?JAVA中的C通常用于流程的转向,其实用的是Dispatch模式,不再是Desktop中的C了。

     

    PHP中的MVC 

    要在PHP中原封不动的COPY JAVAMVC是不可能的。问题主要表现在M上,在JAVA中,M是独立于业务逻辑和表现逻辑的数据模型,在服务器端跨页面存在,JAVA Bean扮演的就是这个脚色。而PHP进程并不长时间驻留于内存,只在PHP页面开始执行时创建,在页面解释执行结束时就已经结束。在这样的情况下,我们根本无法直接实现M。所以所有声称实现了MVC模式的PHP程式都只能通过模拟手段来实现M。实现的方式一般是在当前页面结束前把数据存入数据库或者cookie/session,在下一个页面中再透过数据库或者cookie/session重建M。这样的方式和JAVA中的Bean比起来可以说是开销巨大,本来往内存中写数据的简单操作现在要从服务器端传到客户端或者数据库,然后再传回来。与其用这么大的开销来维护一个数据模型再在最后把这个模型塞回数据库,还不如直接根据需要更新数据库里边的数据。

    现在PHP中MVC架构可以用图一来表示。

    然后我们再来看V。现在很多PHP程序简单的使用了一些模板技术就在说明中写“采用MVC架构”。其实绝大多数的PHP模板程序都只是分离HTMLPHP的,而非MVC强调的显示逻辑和业务逻辑分离。一个混用HTMLPHP的页面一样可以是MVC的一部份。如何分离显示逻辑和业务逻辑至今没有一个满意的方案。我个人则比较认同http://www.phpe.net/articles/384.shtml的实现方案。至于C,和JAVA中差不多,还是被用作转向,这个在PHP中其实并不重要。

    一个极耗资源的M + 一个区别不大的V + 可有可无的C 构成了PHP中所谓的MVC。

    基于以上分析,Easy认为,PHP原有的3层构架比所谓的MVC更为高效,而3层构架中的表现层要解决的问题MVC中的V也同样存在。一个改进后的3层架构比MVC更适用于PHP。

    PS:有的方案把业务逻辑并入M中(http://www.phpe.net/articles/382.shtml),这其实是MVC的思想背道而驰的。


    书籍下载 http://www.mycnknow.com/c.htm

    c函数速查 http://www.easysea.com/diannao/prog/c/c/index.htm

    Linux下的c http://www.linuxfans.org/nuke/modules.php?name=News&file=article&op=view&sid=720

     


    Linux的最大的好处之一就是它的源码公开。同时,公开的核心源码也吸引着无数的电脑爱好者和程序员;他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标。
      Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题;或者是被你修改过了的内核,顺利通过编译,一切运行正常的时候。那种成就感真是油然而生!而且,对内核的分析,除了出自对技术的狂热追求之外,这种令人生畏的劳动所带来的回报也是非常令人着迷的,这也正是它拥有众多追随者的主要原因:
    • 首先,你可以从中学到很多的计算机的底层知识,如后面将讲到的系统的引导和硬件提供的中断机制等;其它,象虚拟存储的实现机制,多任务机制,系统保护机制等等,这些都是非都源码不能体会的。
    • 同时,你还将从操作系统的整体结构中,体会整体设计在软件设计中的份量和作用,以及一些宏观设计的方法和技巧:Linux的内核为上层应用提供一个与具体硬件不相关的平台;同时在内核内部,它又把代码分为与体系结构和硬件相关的部分,和可移植的部分;再例如,Linux虽然不是微内核的,但他把大部分的设备驱动处理成相对独立的内核模块,这样减小了内核运行的开销,增强了内核代码的模块独立性。
    • 而且你还能从对内核源码的分析中,体会到它在解决某个具体细节问题时,方法的巧妙:如后面将分析到了的Linux通过Botoom_half机制来加快系统对中断的处理。

    • 最重要的是:在源码的分析过程中,你将会被一点一点地、潜移默化地专业化。一个专业的程序员,总是把代码的清晰性,兼容性,可移植性放在很重要的位置。他们总是通过定义大量的宏,来增强代码的清晰度和可读性,而又不增加编译后的代码长度和代码的运行效率;他们总是在编码的同时,就考虑到了以后的代码维护和升级。 甚至,只要分析百分之一的代码后,你就会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余爱好者写的。而这一点是任何没有真正分析过标准代码的人都无法体会到的。
      然而,由于内核代码的冗长,和内核体系结构的庞杂,所以分析内核也是一个很艰难,很需要毅力的事;在缺乏指导和交流的情况下,尤其如此。只有方法正确,才能事半功倍。正是基于这种考虑,作者希望通过此文能给大家一些借鉴和启迪。

      由于本人所进行的分析都是基于2.2.5版本的内核;所以,如果没有特别说明,以下分析都是基于i386单处理器的2.2.5版本的Linux内核。所有源文件均是相对于目录/usr/src/linux的。

    方法之一:从何入手

      要分析Linux内核源码,首先必须找到各个模块的位置,也即要弄懂源码的文件组织形式。虽然对于有经验的高手而言,这个不是很难;但对于很多初级的Linux爱好者,和那些对源码分析很有兴趣但接触不多的人来说,这还是很有必要的。

      1、Linux核心源程序通常都安装在/usr/src/linux下,而且它有一个非常简单的编号约定:任何偶数的核心(的二个数为偶数,例如2.0.30)都是一个稳定地发行的核心,而任何奇数的核心(例如2.1.42)都是一个开发中的核心。

      2、核心源程序的文件按树形结构进行组织,在源程序树的最上层,即目录/usr/src/linux下有这样一些目录和文件:

    ◆ COPYING: GPL版权申明。对具有GPL版权的源代码改动而形成的程序,或使用GPL工具产生的程序,具有使用GPL发表的义务,如公开源代码;

    ◆ CREDITS: 光荣榜。对Linux做出过很大贡献的一些人的信息;

    ◆ MAINTAINERS: 维护人员列表,对当前版本的内核各部分都有谁负责;

    ◆ Makefile: 第一个Makefile文件。用来组织内核的各模块,记录了个模块间的相互这间的联系和依托关系,编译时使用;仔细阅读各子目录下的Makefile文件对弄清各个文件这间的联系和依托关系很有帮助;

    ◆ ReadMe: 核心及其编译配置方法简单介绍;

    ◆ Rules.make: 各种Makefilemake所使用的一些共同规则;

    ◆ REPORTING-BUGS:有关报告Bug 的一些内容;

    ● Arch/ :arch子目录包括了所有和体系结构相关的核心代码。它的每一个子目录都代表一种支持的体系结构,例如i386就是关于intel cpu及与之相兼容体系结构的子目录。PC机一般都基于此目录;

    ● Include/: include子目录包括编译核心所需要的大部分头文件。与平台无关的头文件在 include/linux子目录下,与 intel cpu相关的头文件在include/asm-i386子目录下,而include/scsi目录则是有关scsi设备的头文件目录;

    ● Init/: 这个目录包含核心的初始化代码(注:不是系统的引导代码),包含两个文件main.c和Version.c,这是研究核心如何工作的好的起点之一。

    ● Mm/:这个目录包括所有独立于 cpu 体系结构的内存管理代码,如页式存储管理内存的分配和释放等;而和体系结构相关的内存管理代码则位于arch/*/mm/,例如arch/i386/mm/Fault.c;

    ● Kernel/:主要的核心代码,此目录下的文件实现了大多数linux系统的内核函数,其中最重要的文件当属sched.c;同样,和体系结构相关的代码在arch/*/kernel中;

    ● Drivers/: 放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录:如,/block 下为块设备驱动程序,比如ide(ide.c)。如果你希望查看所有可能包含文件系统的设备是如何初始化的,你可以看drivers/block/genhd.c中的device_setup()。它不仅初始化硬盘,也初始化网络,因为安装nfs文件系统的时候需要网络;

    ● Documentation/: 文档目录,没有内核代码,只是一套有用的文档,可惜都是English的,看看应该有用的哦;

    ● Fs/: 所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统, 例如fat和ext2;

    ● Ipc/: 这个目录包含核心的进程间通讯的代码;

    ● Lib/: 放置核心的库代码;

    ● Net/: 核心与网络相关的代码;

    ● Modules/: 模块文件目录,是个空目录,用于存放编译时产生的模块目标文件;

    ● Scripts/: 描述文件,脚本,用于对核心的配置;

      一般,在每个子目录下,都有一个 Makefile 和一个Readme 文件,仔细阅读这两个文件,对内核源码的理解很有用。

      对Linux内核源码的分析,有几个很好的入口点:一个就是系统的引导和初始化,即从机器加电到系统核心的运行;另外一个就是系统调用,系统调用是用户程序或操作调用核心所提供的功能的接口。对于那些对硬件比较熟悉的爱好者,从系统的引导入手进行分析,可能来的容易一些;而从系统调用下口,则可能更合适于那些在dos或Uinx、Linux下有过C编程经验的高手。这两点,在后面还将介绍到。

    方法之二:以程序流程为线索,一线串珠

      从表面上看,Linux的源码就象一团扎乱无章的乱麻,其实它是一个组织得有条有理的蛛网。要把整个结构分析清楚,除了找出线头,还得理顺各个部分之间的关系,有条不紊的一点一点的分析。

      所谓以程序流程为线索、一线串珠,就是指根据程序的执行流程,把程序执行过程所涉及到的代码分析清楚。这种方法最典型的应用有两个:一是系统的初始化过程;二是应用程序的执行流程:从程序的装载,到运行,一直到程序的退出。

      为了简便起见,遵从循序渐进的原理,现就系统的初始化过程来具体的介绍这种方法。系统的初始化流程包括:系统引导,实模式下的初始化,保护模式下的初始化共三个部分。下面将一一介绍。

     ?inux系统的常见引导方式有两种:Lilo引导和Loadin引导;同时linux内核也自带了一个bootsect-loader。由于它只能实现linux的引导,不像前两个那样具有很大的灵活性(lilo可实现多重引导、loadin可在dos下引导linux),所以在普通应用场合实际上很少使用bootsect-loader。当然,bootsect-loader也具有它自己的优点:短小没有多余的代码、附带在内核源码中、是内核源码的有机组成部分,等等。

      bootsect-loader在内和源码中对应的程序是 /Arch/i386/boot/bootsect.S 。下面将主要是针对此文件进行的分析。
    1. 几个相关文件:

      <1> /Arch/i386/boot/bootsect.S

      <2> /include/linux/config.h

      <3> /include/asm/boot.h

      <4> /include/linux/autoconf.h
    2. 引导过程分析:

      对于Intel x86 PC , 开启电源后, 机器就会开始执行ROM BIOS的一系列系统测试动作,包括检查RAM,keyboard,显示器,软硬磁盘等等。执行完bios的系统测试之后,紧接着控制权会转移给ROM中的启动程序(ROM bootstrap routine);这个程序会将磁盘上的第0轨第0扇区(叫boot sector或MBR ,系统的引导程序就放在此处)读入内存中,并放到自0x07C0:0x0000开始的512个字节处;然后处理机将跳到此处开始执行这一引导程序;也即装入MBR中的引导程序后, CS:IP = 0x07C0:0x0000 。加电后处理机运行在与8086相兼容的实模式下。

      如果要用bootsect-loader进行系统引导,则必须把bootsect.S编译连接后对应的二进制代码置于MBR; 当ROM BIOS 把bootsect.S编译连接后对应的二进制代码装入内存后,机器的控制权就完全转交给bootsect; 也就是说,bootsect将是第一个被读入内存中并执行的程序。

      Bootsect接管机器控制权后,将依次进行以下一些动作:


      1.首先,bootsect将它"自己"(自位置0x07C0:0x0000开始的512个字节)从被ROM BIOS载入的地址0x07C0:0x0000处搬到0x9000:0000处; 这一任务由bootsect.S的前十条指令完成;第十一条指令“jmpi go,INITSEG”则把机器跳转到“新”的bootsect的“jmpi go,INITSEG”后的那条指令“go: mov di,#0x4000-12”;之后,继续执行bootsect的剩下的代码;在bootsect.S中定义了几个常量:

      BOOTSEG = 0x07C0 bios 载入 MBR的约定位置的段址;

      INITSEG = 0x9000 bootsect.S的前十条指令将自己搬到此处(段址)

      SETUPSEG =0x9020 装入Setup.S的段址

      SYSSEG =0x1000 系统区段址

      对于这些常量可参见/include/asm/boot.h中的定义;这些常量在下面的分析中将会经常用到;

      2.以0x9000:0x4000-12为栈底,建立自己的栈区;其中0x9000:0x4000-12到0x9000:0x4000的一十二个字节预留作磁盘参数表区;

      3.在0x9000:0x4000-12到0x9000:0x4000的一十二个预留字节中建立新的磁盘参数表,之所以叫“新”的磁盘参数表,是相对于bios建立的磁盘参数表而言的。由于设计者考虑到有些老的bios不能准确地识别磁盘“每个磁道的扇区数”,从而导致bios建立的磁盘参数表妨碍磁盘的最高性能发挥,所以,设计者就在bios建立的磁盘参数表的基础上通过枚举法测试,试图建立准确的“新”的磁盘参数表(这是在后继步骤中完成的);并把参数表的位置由原来的0x0000:0x0078搬到0x9000:0x4000-12;且修改老的磁盘参数表区使之指向新的磁盘参数表;

      4.接下来就到了load_setup子过程;它调用0x13中断的第2号服务;把第0道第2扇区开始的连续的setup_sects (为常量4)个扇区读到紧邻bootsect的内存区;,即0x9000:0x0200开始的2048个字节;而这四个扇区的内容即是/arch/i386/boot/setup.S编译连接后对应的二进制代码; 也就是说,如果要用bootsect-loader进行系统引导,不仅必须把bootsect.S编译连接后对应的二进制代码置于MBR,而且还得把setup.S编译连接后对应的二进制代码置于紧跟MBR后的连续的四个扇区中;当然,由于setup.S对应的可执行码是由bootsect装载的,所以,在我们的这个项目中可以通过修改bootsect来根据需要随意地放置setup.S对应的可执行码;

      5.load_setup子过程的唯一出口是probe_loop子过程;该过程通过枚举法测试磁盘“每个磁道的扇区数”;

      6.接下来几个子过程比较清晰易懂:打印我们熟悉的“Loading”;读入系统到0x1000:0x0000; 关掉软驱马达;根据的5步测出的“每个磁道的扇区数”确定磁盘类型;最后跳转到0x9000:0x0200,即setup.S对应的可执行码的入口,将机器控制权转交setup.S;整个bootsect代码运行完毕;
    3. 引导过程执行完后的内存印象图:


      出于简便考虑,在此分析中,我忽略了对大内核的处理的分析,因为对大内核的处理,只是此引导过程中的一个很小的部分,并不影响对整体的把握。完成了系统的引导后,系统将进入到初始化处理阶段。系统的初始化分为实模式和保护模式两部分。


    II、实模式下的初始化

      实模式下的初始化,主要是指从内核引导成功后,到进入保护模式之前系统所做的一些处理。在内核源码中对应的程序是 /Arch/i386/boot/setup.S;以下部分主要是针对此文件进行的分析。这部分的分析主要是要弄懂它的处理流程和INITSEG(9000:0000)段参数表的建立,此参数表包含了很多硬件参数,这些都是以后进行保护模式下初始化,以及核心建立的基础。

    1. 几个其它相关文件:

    <1> /Arch/i386/boot/bootsect.S

    <2> /include/linux/config.h

    <3> /include/asm/boot.h

    <4> /include/ asm/segment.h

    <5> /include/linux/version.h

    <6> /include/linux/compile.h

    2. 实模式下的初始化过程分析:





    INITSEG(9000:0000)段参数表:(参见Include/linux/tty.h)

    参数名

    偏移量(段址均为0x9000) 长度Byte

    参考文件

    PARAM_CURSOR_POS 0x0000 2 Arch/i386/boot/video.S
    extended mem Size 0x0002 2 Arch/i386/boot/setup.S

    PARAM_VIDEO_PAGE

    0x0004 2 Arch/i386/boot/video.S
    PARAM_VIDEO_MODE 0x0006 1 Arch/i386/boot/video.S
    PARAM_VIDEO_COLS 0x0007 1 Arch/i386/boot/video.S
    没用 0x0008 2 Include/linux/tty.h
    PARAM_VIDEO_EGA_BX 0x000a 2 Arch/i386/boot/video.S
    没用 0x000c 2 Include/linux/tty.h
    PARAM_VIDEO_LINES 0x000e 1 Arch/i386/boot/video.S
    PARAM_HAVE_VGA 0x000f 1 Arch/i386/boot/video.S
    PARAM_FONT_POINTS 0x0010 2 Arch/i386/boot/video.S
    PARAM_LFB_WIDTH 0x0012 2 Arch/i386/boot/video.S
    PARAM_LFB_HEIGHT 0x0014 2 Arch/i386/boot/video.S
    PARAM_LFB_DEPTH 0x0016 2 Arch/i386/boot/video.S
    PARAM_LFB_BASE 0x0018 4 Arch/i386/boot/video.S
    PARAM_LFB_SIZE 0x001c 4 Arch/i386/boot/video.S
    暂未用① 0x0020 4 Include/linux/tty.h
    PARAM_LFB_LINELENGTH 0x0024 2 Arch/i386/boot/video.S
    PARAM_LFB_COLORS 0x0026 6 Arch/i386/boot/video.S
    暂未用② 0x002c 2 Arch/i386/boot/video.S
    PARAM_VESAPM_SEG 0x002e 2 Arch/i386/boot/video.S
    PARAM_VESAPM_OFF 0x0030 2 Arch/i386/boot/video.S
    PARAM_LFB_PAGES 0x0032 2 Arch/i386/boot/video.S
    保留 0x0034--0x003f   Include/linux/tty.h
    APM BIOS Version③ 0x0040 2 Arch/i386/boot/setup.S
    BIOS code segment 0x0042 2 Arch/i386/boot/setup.S
    BIOS entry offset 0x0044 4 Arch/i386/boot/setup.S
    BIOS 16 bit code seg 0x0048 2 Arch/i386/boot/setup.S
    BIOS data segment 0x004a 2 Arch/i386/boot/setup.S
    支持32位标志④ 0x004c 2 Arch/i386/boot/setup.S
    BIOS code seg length 0x004e 4 Arch/i386/boot/setup.S
    BIOS data seg length 0x0052 2 Arch/i386/boot/setup.S
    hd0 参数 0x0080 16 Arch/i386/boot/setup.S
    hd0 参数 0x0090 16 Arch/i386/boot/setup.S
    PS/2 device 标志⑤ 0x01ff 1 Arch/i386/boot/setup.S


    * 注: ① Include/linux/tty.h : CL_MAGIC and CL_OFFSET here

      1. Include/linux/tty.h :
    unsigned char rsvd_size; /* 0x2c */ unsigned char rsvd_pos; /* 0x2d */

    ③ 0表示没有APM BIOS

    ④ 0x0002置位表示支持32位模式

    ⑤ 0表示没有,0x0aa表示有鼠标器


    III、保护模式下的初始化

      保护模式下的初始化,是指处理机进入保护模式后到运行系统第一个内核程序过程中系统所做的一些处理。保护模式下的初始化在内核源码中对应的程序是 /Arch/i386/boot/compressed/head.S 和 /Arch/i386/KERNEL/head.S ;以下部分主要是针对这两个文件进行的分析。
    1. 几个相关文件:

      <1.> /Arch/i386/boot/compressed/head.S

      <2.> /Arch/i386/KERNEL/head.S

      <3.> //Arch/i386/boot/compressed/MISC.c

      <4.> /Arch/i386/boot/setup.S

      <5.> /include/ asm/segment.h

      <6.> /arch/i386/kernel/traps.c

      <7.> /include/i386/desc.h

      <8.> /include/asm-i386/processor.h

    2. 保护模式下的初始化过程分析:

      一、/Arch/i386/KERNEL/head.S流程:



     
     

    二、/Arch/i386/boot/compressed/head.S流程:

    1. 从流程图中可以看到,保护模式下的初始化主要干了这样几件事:
        1. 解压内核到0x100000处、
        2. 建立页目录和pg0页表并启动分页功能(即虚存管理功能)、
        3. 保存实模式下测到的硬件信息到empty_zero_page、初始化命令缓存区、
        4. 检测cpu类型、检查协处理器、
        5. 重新建立gdt全局描述符表、和中断描述附表idt;
    2. 从页目录和pg0页表可以看出,0&#0;4M物理内存被用作系统区,它被映射到系统段线性空间的0&#0;4M和3G&#0;3G+4M;即系统可以通过访问这两个段来访问实际的0&#0;4M物理内存,也就是系统所在的区域;
    3. 本来在实模式下初始化时已经建立了全局描述符表gdt,而此处重新建立全局描述符表gdt则主要是出于两个原因:一个就是若内核是大内核bzimag,则以前建立的gdt,可能已经在解压时被覆盖掉了所以,在这个源码文件中均只采用相对转移指令jxx nf或jxx nb;二是以前建立的gdt是建立在实地址方式下的,而现在则是在启用保护虚拟地址方式之后建立的,也即现在的gdt是建立在逻辑地址(即线性地址)上的;
    4. 每次建立新的gdt后和启用保护虚拟地址方式后都必须重新装载系统栈和重新初始化各段寄存器:cs,ds,es,fs,gs;
    5. 从实模式下的初始化和保护模式下的初始化过程可以看出,linux系统由实模式进入到保护模式的过程大致如下:



    6.由于分页机制只能在保护模式下启动,不能在实模式下启动,所以第一步是必要的;又因为在386保护模式下gdt和idt是建立在逻辑地址(线性地址)上的,所以第三步也是必要的;
    7.经过实模式和保护模式下的初始后,主要系统数据分布如下:

    初始后主要系统数据分布表
    位置 系统数据 大小
    0x101000 页目录swapper_pg_dir 4K
    0x102000 页表pg0 4K
    0x103000 empty_bad_page 4K
    0x104000 empty_bad_page_table 4K
    0x105000 empty_zero_page 4K
    0x105000 系统硬件参数 2K
    0x105800 命令缓冲区 2K
    0x106000 全局描述附表gdt_table 4192B

      从上面对Linux系统的初始化过程的分析可以看出,以程序执行流程为线索、一线串珠,就是按照程序的执行先后顺序,弄懂程序执行的各个阶段所进行的处理,及其各阶段之间的相互联系。而流程图应该是这种分析方法最合适的表达工具。

      事实上,以程序执行流程为线索,是分析任何源代码都首选的方法。由于操作系统的特殊性,光用这种方法是远远不够的。当然用这种方法来分析系统的初始化过程或用户进程的执行流程应该说是很有效的。


    第1页,共2页