2008-07-25

Java中的数组

声明方式:
int[] arrayname;
String[] strs = new String[3];
...

初始化:
int[] arrayname = {88,22,33};
String[] strs = {"test1","ttttt","sdfi"};
对于多维数组:
int[][] twodem = {{1,2,3},{4,5,6}};
或者
int[][] twodem2 = new int [3][3];

但是在Java中多维数组的机制同C/C++有所不同,java不直接支持多维数组,而是用一维数组保存数组的引用来实现的。

在main方法中,其参数String[] args是一个String 对象数组。基本上和C中差不多。

另外,我们还可以构建可变长参数列表。
比如

public double average (int ... list)
{
  double result = 0.0;
  if ( list.length!=0)
  {
    int sum = 0;
    for(int num : list)
      sum+= num;
    result = (double)sum / list.length;
  }

  return result;
}

如果声明多个参数时,可变长参数列表必须放在最后一个,并且一个方法不允许两个可变长参数列表。

除了标准的数组之外,java中也有类似C++中vector类型的ArrayList类。
ArrayList定义在java.util包中。它是一个集合类。
声明:
ArrayList test = new ArrayList();
ArrayList test2 = new ArrayList();
之所以能这样是因为ArrayList是一种泛型。一般最好声明ArrayList的元素类型,否则需要麻烦的类型转换。ArrayList的一些方法:

方法名说明
ArrayList()
构造方法
boolean add(Object obj)
将obj对象插入尾部
void add(int index,Object obj)
将obj对象插入index处
void clear()
清空本列表
Object remove(int index)
删除index处的对象并返回该对象
Object get (int index)
返回index处的对象
int indexOf(Object obj)
返回obj第一次出现的索引位置
boolean contains(Object obj)
是否含有obj对象
boolean isEmpty()
是否为空
int size()
返回列表元素数量

2008-07-22

一些面向对象软件设计和软件工程的基础知识

  虽然目前对软工没爱,不过一些原则还是要知道的。
软件开发的四个基本步骤:

  • 建立软件需求
  • 软件设计
  • 实现软件设计
  • 软件测试
当然一般都是会有步骤重叠发生的拉。
  一般来说,在软件需求文档里面,会出现的一些名词,很可能就是我们要建立的类或对象。据此再确定出我们要设计的类,原则基本上就是,我们是应该将某一事物表达成一个对象还是另一个对象的基本属性。
  识别出类之后,需要给每个类分派职责。设计的初期没有必要为一个类指定所有的方法,常常只需要分派基本职责就够了。
  在Java中,不仅方法可以有静态属性,变量也可以。一个被声明为static的成员不同于实例变量(类的每一个实例都会创建不是static的变量的副本),静态变量是由所有类实例共享的。因此,任意实例对静态变量的修改在程序运行过程中都是累积的。
此外这里还有一些java的特性:
  • final常量经常使用static修饰,不过对类的所有对象来说,只是一个常量值。
  • 由于静态方法是脱离具体对象操作的,所以不能引用实例变量。实例变量只能存在于类的实例中,不过静态变量可以被静态方法引用。例子就是main方法只能访问静态变量或局部变量。
      


      在软件中,类之间的基本关系是依赖、聚合和继承。
      基本来说,依赖就是类A必须对类B的对象引用。聚合就是 has-a的关系,继承就是is-a的关系。
      有时候同一个类的对象之间也存在依赖性。比如String的concat方法。str3=str1.concat(str2)
      聚合的例子最好的表现就是一个帐户的类中用户名是String类
      
      一般,在设计方法的时候是写伪代码的。主要目的在不设计具体的语法细节时,分解复杂的目标。
      java是面向对象的语言,所以它支持多态性,也就是支持方法重载,实际上就是通过方法名相同,但是参数不同来判断调用哪个对应的方法。

      在java中,还有一个超级无敌有用的概念就是接口(interface)了。
      java中的接口被定义为一组公用的方法,通过这组方法与一个对象交互。
      接口是一组常量和抽象方法的几何,抽象方法之所以叫抽象就是因为这家伙没有实现,只是定义了名字,和C中的函数声明一样的语法规则。所以这东西不能实例化。
    比如Complexity的包含的两个抽象方法:setComplexity getComplextiy.

    public interface Complexity
    {
      public void setComplexity(int complexity);
      public int getComplexity();
    }
      一个类通过实现定义在接口的所有抽象方法来实现借口。实现借口的类必须在声明时加上implements 接口名。接口中也可以有final常量。实现接口的类对其有方法权限
      接口的存在实现了实现了强大的多态性。

    Java的条件与循环语句与C/C++不同之处

      总的来说,不同之处非常少,不过一些概念上有所区别。
      其中最关键的就是迭代器(iterator)了,迭代器是一种对象,提供了一些用于处理集合中元素的方法。换句话就是迭代器允许逐步遍历集合中的元素并根据需要与其进行交互。
      一般java的迭代器都使用Iterator借口来定义。通常迭代器包括hasNext方法和next方法,前者返回布尔值表示是否还有需要的元素,后者获得下一个需要的元素。所以前者常常用来作控制条件。因此,也就有了java中的一种for的用法:
    假设accountList是一个管理Account对象的迭代器对象。

    for(Account accs : accountList)
      System.out.println(accs);

    等价于:
    Account accs;
    while(accs.hasNext())
    {
      accs = accountList.next();
      System.out.println(accs);
    }

    df

    2008-07-20

    从上榜CEO看IT业变化

      上个月,《巴伦周刊》公布了它的年度全球CEO30强榜。同时也附带了评选原因,简略的看一看这些去年在全球大放异彩的CEO们我们能够从中看到这些企业的动向。这种体验不同于读到企业最新投资最新产品这样的新闻从小处体验出来的变化,而是往往从战略层面看到他们的掌舵人眼中的方向。
      就IT类和周边行业来说。基本上在这些CEO接手了公司之后都对公司进行了重大的变革,使得公司变得更加灵活,更具创新能力。去年虽然是全球经济相当不好受的一年。但是就IT及周边行业来说,仍然是急速变革,且新产品层出不穷的一年。
      基本上,上榜的几家公司还是可以分成几个类别的:

    硬件制造类:

    苹果CEO史蒂夫•乔布斯(Steven Jobs)
    惠普CEO马克·赫德(Mark Hurd)
    思科CEO约翰·钱伯斯(John Chambers)
    黑莓联席CEO吉姆·巴尔斯利(Jim Balsillie)和迈克·拉扎里迪斯(Mike Lazaridis)
    任天堂CEO岩田聪(Satoru Iwata)
      《巴伦周刊》给出的他们的上榜理由分别是:
    乔布斯:依然是天才人物,依然致力于开发绝对的超级产品。
    赫德:以创新让技术巨头再创辉煌。
    钱伯斯:深水静流
    御手洗富士夫:让佳能找到了业务重心
    岩田聪:他将视频游戏机推向千家万户。
      自从1997年重返APPLE之后乔布斯又再度发挥出他独特的创造力,大力改革APPLE,90年代末挽救苹果的iMac,本世纪初长盛不衰的摇钱树iPod,还有去年令业界为之震惊的iPhone,以及标示了APPLE野心的Apple TV,这些极致的设计,和让人们疯狂排队购买的产品,除了APPLE还有哪个公司能做得出来呢?
      狂妄与偏执确实是Jobs的特色,但是这也是硅谷成功者们之所以成功而必须的特质。Jobs现在不仅是APPLE的CEO,而且还是崇拜者眼中的神。
      自从1997年重返苹果以后,苹果市值增长了40倍,达到了1,130亿美元。这个有着天生的创新的基因的苹果凭借其天生的灵活性接下来也将越走越好
     
      而马克·赫德也从卡丽·费奥瑞娜(Carly Fiorina)手中接过了一个烂摊子,当时的惠普各项业绩严重衰退,在自己的市场内又受到日本公司的严重威胁。2005年赫德继任以来,他成功的在一年多的时间中让惠普再次坐上PC业务第一的宝座,他通过大刀阔斧的改革大幅度的削减成本,提升利润,并且大胆的进军打印业务,成功的拓展了业务范围。最终再次令惠普如日中天。
      不过,从原来的科技型企业转型成了现在的消费电子企业的惠普,是否能在这个高速竞争低利润的市场持续的增长呢?让我们拭目以待。

      思科的CEO钱伯斯是个具有宽广的胸怀和富有远见的人,在他的领导下,思科这家本来就是一个具有绝对优势的公司,在技术上永远保持这自身领域世界第一的位置。而且其利润率在硬件生产商中高居榜首。通过巧妙的对新技术公司的收购策略,思科必将在此领域作为一颗常青树。与钱伯斯本人不喜欢招摇的风格相比其强硬的手段果然不愧为静水深流这个上榜原因。

      黑莓的两位联席CEO创造了在西方广受欢迎的黑莓手机。彻底的改变了西方人的交流习惯。在这个手机将在一定程度上取代个人电脑在商务应用的时代。又怎么能不赚钱呢?

      这两年任天堂的Wii让任天堂赚的盆满钵满,凭借划时代的创意,以及新用户群体的开发,任天堂重振昔日雄风。

    软件服务类:

    IBMCEO帕尔米萨诺
    阿里巴巴CEO马云
      他们的上榜理由:
    帕尔米萨诺:让蓝色巨人闪耀光芒
    马云:他挤走了eBay
      帕尔米萨诺在前任手中接下了IBM之后,同样也面临着20世纪IT产业的剧烈变革,IBM要何去何从?他重组IBM的业务,出售PC部门,大举收购,把IBM打造成不折不扣的软件服务业巨头。至今,IBM仍然保持着惊人的高速增长。
      阿里巴巴可以说是中国互联网产业最辉煌的果实,不仅在本土打败了ebay,而且凭借旗下的支付宝和淘宝成功的在中国的C2C市场占有了绝对份额的,它的IPO也是继Google之后最大的,凭借着马云独特的风格与宽广胸怀,阿里巴巴将是未来一段时间内中国互联网行业的指路之星。

      从这些CEO和他们的公司最近的发展不难看出,在这个IT业急速发展的时代。只有能够适应急剧变化的环境,保有自己强大的创新能力才能一直坐稳宝座。
      三点动向:
    • 个人用户的日常应用日趋移动化
    • 硬件制造商的方向必须配合这个趋势
    • 网络化进一步发展必然使得基础设施供应商和服务提供商的竞争日益激烈且日益缩小

    2008-07-19

    创建自己的类

    以一个实例来展开吧:
    Main.java:

    public class Main
    {
      public static void main(String[] args)
      {
        int totalnu;
        Die die1 = new Die();
        Die die2 = new Die();

        die1.rotate();
        die2.rotate();

        totalnu=die1.getFaceValue() + die2.getFaceValue();
        System.out.println("The total number is "+ totalnu);
      }

    }

    Die.java:

    import java.util.Random;

    public class Die
    {
      private int faceValue;
      private Random radnu = new Random();

      public Die()
      {
        faceValue=1;
      }

      public int rotate()
      {
        faceValue = radnu.nextInt(6)+1;
        return faceValue;
      }

      public int getFaceValue()
      {
        return faceValue;
      }
    }


      按照面向对象编程的思想,类应该代表了有合理的状态和行为的对象,比如,这个例子中,骰子一定有一个向上的面,一个Die对象也有几种描述其行为的方法。
      Public Die()是Die类的构造方法,这种方法比较特殊,方法名必须与类名相同。当使用new 运算符创建一个新的Die类实例时,将调用Die构造方法。构造方法不能有返回值,其方法声明中绝对不能指定返回值,否则可能出现一些奇怪的错误。此外,不一定要为每个类创建构造方法。java会自动创建默认构造方法,不过一般不会影响创建的对象的内容。
      Die类中的其他方法定义了由Die对象提供的各种服务。
      一般类中的方法都应该在文档头部注释说明。

      面向对象程序设计的一个重要特性就是封装。这个类中,通过使用修饰符让类之外的代码无法访问或改变类内部声明的变量,就是封装。对于类的使用者来说,类只提供了接口,而它也只需关心接口的用法和使用目的,无须知道类是如何实现的。
      一般,类常常提供一些用于访问和修改实例的方法。类似于这个程序的getFaceValue的方法被称作访问器(accessor)方法,这种方法只读的访问实例数据。另外还有可能提供一些用于修改实例数据的方法,称作修改器(mutator)方法。这个程序不需要修改器。这里介绍这个的目的在于,一般我们构建这些方法的时候有一定的的命名惯例,例如,本例若有修改器则名为setFaceValue。

    java图形设计章节.交互式GUI基础

    交互式图形用户界面至少需要包括三种类型的对象:

    • 组建(component)
    • 时间(event)
    • 监听器(listener)

      GUI组件在上篇文章里基本介绍了一下。
      事件是一个对象,一般代表了用户的动作,比如按下某键。大部分组件都会根据用户的动作产生相应事件。
      监听器还是一个对象,它等待某个事件发生并作出某种反应。对于我们所关心的事件有必要编写监听器处理。
      总的来说,使用GUI需要:
    • 实例化并设置需要的组件。
    • 实现监听器类,定义某种事件发生是程序该采取的动作。
    • 建立监听器类于产生用户关心事件的组件之间的联系。
    基本上说,一个基于GUI来处理用户事件的程序可以称为“事件驱动”基本上只要对它的核心有所了解,剩下的只是查文档的工作了。 
     

      除了上面所说的外,一般,在我们的GUI设计之中最重要的就是使用布局管理器了,同样,布局管理器也是一个对象,负责在容器中安排组件,决定每个组件的大小和位置,当组件有变化时,布局管理器会根据自己的原则重排这些组件。
      在JAVA标准类库中定义了几种布局管理器:

    布局管理器
    排列原则
    Border
    将组件组织为五个区域:东西南北中
    Box
    将组件组织为单独一行或一列
    Card
    将组件按照区域组织,每次只有一个可见
    Flow
    从左往右组织,有需要就加一行
    Grid
    将组件组织到网格中

      一般可以调用容器的setLayout方法改变容器的布局管理器,只需要从下面简单的代码中就能够亲身体会到它们的不同了。注意这里用了一个标签窗格,这个东西就是Windows下我的电脑的属性里面上面一排标签实现的效果。

    MainDemo.java:
    import javax.swing.*;

    public class MainDemo
    {
      public static void main (String[] args)
      {
      JFrame frame = new JFrame("Demo for Layout");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JTabbedPane tabp = new JTabbedPane();
      tabp.addTab("Flow", new FlowPanel());
      tabp.addTab("Box", new BoxPanel());
      tabp.addTab("Grid", new GridPanel());
      tabp.addTab("Border",new BorderPanel() );

      frame.getContentPane().add(tabp);
      frame.pack();
      frame.setVisible(true);

      }

    }

    FlowPanel.java:

    import java.awt.*;
    import javax.swing.*;

    public class FlowPanel extends JPanel
    {
      public FlowPanel()
      {
        setLayout(new FlowLayout());

        setBackground(Color.BLACK);

        JButton FLOW1 = new JButton("BUTTON 1");
        JButton FLOW2 = new JButton("BUTTON 2");
        JButton FLOW3 = new JButton("BUTTON 3");
        JButton FLOW4 = new JButton("BUTTON 4");
        JButton FLOW5 = new JButton("BUTTON 5");

        add(FLOW1);
        add(FLOW2);
        add(FLOW3);
        add(FLOW4);
        add(FLOW5);

      }
    }

      其他几个文件内容和FlowPanel.java基本相同,发挥你的创造力自己写出来吧。
      实际上,这些东西用NetBeans或者其他IDE都可以十分简单的生成出来。不过,因为这几篇文章目的在于对GUI有一定的基础了解,所以有必要稍微花点时间。
      最后,关于容器有一个设计上的知识就是容器的层次结构。基本上,任何一个Java程序都有一个顶层容器,顶层容器包含一个或多个其他容器,其他这些容器又能包含其他容器,这里面的每个容器都有自己的布局管理器。这里从顶层的容器向下就是一个层次结构树。当程序出现可能影响布局的变化时,会依次询问每个布局管理器来调整变化。

    我们给学生们的Googley的建议

    声明:本文来自Google Offical Blog,本人仅是心血来潮而翻译。

    我们给学生们的Googley的建议:掌握学习的方法!
    作者:Karen



      管理学大师彼得 德鲁克发现,那些能够吸引有着最好的知识的员工的公司能够在竞争中保持着最大的优势。我们和其他那些同样富有远见的公司一样都尽力去雇佣这样的人才,那么,我们最看中的是什么呢?

      从最大的程度来说,我们看中能以非常规的的方法解决问题的能力,我们希望申请者能够把
    常规问题当作一个课题来解决。毕竟,那是绝大多数教育所关注的。但是,竞争中获得优势的机会常常蕴含于非常规问题中,解决这些问题需要创造性的思考和坚持不懈的精神。


      下面是一个真实的例子,我们的一个工程师团队曾经遇到过的一个挑战:

      为Google搜索引擎设计一个拼写检查功能,常规的解决方法可能是通过字典来处理请求,而创造性的非常规的解决方法是通过用户以前提交的请求内容来为新的用户发起的请求提供拼写建议。这个方法让我们可以修正字典里没有的关键词,进而帮助更多的用户(改善搜索体验)。

      我们是怎样找到这些非常规的解决者的呢?当然存在许多方面的因素,不过,我们首先注意的是:
    • 善于分析推理,Google是一个建立在数据分析处理之上的公司,当有问题提出的时候或者需要做出决定的的时候,我们首先从数据开始,这就意味着我们讨论我们知道的而不是我们认为我么知道的。
    • 沟通能力。只是列举和理解那些可用的证据不能祈祷什么作用,除非你能让你的同伴理解你的结论。
    • 热衷于实验,非常规问题需要非常规的解法,没有现成的公式能够帮你解决。一个设计的很好的实验需要一些列的处理,清晰的控制和细心的结果分析。有时一个实验结果能够推翻你喜欢的理论,所以,你需要能够接受那些结果,即使你不喜欢它。
    • 富有团队精神,事实上Google所有的项目都是有小团队进行的,队员们需要良好的团队协作能力,达到团队的期望。
    • 热情和领导能力,从专业的工作或者生活中:例如学习语言活保护森林,最主要的东西,用德鲁克先生的话来说,就是在你了解到你所做的有多么重要的思想下激励你的行动。

      这些特征不仅仅对于我们的事业很重要,而且对于所有事业都非常重要,包括政府、慈善部门和学术研究。我们充满希望的后辈面临的挑战是如何获得它们。教育常规人才很容易,但是教育创新人才相当困难。记住,技能要求是会变化:现在开发者用Python编写代码,而当我还是学生的时候,只有C是热门。但是,推理的需求却从未变化,所以我们相信必须学习极具挑战性的核心课程,比如数学、自然科学、人文科学。


      最后,记得一直挑战自我,因为学习不会因为你毕业而结束,事实上,在真实的世界里,虽然书后面不会印有那些棘手的问题的答案,但是所有的测试都是开卷的。你的成功决定于你从自由市场中获得的教训。学习已经被证实是一生的工作。



    本文由Jonathan Rosenberg提交
    Our Googley advice to students: Major in learning
    Author:Karen


    Management guru Peter Drucker noted that companies attracting the best knowledge workers will "secure the single biggest factor for competitive advantage." We and other forward-looking companies put a lot of effort into hiring such people. What are we looking for?

    At the highest level, we are looking for non-routine problem-solving skills. We expect applicants to be able to solve routine problems as a matter of course. After all, that's what most education is concerned with. But the non-routine problems offer the opportunity to create competitive advantage, and solving those problems requires creative thought and tenacity.

    Here's a real-life example, a challenge a team of our engineers once faced: designing a spell-checker for the Google search engine. The routine solution would be to run queries through a dictionary. The non-routine, creative solution is to use the query corrections and refinements that other users have made in the past to offer spelling suggestions for new queries. This approach enables us to correct all the words that aren't in the dictionary, helping many more users in the process.

    How do we find these non-routine savants? There are many factors, of course, but we primarily look for ...

    ... analytical reasoning. Google is a data-driven, analytic company. When an issue arises or a decision needs to be made, we start with data. That means we can talk about what we know, instead of what we think we know.

    ... communication skills. Marshalling and understanding the available evidence isn't useful unless you can effectively communicate your conclusions.

    ... a willingness to experiment. Non-routine problems call for non-routine solutions and there is no formula for success. A well-designed experiment calls for a range of treatments, explicit control groups, and careful post-treatment analysis. Sometimes an experiment kills off a pet theory, so you need a willingness to accept the evidence even if you don't like it.

    ... team players. Virtually every project at Google is run by a small team. People need to work well together and perform up to the team's expectations.

    ... passion and leadership. This could be professional or in other life experiences: learning languages or saving forests, for example. The main thing, to paraphrase Mr. Drucker, is to be motivated by a sense of importance about what you do.

    These characteristics are not just important in our business, but in every business, as well as in government, philanthropy, and academia. The challenge for the up-and-coming generation is how to acquire them. It's easy to educate for the routine, and hard to educate for the novel. Keep in mind that many required skills will change: developers today code in something called Python, but when I was in school C was all the rage. The need for reasoning, though, remains constant, so we believe in taking the most challenging courses in core disciplines: math, sciences, humanities.

    And then keep on challenging yourself, because learning doesn't end with graduation. In fact, in the real world, while the answers to the odd-numbered problems are not in the back of the textbook, the tests are all open book, and your success is inexorably determined by the lessons you glean from the free market. Learning, it turns out, is a lifelong major.

    Posted by Jonathan Rosenberg, Senior VP, Product Management

    2008-07-18

    动新20世纪末动画巡礼,难忘女角色

    很久以前从朋友的动感新势力那里找到的一张,不管什么时候看到总是让人觉的如此的怀念。。。

    使用一些标准类

    首先需要一些关于对象的基本知识:
      我们在声明一个基本类型值或者对象的时候,建立了两个变量,如:
    long test1;
    String test3;

      第一条语句建立了一个保存long型基本类型值的内存空间,第二条建立的是一个保存着指向String类型对象的引用,它并未保存对象的内容,而知识一个地址。这一点类似于C中声明一个字符指针。
      在Java中,要初始化对象,需要使用new运算符。比如要初始化上面那个test3。
    test3 = new String ("It's only a String");
      如上,new运算符建立对象后将调用类的构造方法初始化新对象。构造方法是一种特殊的方法,方法名和类名是一样的。
      对象在初始化之后才可以使用,这个时候可以通过直接用变量名来引用类的方法。

    test1=test3.length();
      一般,我们可以将声明对象引用变量和创建对象一起做:
    String test3 = new String ("It's only a String");
    此外,由于字符串超级常用,所以Java中简化了它的对象初始化写法。我们可以像C一样写:
    String test3="It's only a String";

      此外,还有一个和C类似的地方,在Java中,直接用"="的赋值也基本可以理解为用后者的值覆盖前者的值,因此也就有了所谓的变量别名了...可见Java中巧妙的隐藏起了指针。又让我们能使用到同样便捷的方法。
      这里值得一提的是,加入某个对象的所有引用都丢失了。Java环境会把它标识为垃圾,会自动释放,这一免去了我们释放内存的烦恼。

      在Java中我们常常要用到类库,有时候也称Java API,Java标准类库被划分成许多包,每个类都属于其中一个包。我们需要了解一下:

    包名
    包含的功能
    java.lang 主要含有与语言相关的类。java.lang包由解释程序自动加载,不需要显示说明

    java.io

    主要含有与输入/输出相关的类,这些类提供了对不同的输入和输出设备读写数据的支持,这些输入和输出设备包括键盘、显示器、打印机、磁盘文件等

    java.util

    包括许多具有特定功能的类,有日期、向量、哈希表、堆栈等,其中Date类支持与时间有关的操作
    java.awt
    提供绘图和建立图形用户界面的类
    AWT表示 Abstract Windowing Too

    java.swing

    扩展的AWT包

    java.net

    含有与网络操作相关的类,如TCP ScoketsURL等工具。

    java.applet

    含有控制HTML文档格式、应用程序中的声音等资源的类,其中Applet类是用来创建包含于HTMLApplet必不可少的类。
    java.beans 定义了应用程序编程接口(API),Java BeansJava应用程序环境的中性平台组件结构。
    java.math
    提供了大量的计算用的类
    java.rmi
    提供用于建立可以跨多个计算机的分布式程序,
    RMI表示Remote Method Invocation
    java.security
    执行安全限制
    java.sql
    提供与数据库交互的类
    java.text
    提供格式化的文本输出
    java.xml.parers
    用于处理XML文档
      当我们要使用某个类的时候就需要import 相应的包,Java支持直接使用*引用指定包中的所有类。类的归属关系请查阅java文档

      在很多情况下,当我们要同时处理基本数据类型和对象的时候很容易出问题,这个时候 封装类(wrapper)就相当有用,其实所谓的封装类就是基本数据类型的类版本。每种类型对于相应的封装类。
    如表:

    基本数据类型
    对应的封装类
    byte
    Byte
    short
    Short
    int
    Integer
    long
    Long
    float
    Float
    double
    Double
    char
    Character
    boolean
    Boolean
    void
    Void
    需要说明的是这里的Void类不能实例化,仅仅代表空引用。
    当涉及到基本数据类型与相应的封装类之间的赋值的时候java会自动包装和自动拆包。
    -------------------------------------------
    接下来是应该要掌握的一些基本类的用法:

    String类:

    方法原型
    说明
    String(String str)
    构造方法,用于建立一个新String对象,并用参数str的字符串来初始化它
    char chartAt(int index)
    返回指定索引位置的字符
    int compartTo(String str)
    返回一个整型值,正、0、负来表示本对象的字符串按字典顺序位置先于、等于或后于str对象的字符串
    String concat (String str)
    返回一个由本对象字符串和str拼接后的字符串
    boolean equals(String str)
    和str的字符串比较是否相同
    boolean equalsIgnoreCase(String str)
    上一个方法的不区分大小写版
    int length()
    返回本字符串包含的字符个数
    String replace(char oldChar,char newChar)
    将本对象字符串中所以和oldChar一样的子串用newChar替换
    String substring(int offset,int endIndex)
    将开始位置偏移offset个取子串返回
      在Java中,一旦建立了一个String对象其内容是不可变的,但是String类的方法可以返回新的String对象来产生新的字符串。所谓字符串所以同C中字符数组。

    Math类(java.lang):

    方法原型
    说明
    static int abs(int num)
    返回num的绝对值
    static double ceil(double num)返回不小于num的最小整数(返回值为double型)
    static double floor(double num)
    返回不大于num的最大整数(返回值为double型)
    static int max(int num1,int num2)
    求两个整数中最大数(另有针对long、float、double的方法)
    static int min(int num1,int num2)
    求两个整数中最小数(另有针对long、float、double的方法)
    static double random()取[0.0 , 1,0)之间的随机数
    static double sqrt(double a)

    求平方根
    static double sin(double angle)

    求d的sin值(另有求其他三角函数的方法如cos,tan,asin, acos, atan)angle为弧度。
    static double log(double x)
    求自然对数
    static double exp(double x)求e的x次幂
    static double pow(double a, double b)
    求a的b次幂

      值得注意的是,Math类的所有方法都是静态方法,(static方法,又称类方法),也就是说可以通过类名直接调用方法而无须先初始化对象。比如:

    double test1,test3,test5;
    test1=Math.sqrt(2);
    test3=Math.sin(0);
    test5=Math.random();


    Random类(java.util):


    方法原型
    说明
    Random()
    构造方法,创建一个新的伪随机数生成器。
    float nextFloat()
    返回一个分布在[0.0 , 1.0)之间的浮点随机数
    int nextInt()
    返回一个整形随机数,取值分布在int区间,包括正负
    int nextInt(int num)
    返回一个整形随机数取值分布在[0 , num-1]之间
    基本上,这个类在编写一些包含随机结果的程序中相当的有用。
    例如:

    Random test= new Random();
    int te1;
    float te2;
    te1=test.nextInt(100);
    te2=test.nextFloat();

    2008-07-17

    系统启动时LVM居然未激活

    最近rp相当底下,这次更新了一些包。之后重启发现又再度出现在fsck时出错进入维护模式了。看一下发现/dev/vgname/lvname不存在。
    因此推断肯定是在fsck时vg还没有激活,手动激活之后exit果然能正常启动。

    好了,知道问题出在那里就好解决了。
    我们找到启动脚本。编辑一下就好。。。
    在我的ubuntu下

    sudo gedit /etc/rcS.d/S30checkfs.sh

    在最前面加入:
    ##Activition lvm volume group
    /sbin/modprobe dm_mod
    /sbin/vgscan
    /sbin/vgchange -a y
    ##

    ok,重启下就解决了。。。。

    原理在于,我们需要在fsck这一步骤出错前。激活vg,这样才能通过这个步骤到下一个步骤 S35mountall.sh

    此外可以参考此片段:出自blog.chinaunix.net

    然后需要在系统启动脚本中加入激活LVM的命令
    并且必须在挂载/etc/fstab中的文件系统之前激活LVM,不然怎么挂载阿。^_^
    我写在了/etc/rc.d/init.d/mountfs这个脚本中,它的作用是
    在fsck检查各个分区后,将/分区及其他分区重新挂载成read-write的

    /sbin/vgscan -------->需要加入的两行
    /sbin/vgchange -a y

    mountfs脚本主要内容是:(传递start参数)

    echo "Remounting root file system in read-write mode..."
    mount -n -o remount,rw /
    echo "Recording existing mounts in /etc/mtab..."
    > /etc/mtab
    mount -f / || failed=1
    mount -f /proc || failed=1
    if grep -q '[[:space:]]sysfs' /proc/mounts ; then
    mount -f /sys || failed=1
    fi
    echo "Mounting remaining file systems..."
    ##############LVM##############
    /sbin/vgscan #------->在挂载其他文件系统之前
    /sbin/vgchange -a y #---->就激活了LVM,随后就挂载上啦
    mount -a -O no_netdev #--->依照/etc/fstab挂载FS

    这样系统启动时,就会激活LVM,并自动挂载上。

    一篇关于LVM的文章中说,将这两条命令加在了检查文件系统脚本中,但是我加在那里
    不成功,可能因为在checkfs时,系统是read-only的,而vgchange -a y
    需要写入数据却无法写入,所以不行.

    udev服务先于checkfs启动,并且通过mount -n -t ramfs ramfs /dev
    将/dev挂载成ramfs,完全在内存中活动,无论根分区是否可写,/dev都是可写的。
    莫非vgchange -a y 还要向其他位置写入数据?有待研究:)

    在其他的发行版中,如Red Hat,Mandrake中,检查根文件系统,依照/etc/fstab
    挂载各个文件系统,开启SWAP分区...等等,这些都是通过/etc/rc.d/rc.sysinit完成的
    而在LFS中则是将这个脚本 分成了若干的小脚本,然后逐一的运行它们。
    个人认为这样可以更直观的了解系统的启动过程,方便修改。
    所以在其他发行版中,激活lvm,就要写到/etc/rc.d/rc.sysinit中
    并且必须要在挂载/etc/fstab中文件系统之前激活。还要注意激活时,系统是rw的。

    最后我又在mountfs中添加了关闭VG的语句,这样可以
    在系统关机/重启的时候自动关闭VG。

    /sbin/vgchange -a n ------>添加这句

    当系统关机/重启时,mountfs会依照/etc/fstab卸载所有的文件系统:
    mountfs
    脚本内容 : (传递stop参数)

    echo "Unmounting all other currently mounted file systems..."
    umount -a -d -r -t noramfs
    /sbin/vgchange -a n # --->加在了这里

    在卸载LV卷后,才可以关闭VG,开始我加在了umount上面一行就不行。提示仍有LV在使用。

    其他发行版中,关闭VG要比激活VG容易多啦。只要加在halt/reboot这个服务脚本里就可以。
    其实只要卸载文件系统后的服务脚本都可以,随你喜欢了。 ^_^

    用Grub Splash图片给Grub增加一张背景图

    参考文章:http://ruslug.rutgers.edu/~mcgrof/grub-images/

    黑黑的Grub相当难看,像Solaris和Opensolaris那样有一个背景图片就好多了,
    虽然貌似有其他的程序也能提供这个功能,不过我个人只要用到grub splash就满足了。。。
    先装个包
    sudo apt-get install grub-splashimages
    去找个你想要的图片,这里有一些技巧,如果你希望能够让之后用来作背景的图片漂亮点的话就别直接用convert那个。。。
    直接用GIMP把图片保存成png格式,之后选图像→模式→索引填上14色,一般来说原来的图片如果颜色不是很丰富的话这个时候图片的效果还是可以接受的,之后直接保存成xpm格式的图片。
    more image.xpm
    如果看到类似:
    /* XPM */
    static char *10[] = {
    /* columns rows colors chars-per-pixel */
    "640 480 14 1",
    的信息则说明有效。
    然后
    gzip image.xpm
    就会压缩出一个image.xpm.gz 文件。
    在menu.lst文件里加一行:
    splashimage=(hd0,7)/boot/grub/splash.xpm.gz
    假设我已经把文件拷贝到/boot/grub/下了。。
    保存重启试试。。。

    2008-07-16

    wine中文乱码的有效解决方法

    即使到了1.01版仍然还是一装好打开就是一大片中文乱码啊。不过这个搜一下还是能找到有效的解决方法的:

    1. 初始设置

    运行 winecfg,把模拟的 Windows 系统设置为 Windows XP 或者 Windows 2000。

    2. 准备字体

    为了让 Windows 应用程序看上去更美观,所以需要 Windows 下面的字体。

    由于我已经将 simsun.ttc 复制到 /usr/share/fonts/windows/ 目录中了。所以我只需要在 ~/.wine/drive_c/windows/fonts/ 目录中为 simsun.ttc 创建一个符号连接:

    cd ~/.wine/drive_c/windows/fonts
    ln -s /usr/share/fonts/windows/simsun.ttc simsun.ttc
    ln -s /usr/share/fonts/windows/simsun.ttc simfang.ttc

    创建一个 simfang.ttc 是许多 Windows 应用默认使用 simfang.ttc 字体。
    3. 修改 ~/.wine/system.reg

    装好字体后,还要修改一下 Wine 的注册表设置,指定与字体相关的设置:

    gedit ~/.wine/system.reg

    (一定要使用 gedit 或其他支持 gb2312/utf8 编码的编辑器修改这些文件,否则文件中的中文可能变乱码)

    搜索: LogPixels
    找到的行应该是:[System\\CurrentControlSet\\Hardware Profiles\\Current\\Software\\Fonts]
    将其中的:
    "LogPixels"=dword:00000060

    改为:
    "LogPixels"=dword:00000070

    搜索: FontSubstitutes
    找到的行应该是:[Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes]
    将其中的:
    "MS Shell Dlg"="Tahoma"
    "MS Shell Dlg 2″="Tahoma"

    改为:
    "MS Shell Dlg"="SimSun"
    "MS Shell Dlg 2″="SimSun"

    4. 修改 ~/.wine/drive_c/windows/win.ini

    gedit ~/.wine/drive_c/windows/win.ini
    在文件末尾加入:

    [Desktop]
    menufontsize=13
    messagefontsize=13
    statusfontsize=13
    IconTitleSize=13


    5. 最关键的一步,网上很多文章中没有提到的一步──把下面的代码保存为zh.reg,然后终端执行regedit zh.reg。从Windows目录下的Fonts里的simsun.ttc复制到/home/user/.wine/drive_c/windows/fonts里面。
    代码:
    REGEDIT4

    [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes]
    "Arial"="simsun"
    "Arial CE,238"="simsun"
    "Arial CYR,204"="simsun"
    "Arial Greek,161"="simsun"
    "Arial TUR,162"="simsun"
    "Courier New"="simsun"
    "Courier New CE,238"="simsun"
    "Courier New CYR,204"="simsun"
    "Courier New Greek,161"="simsun"
    "Courier New TUR,162"="simsun"
    "FixedSys"="simsun"
    "Helv"="simsun"
    "Helvetica"="simsun"
    "MS Sans Serif"="simsun"
    "MS Shell Dlg"="simsun"
    "MS Shell Dlg 2"="simsun"
    "System"="simsun"
    "Tahoma"="simsun"
    "Times"="simsun"
    "Times New Roman CE,238"="simsun"
    "Times New Roman CYR,204"="simsun"
    "Times New Roman Greek,161"="simsun"
    "Times New Roman TUR,162"="simsun"
    "Tms Rmn"="simsun"

    实际上注意看一下,就能发现里面很多地方是自己随便设置的。。。

    我机器上Ubuntu 8.04配置LVM的经历

      虽然前天发的LVM2的介绍信息十分详尽,不过我自己在安装的过程中可没少吃苦头。。所幸我的机器本来就刚装系统,所以也不在乎一边一边重装尝试。
      本来,每次我在ubuntu下apt-get安装好LVM2和EVMS后奇怪的是重启之后我的系统除了挂载在/ 下的分区之外其他都在开机的fsck过程失败,也无法挂载,说无法使用资源,忙。。。之后系统进入维护模式,即使在这个模式下。mount里看到其他分区也没有挂载,但是即使用mount挂载也会提示无法使用,忙。(这几个分区我并未作为LVM的分区使用)。
      在liveCD下安装的时候可以哦嗯apt安装lvm2不过如果系统的某些目录被它的LV用了的话,系统是启动不了的。因为Ubuntu并未默认支持LVM。
      鼓捣了2天,最终只能用折衷的方法解决。
      系统安装的时候只用一个分区。之后装好以后制作lvm,把相应目录的东西拷贝到lvm分区下,之后自动挂在lvm分区。

    基本上。先选好几个要作为lvm分区的分区。最好在fdisk下把id改成8e,这里假设我用/dev/sda2 /dev/sda4

    sudo pvcreate /dev/sda2 /dev/sda4
    成功的话
    sudo pvscan
    会找到相应的东西。
    接下来创建VG
    sudo vgcreate vgname /dev/sda2 /dev/sda4
    成功的话
    sudo vgdisplay
    同样会显示相应的东西。
    之后创建LV
    lvcreate -L 8G -n lvname vgname
    同样查看属性:
    lvdisplay /dev/vgname/lvname
    弄好后格式化lv吧:
    mkfs.ext3 /dev/vgname/lvname
    最后就是挂载了。。。。

    至于在/dev/fstab里面的自动挂载选项基本上和其他一样。
    此外还稍微尝试了一下扩展lv
    基本上如下步骤:
    1. 初始化新的pv,假设我是/dev/sda8
      pvcreate /dev/sda8
    2. 增加到已有的VG
      vgextend vgname /dev/sda8
    3. 扩展已有的LV
      lvextend -L +3G /dev/vgname/lvname
    当然其实也可以用其他的VG来扩展LV.
    至于更高级的应用还是看前面那篇文章了。。。

    Linux的文件系统解析与使用

    恩。再转一帖,刚入门的朋友应该十分需要这篇文章的指点:
    原文:http://www.ibm.com/developerworks/cn/linux/l-roadmap/part6/index.html
    级别: 初级
    作者:Chris Walden (mailto:cmwalden@us.ibm.com?subject=第), 电子商务架构师, IBM Developer Relations
    使用分区和文件系统

    在 Linux 中文件和存储设备的使用与 Windows 中不同。虽然同样有文件和分层目录结构,但是除此以外您还需要建立一种不同的思维方式。


    清单 1. 目录结构




    没有驱动器字母!
      在 Linux 中没有驱动器字母,这确实相当有用。如果您曾经在复杂的网络环境中使用过 Windows 系统,并且运行这个系统的机器带有若干个设备,那么您可能会发现字母表中的字母不够用。在 Linux 中,只有一个文件结构。它以 root (/) 开始,所有的本地文件系统,所有本地设备,以及所有的远程文件系统都表示为这个结构中的子目录。
      当 Linux 第一次引导时,它根据 /etc/fstab 文件中的信息构建这个文件结构。Windows 为硬盘驱动器分区和其他存储设备分配驱动器字母,而 Linux 在 root 文件结构中为它们分配目录。这个分层的结构是完全可配置的,并且可以动态地修改。

    装载!
      将一个设备添加到文件系统中,术语上称为 装载。Linux 会自动装载一个 / (root) 文件系统。也可能会有一个单独的 /boot 文件系统,其中存放的是核心的内核引导文件。Linux 还将装载一些特殊的文件系统。交换分区并不表示为文件系统的一部分,但是内核会处理它。不过,其他特殊的文件系统,比如 proc,被看作是文件系统的常规部分,可以像普通文件一样对它进行处理。



    什么是 /proc?
    /proc 文件系统是 Windows 思想与 Linux 思想不同之处的极好示例。
    /proc 存储的是对正在运行的系统各个方面的虚拟描述。在那里有 IRQ 设置、内存使用、加载的设备驱动器、网络状态等很多信息。甚至有一个叫做
    /proc/kcore
    的文件,是所有用到的系统内存的虚拟描述。这里的每一个文件都可以像普通文件或二进制文件一样解析。可以编写某些文件来改变运行着的内核的行为,而不用重新引导。例如,为打开系统中启用的第一个以太网设备的
    IP 转发,您可以使用一个文件命令:
    echo 1 >
    /proc/sys/net/ipv4/conf/eth0/forwarding

    这种系统的主要好处在于,您只需要使用简单的脚本技术,就可以对您的正在运行的系统进行深入而有效的操作。
      其他文件系统,比如可移动的媒体或者远程文件系统,需要手工装载。装载一个文件系统时,您需要知道在 Linux 中对它进行引用的正确方法,还需要有一个空目录作为 装载点。对于可移动媒体,Linux 可能在安装时就为您创建了装载点。在 Red Hat Linux 中,cdrom 设备被设置装载到 /mnt/cdrom 目录。也就是说,当您将一张 CD 放入 CDROM 设备后,输入命令:
    mount /mnt/cdrom
      CD 就会被添加到文件系统中,CDROM 设备会被锁定以使它不会被意外弹出。只需要到 /mnt/cdrom 目录就可以访问 CD 中的内容。当不再使用 CD 时,您可以用下面的命令将它从文件系统中移除:
    umount /mnt/cdrom
      /mnt/cdrom 目录将变空,CDROM 设备的锁定被解除。您现在可以安全地弹出 CD。对其他可移动媒体也是如此,比如软盘驱动器 (/mnt/floppy)。
      运行不带参数的 mount 命令会显示出当前已装载的文件系统。

    /etc/fstab 文件
    设备与其装载点之间的关联关系在 /etc/fstab 中配置。这个文件可以直接修改,也可以由管理工具来维护。下面是一个 /etc/fstab 示例:
    理解 /etc/fstab

    /dev/hda5         ext3  defaults     1   1
    /dev/hda2  /boot     ext3  exec,dev,duid,rw 1   2
    /dev/hda6  swap     swap  defaults     0   0
    /dev/scd0  /mnt/cdrom  auto  ro,noauto,exec  0   0
    none     /dev/pts   devpts  id=5,mode=620 0   0
    none     /proc     proc  defaults     0   0
    none     /dev/shm   tmpfs  defaults    0   0

      每一行表示一个要装载的文件系统。第一列指出的是要装载的设备。第二列是装载点,也就是设备在文件系统中的位置。第三列指出了文件系统的类型。第四列是处理文件系统的选项。最后一列是文件系统的标志位。第一个数字是 1 或者 0,指定系统是否应该用 dump(系统备份的一个选项)进行复制。第二个数字是 0、1 或者 2,指定了在引导时检查文件系统的次序。0 表示完全不检查。1 表示要最先检查, root (/) 文件系统需要指定为 1。其他文件系统应该是 2。

      在上面列出的 fstab 文件中,root 文件系统位于第一个 IDE 硬盘驱动器的第五个分区中,这个分区是扩展分区的第一个逻辑驱动器。/boot 文件系统位于第一个 IDE 硬盘驱动器的第二个主分区中,其中存放的是内核启动文件。交换分区位于第一个 IDE 硬盘驱动器的第六个分区,也就是扩展分区的第二个逻辑驱动器。列表中的其他文件系统相应的设备是“none”。我们马上就要阐述这一问题。现在我们先来关注物理磁盘。

      第四列中的选项将随文件系统类型而不同。在上面的例子中,/ 和 /boot 的装载选项为“default”。也就是说,它们使用异步 I/O 以可读写方式自动装载。只有 root 可以装载或者缷载设备,但是用户可以执行二进制文件和使用“sticky bit”(稍后介绍)。文件系统将被作为块字符设备来处理。然而,对 /mnt/cdrom 来说,选项就不同了。它不会被自动装载,并且将会作为只读文件系统装载。用户将可以在该文件系统中执行脚本和程序。

    什么都是文件
      在 Linux 中,文件系统由类似于文件的名称来表示。在 /dev 目录下的所有文件都是称为 nodes 的特殊文件,它们通过设备驱动程序链接到物理设备。这就使得您可以做一些有趣的事情。例如,为制作一张 CD 的 ISO 映像,您可以使用 cp (copy) 命令:
    cp /dev/cdrecorder MyCD.iso
      这样复制的是一个二进制映像而不是 CD 的文件结构。
      以文件为中心的方法还允许您可以为设备名称指定有意义的别名。例如,通常有一个叫做 /dev/cdrom 的别名,指向物理 CDROM 设备,而这个设备通常是 /dev/hdc。 一旦创建了别名,您就可以通过 /dev/cdrom 访问那个设备,这样更好记。别名技术还允许您标准化脚本,使这些脚本可以在物理配置不同的系统上使用。

    添加文件系统
      在 /etc/fstab 文件中添加新的一行,您就可以将文件系统添加到 /etc/fstab。作为一个实际的例子,我有一个 RAID 设备,存储的是部门所用到的文件资源。这个设备中只有数据文件,并且保持与操作系统分离,这样在出现硬件故障时可以将它转移到另一个系统。RAID 已经配置好,在 Linux 中识别为 /dev/sdc,即第三个 SCSI 设备。在第一个分区上创建了带日志的 ext3 文件系统,这样我们通过 /dev/sdc1 就可以访问它。我希望在计算机引导时自动将这个 RAID 装载到文件系统中。
    我在 /etc/fstab 中添加了如下一行:
    dev/sdc1 /data ext3 defaults 0 0/
    这样在引导时 RAID 就会像 / 和 /boot 系统一样被装载。现在我只要再创建一个目录作为指定的装载点:
    mkdir /data
    一旦创建了这个空目录,我们可以将文件系统装载到它:
    mount /data
    RAID 现在关联到了 /data。如果系统被重新引导,/data 将自动装载。

    分区
    在 Linux 中分区与 Windows 中本质上相同。控制台命令 fdisk 可以创建和管理分区。当您使用 fdisk 时,您必须指明它要操作哪个设备。可使用命令 fdisk -l 来查看可用设备。 清单 2. 使用 fdisk

    [root@cmw-t30 root]# fdisk -l
    Disk /dev/hda: 240 heads, 63 sectors, 7752 cylinders
    Units = cylinders of 15120 * 512 bytes
     Device Boot  Start   End   Blocks    Id    System
    /dev/hda1      1     8    60448+   8e    Linux LVM
    /dev/hda2      9     15    52920    83    Linux
    /dev/hda3 *     16    1403   10493280  c   Win95 FAT32 (LBA)
    /dev/hda4      1404   7751   47990880  f   Win95 Ext'd (LBA)
    /dev/hda5      1404   5565   31464688+  83  Linux
    /dev/hda6      5566   5635   529168+   82  Linux swap
    /dev/hda7      5636   7751   15996928+  b   Win95 FAT32

      上面的清单来自于一台膝上型电脑,所以它显示的结构与服务器有些不同。它显示了一个有若干个分区的 IDE 硬盘驱动器。如果有其他设备,同样也将会被列出。例如,第二个 IDE 硬盘驱动器可能会显示为 /dev/hdb。
    指定一个设备再次运行 fdisk ,您会得到一个简短的提示。 清单 3. 对一个设备运行 fdisk
    [root@cmw-t30 root]# fdisk /dev/hda
    The number of cylinders for this disk is set to 7752.
    There is nothing wrong with that, but this is larger than 1024,
    and could in certain setups cause problems with:
    1) software that runs at boot time (e.g., old versions of LILO)
    2) booting and partitioning software from other OSs
    (e.g., DOS FDISK, OS/2 FDISK)
    Command (m for help):


    输入“m”可以查看命令菜单。您可以使用“p”来显示当前的分区表。您可以创建、删除和修改现有分区的类型。“l”将为您列出可用分区类型的完全列表。用“w”将您的修改写入到分区表并退出程序,或者使用“q”不保存修改而退出。一些修改会立即生效。有一些修改需要系统重新引导方能生效。
    Linux 下的分区规则与 Windows 中相同。您可以使用 4 个主分区,每个都可以成为扩展分区。
     
    文件系统类型
      Linux 可以处理内核所能识别的任何文件系统类型。相当多的类型是默认编译到内核中的,并且可以再添加新的文件系统。下面是一些重要的文件系统类型:
    • ext2:标准 Linux 文件系统
    • ext3:带日志的标准 Linux 文件系统
    • vfat:Microsoft 的 Fat32 文件系统
    • jfs:IBM 的日志文件系统
    • reiserfs:另一个流行的日志文件系统

    格式化分区

      分区创建完成后,用适当版本的 mkfs 命令对其进行格式化。文件系统将有其自己版本的 mkfs ,比如 mkfs.ext2 或者 mkfs.ext3 。这些助手脚本让您可以只需要指定分区就可以创建一个文件系统。下面是一些例子:>清单 4. 使用 mkfs

    # Create an ext2 file system on the third
    # parition of the first IDE hard drive
    mkfs.ext2 /dev/hda3
    # Create an ext3 file system on the first
    # partition of the 2nd SCSI hard drivemkfs.ext2
    mkfs.ext3 /dev/sdb1
    # Create a jfs file system in an extended
    # partition on the first IDE hard drive.
    mkfs.jfs /dev/hda5

      有一些高级的参数会影响分区如何格式化,但是对通常的用途来说,使用默认的参数就可以了。一旦分区经过了格式化,它就可以装载到 / 文件系统中。一个文件系统必须在被缷载后才可以重新格式化。其他文件系统工具


    让我们来看一看其他有用的工具。
    控制台工具
    有几个工具可以查看磁盘和文件系统的状态。
    df

      df 表示“disk free”。它会报告装载的文件系统上已用的和可用的磁盘空间的大小。有用的开关:
    检查磁盘空间
    df -h
    人类可读的格式;以易读的 k、M、G 而不是以字节为单位来显示文件的大小
    df -l
    仅列出本地文件系统;默认情况下,远程文件系统也会被列出
    du

      du 表示“disk usage”。它会报告特定的文件和每个子目录 (参数中指定的目录) 所使用的磁盘空间大小。有用的开关:
    检查磁盘使用情况
    du -a
    列出所有文件所占的空间,而不仅是目录
    du -h
    人类可读的格式;以易读的 k、M、G 而不是以字节为单位来显示文件的大小
    du -c
    在所有的参数处理完成后输出一个总计;可以用来得到给定的一组文件或目录所占的总的磁盘空间
    du -s
    只显示出每个参数指定的文件大小的总和


    fsck

      这个程序用来检查和修复文件系统,相当于 Windows 中的 chkdsk 。如同 mkfs 一样,对应不同的文件系统类型它有不同的版本。 fsck 必须运行于已缷载的卷上,虽然除非是在文件系统没有缷载完全的时候,否则很少会用到它。 man fsck 和 info fsck ,以及本文最后的 参考资料中都提供了详细的资料。

    完整的体系是分区的总和
    虽然在 Linux 中对分区和文件系统的管理与 Windows 中有很多类似之处,但是从驱动器字母过渡到完全的分层树可能还需要作一些调整。因此,有一些健壮的控制台工具可以使用这些功能及 /etc 目录下的配置文件。

    2008-07-15

    Openoffice幻灯片的3D切换包

    OpenOffice 2.4 的一个重要新功能就是在幻灯演示工具 Impress 上增加了3D变换的功能。但是这个新的幻灯片过渡效果没有包含在默认安装中。
    sudo apt-get install openoffice.org-ogltrans
    可以安装这个功能。效果看:

    2008-07-14

    无奈的启用LVM了。。。

    相当无奈,装系统的时候没注意到挂了/usr的分区大小。。现在满了。。。剩下另外一个分区格式又不同。。。只能用LVM来处理了。。。

    原文链接:http://www.ibm.com/developerworks/cn/linux/l-lvm2/
    级别: 中级
    作者:Klaus Heinrich Kiwi (mailto:klausk@br.ibm.com?subject=逻辑卷管理), 软件开发工程师, IBM
    卷管理在 -ix 环境(UNIX、AIX 等等)中并不是新特性。逻辑卷管理(logical volume management,LVM)在 Linux 内核
    2.4v1 和 2.6.9v2 中就已经出现了。 本文讨论 LVM2 最有用的特性(LVM2
    是一个相当新的用户空间工具集,它提供逻辑卷管理功能),并提供几种简化系统管理任务的方法。
      逻辑卷管理(LVM)指系统将物理卷管理抽象到更高的层次,常常会形成更简单的管理模式。通过使用 LVM,所有物理磁盘和分区,无论它们的大小和分布方式如何,都被抽象为单一存储(single storage)源。例如,在图 1 所示的物理到逻辑映射布局中,最大的磁盘是 80GB 的,那么用户如何创建更大(比如 150GB)的文件系统呢?

    图 1. 物理到逻辑的映射


      LVM 可以将分区和磁盘聚合成一个虚拟磁盘(virtual disk),从而用小的存储空间组成一个统一的大空间。这个虚拟磁盘在 LVM 术语中称为卷组(volume group)。

      建立比最大的磁盘还大的文件系统并不是这种高级存储管理方法的惟一用途。
      还可以使用 LVM 完成以下任务:
    • 在磁盘池中添加磁盘和分区,对现有的文件系统进行在线扩展
    • 用一个 160GB 磁盘替换两个 80GB 磁盘,而不需要让系统离线,也不需要在磁盘之间手工转移数据
    • 当存储空间超过所需的空间量时,从池中去除磁盘,从而缩小文件系统
    • 使用快照(snapshot)执行一致的备份(本文后面会进一步讨论
      LVM2 是一个新的用户空间工具集,它为 Linux 提供逻辑卷管理功能。它完全向后兼容原来的 LVM 工具集。在本文中,将介绍 LVM2 最有用的特性以及几种简化系统管理任务的方法。(随便说一句,如果您正在寻找关于 LVM 的基本指南,那么可以看看 参考资料 中列出的 LVM HowTo。)
    LVM 的结构
    LVM 被组织为三种元素:
    • 卷(Volume):物理、逻辑卷和卷。
    • 区段(Extent):物理和逻辑区段。
    • 设备映射器(Device mapper):Linux 内核模块。
      Linux LVM 组织为物理卷(PV)、卷组(VG)和逻辑卷(LV)。物理卷是物理磁盘或物理磁盘分区(比如 /dev/hda 或 /dev/hdb1)。卷组是物理卷的集合。卷组可以在逻辑上划分成多个逻辑卷。 图 2 显示一个三个磁盘构成的布局。

    图 2. 物理到逻辑卷的映射

      物理磁盘 0 上的所有四个分区(/dev/hda[1-4])以及完整的物理磁盘 1(/dev/hdb)和物理磁盘 2(/dev/hdd)作为物理卷添加到卷组 VG0 中。

      卷组是实现 n-to-m 映射的关键(也就是,将 n 个 PV 看作 m 个 LV)。在将 PV 分配给卷组之后, 就可以创建任意大小的逻辑卷(只要不超过 VG 的大小)。在图 2 的示例中,创建了一个称为 LV0 的卷组,并给其他 LV 留下了一些空间(这些空间也可以用来应付 LV0 以后的增长)。

      LVM 中的逻辑卷就相当于物理磁盘分区;在实际使用中,它们就是 物理磁盘分区。

      在创建 LV 之后,可以使用任何文件系统对它进行格式化并将它挂载在某个挂载点上,然后就可以开始使用它了。图 3 显示一个经过格式化的逻辑卷 LV0 被挂载在 /var。

    图 3. 物理卷到文件系统的映射


    区段

      为了实现 n-to-m 物理到逻辑卷映射,PV 和 VG 的基本块必须具有相同的大小;这些基本块称为物理区段(PE)和逻辑区段(LE)。尽管 n 个物理卷映射到 m 个逻辑卷,但是 PE 和 LE 总是一对一映射的。

      在使用 LVM2 时,对于每个 PV/LV 的最大区段数量并没有限制。默认的区段大小是 4MB,对于大多数配置不需要修改这个设置,因为区段的大小并不影响 I/O 性能。但是,区段数量太多会降低 LVM 工具的效率,所以可以使用比较大的区段,从而降低区段数量。但是注意,在一个 VG 中不能混用不同的区段大小,而且用 LVM 修改区段大小是一种不安全的操作,会破坏数据。所以建议在初始设置时选择一个区段大小,以后不再修改

      不同的区段大小意味着不同的 VG 粒度。例如,如果选择的区段大小是 4GB,那么只能以 4GB 的整数倍缩小或扩展 LV。

    图 4 用 PE 和 LE 显示与前一个示例相同的布局(VG0 中的空闲空间也由空闲 LE 组成,尽管图中没有显示它们)。

    图 4. 物理到逻辑区段的映射

      另外,请注意图 4 中的区段分配策略。LVM2 并非总是连续分配 PE;细节参见关于 lvm 的 Linux 手册页(见 参考资料 中的链接)。系统管理员可以设置不同的分配策略,但是一般不需要这么做,因为默认策略(名为一般分配策略(normal allocation policy))使用符合常规的规则,比如不把并行的条带放在同一物理卷上。

      如果决定创建第二个 LV(LV1),那么最终的 PE 布局可能像图 5 这样。

    图 5. 物理到逻辑区段的映射

    设备映射器

      设备映射器(也称为 dm_mod)是一个 Linux 内核模块(也可以是内置的),最早出现在 2.6.9 内核中。它的作用是对设备进行映射 —— LVM2 必须使用这个模块。

      在大多数主流发行版中,设备映射器会被默认安装,常常会在引导时或者在安装或启用 LVM2/EVMS 包时自动装载(EVMS 是一种替代 LVM 的工具,更多信息见 参考资料)。如果没有启用这个模块,那么对 dm_mod 执行 modprobe 命令,在发行版的文档中查找在引导时启用它的方法:modprobe dm_mod。

      在创建 VG 和 LV 时, 可以给它们起一个有意义的名称(而不是像前面的示例那样使用 VG0、LV0 和 LV1 等名称)。设备映射器的作用就是将这些名称正确地映射到物理设备。对于前面的示例,设备映射器会在 /dev 文件系统中创建下面的设备节点:

    • /dev/mapper/VG0-LV0
    • /dev/VG0/LV0 是以上节点的链接
    • /dev/mapper/VG0-LV1
    • /dev/VG0/LV1 是以上节点的链接

    (注意名称的格式标准:/dev/{vg_name}/{lv_name} -> /dev/mapper/{vg_name}-{lv_name})

      与物理磁盘相反,无法直接访问卷组(这意味着没有 /dev/mapper/VG0 这样的文件,也不能执行 dd if=/dev/VG0 of=dev/VG1)。常常使用 lvm(8) 命令访问卷组。

    常见任务

      在使用 LVM2 时常常执行的任务包括系统检验(是否安装了 LVM2)以及创建、扩展和管理卷。

    以下开始涉及具体设置

    系统准备好运行 LVM2 了吗?

      检查您的 Linux 发行版是否安装了 LVM2 软件包。如果还没有,就安装它(最好安装发行版附带的软件包)。

      设备映射器模块必须在系统启动时装载。用 lsmod grep dm_mod 命令检查当前是否装载了这个模块。如果没有装载,那么可能需要安装并配置更多的软件包(文档会说明如何启用 LVM2)。

      如果只是想测试一下(或者挽救某个系统),那么可以使用以下命令启动 LVM2:

    清单 1. 启动 LVM2 的基本命令

    #this should load the Device-mapper module

    modprobe dm_mod

    #this should find all the PVs in your physical disks

    #this should activete all the Volume Groups

    vgchange -ay

      如果打算将根文件系统放在一个 LVM LV 中,那么还要注意 initial-ramdisk 映像。同样,发行版常常会负责处理这个问题 —— 在安装 LVM2 包时,它们常常会重新构建或更新 initrd 映像,在其中添加适当的内核模块和启动脚本。但是,可能需要查看发行版的文档,确保系统支持 LVM2 根文件系统。

      注意,通常只有当探测到根文件系统在一个 VG 中时,initial-ramdisk 映像才会启用 LVM。这种探测常常是通过分析 root= 内核参数执行的。不同的发行版以不同的方式判断根文件系统是否在卷组中。细节参见发行版的文档。如果不确定的话,就需要检查 initrd 或 initramdisk 的配置。

    创建新的卷

      使用您喜欢的分区工具(比如 fdisk、parted 或 gparted),创建一个供 LVM 使用的新分区。尽管 LVM 支持在整个磁盘上使用 LVM,但是不 建议这么做:其他操作系统可能认为这个磁盘没有初始化,可能会破坏它!更好的方法是创建一个覆盖整个磁盘的分区。 qm7Linux

      大多数分区工具常常默认使用分区 ID 0x83(或 Linux)来创建新分区。可以使用这个默认 ID,但是为了便于组织,最好将它改为 0x8e(或 Linux LVM)。

      在创建分区之后,应该会在分区表中看到一个(或多个)Linux LVM 分区:

    root@klausk:/tmp/a# fdisk -l

    Disk /dev/hda: 80.0 GB, 80026361856 bytes 255 heads, 63 sectors/track, 9729 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System

    /dev/hda1 * 1 1623 13036716 7 HPFS/NTFS

    /dev/hda2 1624 2103 3855600 8e Linux LVM

    /dev/hda3 2104 2740 5116702+ 83 Linux

    /dev/hda4 3000 9729 54058725 5 Extended

    /dev/hda5 9569 9729 1293232+ 82 Linux swap / Solaris

    /dev/hda6 3000 4274 10241374+ 83 Linux

    /dev/hda7 4275 5549 10241406 83 Linux

    /dev/hda8 5550 6824 10241406 83 Linux

    /dev/hda9 6825 8099 10241406 83 Linux

    /dev/hda10 8100 9568 11799711 8e Linux LVM

    Partition table entries are not in disk order

    root@klausk:/tmp/a#

    现在用 pvcreate 对每个分区进行初始化:

    清单 2. 分区初始化

    root@klausk:/tmp/a# pvcreate /dev/hda2 /dev/hda10

    Physical volume "/dev/hda2" successfully created

    "/dev/hda10" successfully created

    root@klausk:/tmp/a#

    在一个步骤中同时创建 PV 和 VG:vgcreate:

    清单 3. 创建 PV 和 VG

    root@klausk:~# vgcreate test-volume /dev/hda2 /dev/hda10

    Volume group "test-volume" successfully created

    root@klausk:~#

      上面的命令创建一个称为 test-volume 的逻辑卷,它使用 /dev/hda2 和 /dev/hda10 作为最初的 PV。

      在创建 VG test-volume 之后,使用 vgdisplay 命令查看刚创建的 VG 的基本信息:

    清单 4. 查看刚创建的 VG 的基本信息

    root@klausk:/dev# vgdisplay -v test-volume
    Using volume group(s) on command line
    Finding volume group "test-volume"
    --- Volume group ---
    VG Name test-volume
    System ID
    Format lvm2
    Metadata Areas 2
    Metadata Sequence No 1
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 0
    Open LV 0
    Max PV 0
    Cur PV 2
    Act PV 2
    VG Size 14.93 GB
    PE Size 4.00 MB
    Total PE 3821
    Alloc PE / Size 0 / 0
    Free PE / Size 3821 / 14.93 GB
    VG UUID lk8oco-ndQA-yIMZ-ZWhu-LtYX-T2D7-7sGKaV

    --- Physical volumes ---
    PV Name /dev/hda2
    PV UUID 8LTWlw-p1OJ-dF6w-ZfMI-PCuo-8CiU-CT4Oc6
    PV Status allocatable
    Total PE / Free PE 941 / 941

    PV Name /dev/hda10
    PV UUID vC9Lwb-wvgU-UZnF-0YcE-KMBb-rCmU-x1G3hw
    PV Status allocatable
    Total PE / Free PE 2880 / 2880

    root@klausk:/dev#


      在清单 4 中,可以看到有两个 PV 被分配给这个 VG,总大小为 14.93GB,有 3,821 个 4MB 的 PE,这些 PE 都是空闲的!

      既然卷组已经准备好了,就可以像使用磁盘一样用它创建分区(LV)、删除分区和重新设置分区大小 —— 注意,卷组是一个抽象实体,只有 LVM 工具集能够看到它们。使用 lvcreate 创建一个新的逻辑卷:

    清单 5. 创建新的逻辑卷(分区)

    root@klausk:/# lvcreate -L 5G -n data test-volume

    Logical volume "data" created

    root@klausk:/#

    清单 5 创建一个名为 data 的 5GB LV。创建这个 LV 之后,可以检查它的设备节点:

    清单 6. 检查 LV 的设备节点

    root@klausk:/# ls -l /dev/mapper/test--volume-data

    brw-rw---- 1 root disk 253, 4 2006-11-28 17:48 /dev/mapper/test--volume-data

    root@klausk:/# ls -l /dev/test-volume/data

    lrwxrwxrwx 1 root root 29 2006-11-28 17:48 /dev/test-volume/data ->

    /dev/mapper/test--volume-data

    root@klausk:/#

    还可以用 lvdisplay 命令查看 LV 的属性:

    清单 7. 查看 LV 的属性
    root@klausk:~# lvdisplay /dev/test-volume/data
    --- Logical volume ---
    LV Name /dev/test-volume/data
    VG Name test-volume
    LV UUID FZK4le-RzHx-VfLz-tLjK-0xXH-mOML-lfucOH
    LV Write Access read/write
    LV Status available
    # open 0
    LV Size 5.00 GB
    Current LE 1280
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 253:4
    root@klausk:~#

      在这里可以看到,在实际使用时 LV 的名称/路径是 /dev/{VG_name}/{LV_name},比如 /dev/test-volume/data。除了用作 /dev/{VG_name}/{LV_name} 链接的目标之外,不应该在其他地方使用 /dev/mapper/{VG_name}-{LV_name} 文件。大多数 LVM 命令要求以 /dev/{vg-name}/{lv-name} 格式指定操作的目标。

    建立逻辑卷之后,可以使用任何文件系统对它进行格式化,然后将它挂载在某个挂载点上:

    root@klausk:~# mkfs.reiserfs /dev/test-volume/data
    root@klausk:~# mkdir /data
    root@klausk:~# mount -t reiserfs /dev/test-volume/data /data/
    root@klausk:~# df -h /data
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/test--volume-data
    5.0G 33M 5.0G 1% /data
    root@klausk:~#

    还可以编辑 fstab(5) 文件,从而在引导时自动挂载这个文件系统:

    清单 9. 自动挂载

    #mount Logical Volume 'data' under /data

    /dev/test-volume/data /data reiserfs defaults 0 2

    在实际使用中,逻辑卷的表现就像一个块设备,比如可以将它用作数据库的原始分区。实际上,如果希望对数据库执行一致的备份,那么使用 LVM 快照是标准的最佳实践。

    扩展

      扩展卷是非常容易的。如果卷组中有足够的空闲空间,那么只需使用 lvextend 来扩展卷,不需要卸载它。然后,还要扩展逻辑卷中的文件系统(请记住,它们是两回事儿)。根据所用文件系统的不同,也可以进行在线扩展(即在挂载状态下进行扩展)。

      如果 VG 中没有足够的空间,那么首先需要添加更多的物理磁盘。步骤如下

    • 使用一个物理磁盘创建一个分区。建议将分区类型改为 0x8e(Linux LVM),这样便于识别 LVM 分区/磁盘。使用 pvcreate 对物理磁盘进行初始化:pvcreate /dev/hda3。
    • 然后,使用 vgextend 将它添加到现有的 VG 中:vgextend test-volume /dev/hda2。

    还可以同时创建或添加多个物理磁盘:

    pvcreate /dev/hda2 /dev/hda3 /dev/hda5

    vgextend test-volume /dev/hda2 /dev/hda3 /dev/

      添加了 PV 之后,就有了足以扩展逻辑卷的空间,就可以使用 lvextend 扩展逻辑卷了:lvextend -L 8G /dev/test-volume/data。这个命令将 /dev/test-volume/data LV 的大小扩展到 8GB。

      lvextend 有一些有用的参数:

    • 如果希望让 LV 增加 5GB,那么可以使用 -L +5G。
    • 可以指定扩展部分的位置(也就是,用哪些 PV 提供新的空间);只需将希望使用的 PV 附加在命令后面。
    • 还可以以 PE 为单位指定绝对/相对扩展大小。

    细节参见 lvextend(8)。

      在扩展 LV 之后,不要忘记扩展文件系统(这样才能实际使用增加的空间)。根据文件系统类型,这个操作可以在文件系统挂载状态下在线执行。

    清单 10 是一个用 resize_reiserfs 重新设置 LV 大小的示例(随便说一句,可以在挂载的文件系统上使用这个命令):resize_reiserfs /dev/test-volume/data。

    管理卷

      为了管理卷,需要知道如何减小 LV 和删除 PV。

      减小逻辑卷 qm7Linux联盟可以按照扩展 LV 的方式使用 lvreduce 命令减小 LV。从 LVM 的角度来说,这个操作可以在卷在线的情况下执行;但是,大多数文件系统不支持缩小在线文件系统。清单 10 给出这个过程的示例:
    #unmount LV
    umount /path/to/mounted-volume
    #shrink filesystem to 4G
    resize_reiserfs -s 4G /dev/test-volume/data
    #reduce LV
    lvreduce -L 4G /dev/vg00/test

    请注意大小和单位:文件系统不应该比 LV 大!

    删除物理卷

      假设出现了以下情况:一个卷组包含两个 80GB 的磁盘,希望将它们替换为 160GB 的磁盘。在使用 LVM 时,可以按照添加 PV 的方式从 VG 中删除 PV(即在在线情况下执行删除)。但是注意,不能删除 LV 中正在使用的 PV。对于这些情况,可以使用 pvmove,它可以释放在线的 PV,这样就可以轻松地替换它们。在热交换环境中,甚至可以交换所有磁盘,而根本不需要停机!

      pvmove 的惟一要求是,VG 中连续空闲区段的数量必须等于要从 PV 中删除的区段数量。没有直接判断连续空闲 PE 的最大数量的简便方法,但是可以使用 pvdisplay -m 显示 PV 分配图:

    清单 11. 显示 PV 分配图


    #shows the allocation map
    pvdisplay -m
    --- Physical volume ---
    PV Name /dev/hda6
    VG Name test-volume
    PV Size 4.91 GB / not usable 1.34 MB
    Allocatable yes (but full)
    PE Size (KByte) 4096
    Total PE 1200
    Free PE 0
    Allocated PE 1200
    PV UUID BA99ay-tOcn-Atmd-LTCZ-2KQr-b4Z0-CJ0FjO

    --- Physical Segments ---
    Physical extent 0 to 2367:
    Logical volume /dev/test-volume/data
    Logical extents 5692 to 8059
    Physical extent 2368 to 2499:
    Logical volume /dev/test-volume/data
    Logical extents 5560 to 5691

    --- Physical volume ---
    PV Name /dev/hda7
    VG Name test-volume
    PV Size 9.77 GB / not usable 1.37 MB
    Allocatable yes
    PE Size (KByte) 4096
    Total PE 2500
    Free PE 1220
    Allocated PE 1280
    PV UUID Es9jwb-IjiL-jtd5-TgBx-XSxK-Xshj-Wxnjni

    --- Physical Segments ---
    Physical extent 0 to 1279:
    Logical volume /dev/test-volume/LV0
    Logical extents 0 to 1279
    Physical extent 1280 to 2499:
    FREE


    清单 11 显示有 2,499-1,280 = 1,219 个连续空闲区段,这表示最多能够将 1,219 个区段从另一个 PV 转移到 /dev/hda7。

      如果希望释放一个 PV 以便进行替换,那么最好禁止它的分配,这样就可以在从卷组中删除它之前确保它一直是空闲的。在转移数据之前,执行以下命令:

    清单 12. 在释放之前禁止 PV 的分配

    #Disable /dev/hda6 allocation

    pvchange -xn /dev/hda6

    释放之后,PV /dev/hda6 的大小为 1,200 个区段,没有空闲区段了。使用以下命令将数据转移出这个 PV:

    清单 13. 从释放的 PV 移出数据

    #Move allocated extents out of /dev/hda6

    pvmove -i 10 /dev/hda6

    清单 13 中的 -i 10 参数指示 pvmove 每 10 秒报告一次状态。根据要转移的数据量,这个操作可能要花费几分钟(甚至几小时)。还可以使用 -b 参数将这个操作转到后台执行。在后台执行的情况下,状态报告会发送到系统日志。

      如果没有足以进行 pvmove 操作的连续空闲区段,那么可以在 VG 中添加 一个或多个磁盘/分区,从而形成 pvmove 所需的连续空间。

    其他有用的 LVM 操作

     关于下面这些 LVM 操作的细节,请查阅手册页

    pvresize:如果底层分区也已经扩展了,那么可以用这个操作扩展 PV;如果分配图允许的话,它也可以缩小 PV。

    pvremove:销毁 PV(清空它的元数据)。只有在用 vgreduce 从 VG 中删除 PV 之后,才能使用这个操作。

    • vgreduce:从卷组中删除未分配的 PV,这会减小 VG。
    • vgmerge:将两个 VG 合并成一个。目标 VG 可以是在线的
    • vgsplit:分割一个卷组。
    • vgchange:修改一个 VG 的属性和权限。
    • lvchange:修改一个 LV 的属性和权限。
    • lvconvert:在线性卷和镜像或快照之间进行转换

    用快照执行备份

      如果在备份过程期间数据没有发生变化,那么就能够获得一致的备份。如果不在备份期间停止系统,就很难保证数据没有变化。

      Linux LVM 实现了一种称为快照(Snapshot)的特性,它的作用就像是 “拍摄” 逻辑卷在某一时刻的照片。通过使用快照, 可以获得同一 LV 的两个拷贝 —— 一个可以用于备份,另一个继续用于日常操作。

      快照有两大优点

    1. 快照的创建非常快,不需要停止生产环境。
    2. 建立两个拷贝,但是它们的大小并不一样。快照使用的空间仅仅是存储两个 LV 之间的差异所需的空间。

      快照由一个例外列表(exception list)来实现,每当 LV 之间出现差异时就会更新这个列表(正式的说法是 CoW,Copy-on-Write)。

    创建新的快照

      创建新的快照 LV 也是使用 lvcreate 命令,但是要指定 -s 参数和原来的 LV。在这种情况下,-L size 指定例外列表的大小,这影响快照支持的最大差异量,如果差异超过这个量,就无法保持一致性。

    清单 14. 建立快照

    #create a Snapshot LV called 'snap' from origin LV 'test'

    lvcreate -s -L 2G -n snap/dev/test-volume/test

    可以使用 lvdisplay 查询特殊信息,比如 CoW 的大小和使用情况

    清单 15. CoW 的大小和使用情况

    lvdisplay /dev/vg00/snap
    --- Logical volume ---
    LV Name /dev/vg00/snap
    VG Name vg00
    LV UUID QHVJYh-PR3s-A4SG-s4Aa-MyWN-Ra7a-HL47KL
    LV Write Access read/write
    LV snapshot status active destination for /dev/vg00/test
    LV Status available
    # open 0
    LV Size 4.00 GB
    Current LE 1024
    COW-table size 2.00 GB
    COW-table LE 512
    Allocated to snapshot 54.16%
    Snapshot chunk size 8.00 KB
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:5

    清单 15 表明这个 CoW 的大小为 2GB,其中的 54.16 % 已经使用了。

      对于所有日常操作,快照看起来就是 原 LV 的一个拷贝。如果已经建立了文件系统的话,可以用以下命令挂载它:

    #mount snapshot volume

    mount -o ro /dev/test-volume/test /mnt/snap

      在这个命令中,ro 标志表示将它挂载为只读的。可以在 lvcreate 命令后面加上 -p r,这样就在 LVM 级将它设置为只读的。

      挂载文件系统之后,就可以用 tar、rsync 或其他备份工具执行备份。如果 LV 不包含文件系统,或者需要原始备份,那么也可以在这个设备节点上直接使用 dd。

      复制过程完成之后,就不需要快照了,这时只需用 lvremove 卸载并销毁它:

    #remove snapshot

    lvremove /dev/test-volume/snap

      如果数据库建立在 LV 上,并且需要一个一致的备份,那么一定要刷新表并在获得读取锁(read-lock)的情况下建立快照卷(见下面的伪代码):

    SQL> flush tables read lock

    {create Snapshot}

    SQL> release read lock

    {start copy process from the snapshot LV}

    备份脚本示例

    清单 16 中的脚本直接取自我的笔记本电脑,我在这个脚本中使用 rsync 向一台远程服务器执行每日备份。这个脚本并不适合企业环境;在企业环境中,带历史记录的增量备份更合适,但概念是相同的。

    清单 16. 简单的备份脚本示例


    #!/bin/sh

    # we need the dm-snapshot module
    modprobe dm-snapshot
    if [ -e /dev/vg00/home-snap ]
    then
    # remove left-overs, if any
    umount -f /mnt/home-snap && true
    lvremove -f /dev/vg00/home-snap
    fi
    # create snapshot, 1GB CoW space
    # that should be sufficient for accommodating changes during copy
    lvcreate -vs -p r -n home-snap -L 1G /dev/vg00/home
    mkdir -p /mnt/home-snap
    # mount recently-created snapshot as read-only
    mount -o ro /dev/vg00/home-snap /mnt/home-snap
    # magical rsync command__rsync -avhzPCi --delete -e "ssh -i /home/klausk/.ssh/id_rsa" \
    --filter '- .Trash/' --filter '- *~' \
    --filter '- .local/share/Trash/' \
    --filter '- *.mp3' --filter '- *Cache*' --filter '- *cache*' \
    /mnt/home-snap/klausk klausk2@pokgsa.ibm.comThis e-mail address is being protected
    from spam bots, you need JavaScript enabled to view it :bkp/
    # unmount and scrap snapshot LV
    umount /mnt/home-snap
    lvremove -f /dev/vg00/home-snap


      在某些特殊情况下,无法估计备份周期或者复制过程很长,那么脚本可以用 lvdisplay 查询 Snapshot CoW 的使用情况并根据需要扩展这个 LV。在极端情况下, 可以让快照与原 LV 同样大 —— 这样就不需要执行查询,因为变化量不会比整个卷更大

    其他 LVM2 系统管理技巧

      最后, 我要介绍一些可以用 LVM2 执行的系统管理任务,包括按需虚拟化、用镜像提高容错能力以及透明地对块设备执行加密。

    快照和虚拟

      在使用 LVM2 时,快照可以不是只读的。这意味着,在创建快照之后, 可以像常规块设备一样挂载和读写快照。

      因为流行的虚拟化系统(比如 Xen、VMWare、Qemu 和 KVM)可以将块设备用作 guest 映像,所以可以创建这些映像的完整拷贝,并根据需要使用它们,它们就像是内存占用量很低的虚拟机。这样做的好处是部署迅速(创建快照的时间常常不超过几秒)和节省空间(guest 共享原映像的大多数数据)。

    设置的步骤如下:

    1. 为原映像创建一个逻辑卷。
    2. 使用这个 LV 作为磁盘映像安装 guest 虚拟机
    3. 暂停这个虚拟机。内存映像可以是一个常规文件,所有其他快照都放在里面。
    4. 为原 LV 创建一个可读写的快照。
    5. 使用快照卷作为磁盘映像生成一个新的虚拟机。如果需要的话,要修改网络/控制台设置。
    6. 登录已经创建的虚拟机,修改网络设置/主机名。

      完成这些步骤之后, 就可以让用户访问刚创建的虚拟机了。如果需要另一个虚拟机,那么只需重复步骤 4 到 6(所以不需要重新安装虚拟机)。还可以用一个脚本自动执行这些步骤。

      在使用完虚拟机之后, 可以停止虚拟机并销毁快照。

    更好的容错能力

      最近的 LVM2 开发成果为逻辑卷提供了高可用性。逻辑卷可以有两个或更多的镜像,镜像可以放在不同的物理卷(或不同的设备)上。当在设备上发现 I/O 错误时,可以使用 dmeventd 让一个 PV 离线,而不会影响服务。更多信息请参考 lvcreate(8)、lvconvert(8) 和 lvchange(8) 手册页。

      如果硬件能够支持的话,可以用 dm_multipath 通过不同的通道访问同一设备,这样的话在一个通道发生故障时,可以转移到另一个通道。更多细节请参考 dm_multipath 和 multipathd 的文档。

    透明的设备加密

      可以用 dm_crypt 对块设备或逻辑卷执行透明的加密。更多信息请参考 dm_crypt 的文档和 cryptsetup(8) 手册页。

    参考资料

    学习

    Ubuntu安装后的快速家用型配置

    首先说明,原因和前面的Windows 2008一样,不需要使用其他服务功能,配置到家用所需即可。
    本文参考ubuntu中文论坛上的ubuntu 8.04速成手册1.0和利用google搜到的许多文章。

    安装过程十分简单,略过。

      装好后第一步:设置网络:拨号连接,在终端里运行pppoeconf。按照向导配置。不懂就选是。配置好以后就可以拨号上网了。据称如果你常断线按照如下设置可以解决:

    在终端输入
    sudo gedit /etc/ppp/options
    将 弹出的文档中的 lcp-echo-failure 4 改为 lcp-echo-failure 40 这是因为 Ubutnu 默认的设置有个很明显的缺陷,lcp-echo-failure 次数被设为 4,而 lcp-echo-interval 设为 30秒。也 就是说,如果 120 秒钟之内,ADSL 服务器没有给回 echo-reply 信号,Ubuntu 便会认为网络已经出了问题,马上中断重联,搞得人非常不爽。
      实际上,此事搞定之后记得先配置一下更新源sudo gedit /etc/apt/sources.list

      教育网的推荐用交大的:
      南方的同学用CN99的:
    deb http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe ultiverse
    deb http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse
    deb http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse
    deb http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe
    multiverse
    deb http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse
    deb-src http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe multiverse
    deb-src http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse
    deb-src http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse
    deb-src http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe
    multiverse
    deb-src http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse
    deb http://ubuntu.cn99.com/ubuntu-cn/ hardy main restricted universemultiverse
      配置完后
    sudo apt-get update
    sudo apt-get upgrade

      第二步:设置语言,默认情况用liveCD装的中文版字体惨不忍睹。赶快在系统→系统管理→Language Support那里把汉语选上,装了。
      顺便也装几个有用的工具:sudo apt-get install nautilus-open-terminal
      这个工具让右键菜单里有终端的快捷方式,可以直接在当前目录打开终端。
      第三步:装软件,先sudo apt-get install build-essential装好编译用的包,
      首先是我的显卡驱动,nvidia_geforce_1731409_linux86,这个要关闭GNOME装:按Ctrl+Alt+F1切换到1号终端
      装驱动之前先确保安装完全了内核模块linux-restricted-modules,在新得利中找到适合你机器的,装好,之后sudo /etc/init.d/gdm stop。记得运行下sudo dpkg -r nvidia-glx,然后就运行安装程序吧。
      按照提示选就好。装好后sudo nvidia-xconfig,弄完之后启动gdm会看到nvidia的logo就表示成功了。因为我不喜欢那个标志,所以删掉它:sudo gedit /etc/X11/xorg.conf,直接搜索nvidia,在找到的有效行后面加一行Option "NoLogo"就好。如果你的显卡安装有问题可以参考此文:http://wiki.ubuntu.org.cn/NVIDIA%E6%98%BE%E5%8D%A1%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE%E6%8C%87%E5%8D%97

      然后是我常用的几个软件:
    sudo apt-get install rar unrar p7zip
    sudo ln -fs /usr/bin/rar /usr/bin/unrar
    作用是装好rar和7zip解压的程序并建立软连接方便使用。
    --------------------------------------
    sudo apt-get install stardict stardict-common
    星际译王,装好后到
    http://stardict.sourceforge.net/Dictionaries_zh_CN.php
    下载词典,之后把词典文件解压到/usr/share/stardict/dic
    --------------------------------------
    sudo apt-get install gstreamer0.10-*
    sudo apt-get install totem-xine ffmpeg lame faad sox mjpegtools
    sudo apt-get install mplayer mplayer-fonts mozilla-mplayer
    按照参考的资料安装一批解码器编码器和mplayer。
    记得到http://www.mplayerhq.hu/MPlayer/releases/codecs/下载对应的解码包解压到/usr/lib/codecs
    我就只下了那个all-20071007.tar.bz2
    sudo apt-get install audacious
    我也比较喜欢这个播放器
    --------------------------------------
    sudo apt-get install amule amule-common amule-utils
    sudo apt-get install azureus
    BT和电驴客户端,电驴的值得优化下:导入http://www.emule.org.cn/server.met的服务器列表。在设置中把你的名字前面加几个有好处的前缀[TLF][CHN][VeryCD][Cyndi][TwED2K]
    然后和firefox关联一下:打开about:config
    1.新建一个 boolean 类型 network.protocol-handler.external.ed2k ,值为 true,表示处理ed2k 的协议
    2.新建一个 string 类型 network.protocol-handler.app.ed2k ,值为/usr/bin/amule,指定处理 ed2k 协议的程序为/usr/bin/ed2k
    3.实际上这样设置完之后速度还是很慢滴。为什么?别忘记还有kad网络节点没有设置。
    添加KAD nodes.dat
    http://www.emule-inside.net/nodes.dat
    http://renololo1.free.fr/e/nodes.dat
    更新一下就好了。

    此外,如果你像我一样希望和windows下的驴子能下载同样的东西,可以建立一个目录自动挂载windows分区。如果遇到中文乱码问题解方案如下:
    假设使用的locale是utf8,修改/etc/fstab文件:
    NTFS分区示例(逗号两侧没有空格, gid=46在系统安装时就有,不用修改。下同):
    /dev/hda1 /media/hda1 ntfs-3g defaults,locale=zh_CN.utf8,umask=007,gid=46 0 1
    FAT32分区示例(一般情况下使用默认的设置就行了)
    /dev/hda5 /media/hda5 vfat defaults,nls=utf8,umask=007,gid=46 0 1

    最后,最好在更新源里加上
    deb http://ppa.launchpad.net/festor90/ubuntu hardy main
    以便以后自动升级amule
    --------------------------------------
    sudo apt-get install sun-java6-jdk
    装完jdk后要设置一下:
    配置 JAVA 环境变量:
    sudo gedit /etc/environment
    在其中添加如下两行:
    CLASSPATH=.:/usr/lib/jvm/java-6-sun/lib
    JAVA_HOME=/usr/lib/jvm/java-6-sun
    sudo gedit /etc/jvm
    在文件中的配置块的顶部增加
    /usr/lib/jvm/java-6-sun
    这种安装方法比直接下bin包安装的好处在于不会乱码。。。

    sudo apt-get install eva #注意如果登录QQ失败可能是要验证码
    sudo apt-get install filezilla #ftp client



      第四步:当然就是传说中的3D桌面优化了。先安装设置程序。
    sudo apt-get install compizconfig-settings-manager
    在系统→首选项→外观中开启扩展特效,之后在系统→首选项Advanced Desktop Effects Settings中打开general options 在desktop size中把横向设置为4个,之后开启desktop cube,就出现传说中的桌面立方体了。。。
    之后的配置就靠自己去尝试了。

    到这里基本就完成了。愉快的玩吧。。。。

    简单的设置一个家用版Windows server 2008 附装卡巴斯基的方法

    貌似网上帖子也不少了。不过各取所需,我的需求和他们不同,就有了不同的设置。


    先说说我的需求:




    1. 要留给不大懂计算机的普通用户使用。


    2. 完全不需要服务器功能。也不要虚拟化功能(我的这台机器也不支持)


    3. 提供基本的影音功能。


    4. 优化性能让它在我的Athlon 2000+ 和512M内存的机器上跑好。最好能用Aero.


    基本按照下面的步骤就好(我装Windows Server 2008 Standard版):





    1. 设置好网络。之后上网下载显卡和声卡的驱动。


    2. 装好他们。在下载的时间中还可以做到一些其他事:
      关闭UAC:在控制面板 用户帐户设置里
      关闭关机事件跟踪:在运行中输入gpedit.msc。之后再计算机管理->管理模板->系统中找到显示"关机事件跟踪程序"这个策略,禁用之。装好后重启。


    3. 开启音频服务在服务设置里把windows audio设置为自动。

    4. 如果前面关闭了登录时自动显示的那个初始配置任务的话在运行里输入oobe就可以了。之后选添加功能->桌面体验就好。同样要在服务中把Theme服务设置为自动。

    5. 开始禁用服务:
      Ip Helper :禁用,因为我不用IPv6
      Print Sponler:改手动,因为我没有打印机,也暂时不需要用到打印预览功能。
      Remote Registry:禁用,我不需要远程修改注册表。
      Shell Hardware Detection:禁用,我从不用自动播放
      Windows Defender:禁用,我用卡巴。

    6. 其他设置:
      在计算机右键的属性中,选高级,性能,选数据执行保护,把它改成仅为基本Windows程序和服务启用DEP,同样一个面板中选高级,在处理器计划中选优先分配给程序。主题和颜色那里开启Aero。

    7. 开启传说中的SuperFetch
      You will have to make two registry changes to enable this service. I basically copied them over from my Vista machine.HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParametersEnablePrefetcher DWORD 3EnableSuperfetch DWORD 3

    这样一来基本上就搞定了,总的来说日常应用速度还是可以的。另外,Windows server 2008的评估期限为60天,快到的时候在命令行下执行slmgr.vbs –rearm 可以重置信息,基本上可以有3次共240天的全功能试用期。

    附注:安装卡巴斯基。

    虽然卡巴最近出了所谓server2008认证版,不过据网友反映有严重缺陷,所以其实还是可以直接用kav7.0的。我自己也有试过,还是非常稳定的。

    一般来说,你是不能装的。会提示不支持此操作系统。

    下载一个Orca:http://www.swifthome.info/wp-content/uploads/2007/09/orca.zip

    装好后这样干:

    先点安装文件,开始装。等到报错的页面出现的时候不要动。去C:\Users\SVBlue\AppData\Local\Temp把卡巴的.msi文件复制出来。用Orca编辑。

    搜索”操作系统不支持“把找到的都删了就ok了。


    -----------------------------------------------

    更新:如果你使用kmplayer发现不能播放rmvb的话,请下载

    cook.dll

    drvc.dll

    pncrt.dll

    sipr.dll

    这四个文件,解压到kmplayer目录下。即可,如果还是不能播放试着cd到kmplayer的目录下。之后regsrv32 RealMediaSplitter.ax

    2008-07-13

    在AMD64位Ubuntu8.04下安装锐捷认证客户端

    首先,我只能说锐捷在Linux下还是一个相当不成熟的产品,我实在看不出有什么地方值得选择锐捷。
    不过学校选择了这个也只能尽自己的力去搞定它了。
    按照安装文档的安装方法是不能用的

    • 似乎是由于和64为的运行库的调用问题,像我这样运行sudo xrgsu提示找不到文件(No such file of directer)。 安装libc6-i386_2.7-10ubuntu3_amd64.deb 这个软件包能够解决这个问题
    • 接下来继续运行会发现提示libpcap.so.0.6.2找不到。同样火大,实际上在/usr/lib /usr/lib32 /usr/lib64下面都已经有这个文件了,不过就是不行,仔细一看也觉得有点不对。于是下过一个文件把这三个目录的都覆盖了。OK,搞定了。。
    • 接下来又提示libstdc++.s0.5有问题,类似上面那个解决。
    • 最后再提示libgcc_s.s0.1有问题。简单。。直接从/lib/中把同样一个文件拷过去就解决了。
      之后就可以运行了。

    基本上来说就是64位系统运行32位程序的不便导致的。。。

    前面提到的几个文件可以在ulysess.ys168.com找到。如果网盘挂了可以在下面留言我会修复的。

    2008-07-09

    java的图形设计章节.预备知识&组件

    预备知识:
    java的图形系统:

    • java坐标系统左上角为原点。
    • java用RGB表示像素点的颜色。在java.awt.Color类中可以定义和管理颜色。
    java的GUI组件也是一个对象,它由java.awt和javax.swing定义。

    容器(container)是一个保存和组织其他组件的特殊组件,框架(frame)和面板(panel)就是两种容器:
    • 框架用于显示基于GUI的java程序界面,一个框架有独立的窗口,包含最大化最小化关闭的按钮,框架有JFrame类定义。
    • 面板自身不能独立显示,必须加到一个可以显示它的容器中也就是所它只能作为其他容器的部分,它只能随着包含它的容器移动,面板由JPanel类定义。
    一般我们可以创建一个显示GUI的框架来建立一个Java图形程序,GUI通常显示在框架中的主面板上。
    举个例子介绍下GUI的各种组件:

    import java.awt.*;
    import javax.swing.*;

    public class Main {


      public static void main(String[] args) {
        JFrame frame= new JFrame ("For Learning");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel primary = new JPanel();
        primary.setBackground(Color.CYAN);
        primary.setPreferredSize(new Dimension(300,100));

        JLabel label1 = new JLabel("Label1 is here ");
        JLabel label2 = new JLabel("Label2 is also here");

        primary.add(label1);
        primary.add(label2);

        frame.getContentPane().add(primary);
        frame.pack();
        frame.setVisible(true);

      };

    }

    运行结果是这样的:

      这里的JFrame构造方法以参数的字符串作为标题栏的内容。
      setDefaultCloseOperation方法决定点击×时做的事,本程序使用JFrame.EXIT_ON_CLOSE常量
      这里的JPanel类创建了一个面板,setPreferredSize方法接受一个Dimension对象作为参数以指定面板宽高,一般程序常用此法来控制大小,并且使用setMinimumSize和setMaximumSize来控制外观。
      容器都有一个add方法,用于将其他组件加入本容器。
      在程序的最后通过getContentPane方法获得框架的内容窗格,并调用内容窗格的add方法把primary面板加入框架。pack方法是根据框架的内容来设定框架的尺寸。

      每一个容器都有一个名为布局管理器的对象管理,它负责容器内的组件如何部署位置。默认如果没有指定排列位置的话面板中的组件总是试图按照行顺序排列。

      一般来说,真的编写有用的程序,还是需要多个面板的嵌套。
    把前面那个程序的
        primary.add(label1);
      primary.add(label2);

    替换成
        JPanel subp1= new JPanel();
        subp1.setPreferredSize(new Dimension(140,100));
        subp1.setBackground(Color.yellow);
        subp1.add(label1);

        JPanel subp2= new JPanel();
        subp2.setPreferredSize(new Dimension(140,100));
        subp2.setBackground(Color.ORANGE);
        subp2.add(label2);

        primary.add(subp1);
        primary.add(subp2);


    就变成了一个嵌套了两个子面板的情况:



      一般来说,图片在程序中的用法还是相当丰富的。Graphics类提供了一个drawImage方法来让用户方便的绘制图像。
      JLabel类定义的标签也可以含有图像,ImageIcon类代表一个包含在标签中的图像。可将参数中指定的图像文件装入ImageIcon对象中,支持JPEG和GIF。

    以下介绍一些交互用的组件:

    按钮:

    代码:
    main方法和前面基本类似,只是frame.getContentPane().add(new ClickCounterPanel());

    这个类的定义如下:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class ClickCounterPanel extends JPanel{

      private int count;
      private JButton click;
      private JLabel label;

      /*
      * Constructor:set up the GUI;
      */
      public ClickCounterPanel ()
      {
        count =0 ;
        click= new JButton("Click Me!");

        click.addActionListener(new ButtonListener());
        //set the connection between the Event and the component
        label = new JLabel("Click time:"+ count);

        add (click);
        add (label);

        setPreferredSize (new Dimension (250,50));
        setBackground (Color.GREEN);

      }

      /*
      * A Listener for button push action event.
      */
      private class ButtonListener implements ActionListener
      {
        public void actionPerformed(ActionEvent event)
        {
          count++;
          label.setText("Click times:" + count);

        }
      }

    }
    编译以后运行结果:

    注意label包含的文本的区别,你就能理解这个程序中是如何令监听器与组件之间建立联系的了。
      
      此外,值得一提的是,这个程序的ButtonListener类是一个内部类(inner class),也就是在另一个类内部定义的类,这样的好处在于ButtonListener类也能够访问ClickCounterPanel类的成员变量,而我们不需要编写复杂的其他代码。一般只有两个类有着紧密的联系并且内部类不需要被外部的其他类访问的时候才使用内部类

    从数据与表达式开始

      上一篇文章介绍了java的基本数据类型,实际上,在java中除了基本类型之外的其他数据都被当作对象。
      所有程序中必不可少的一个数据类型就是字符串了,在java中,一个字符串就是一个对象,由String类定义。同C一样,java中同样允许字符串常量。
      类似于C,Java也是有字符类型组成的。
    同样,Java中的字符处理的转义字符和C类似:


    转义字符
    意义
    \n
    换行
    \b
    退格
    \t
    制表符
    \r
    回车
    \"
    双引号
    \\
    反斜杠

    在Java中,声明一个变量和C类似,都是定义了一个内存单元的符号地址。
    Java的不同之处在于,Java中,只有基本数据类型可以在声明是赋值,对象不允许在声明时赋值。如:
    int count,num=88;
    用final将声明一个常量。如:
    final int x=8;
    此外在赋值时必须注意的是,java不允许在赋值的时候对一个变量赋予不同类型的值。
    在java中,自增、自减运算符和C中有着一样的法则。同样也有+= -= *= /= %=这几种用样用法的运算符。不过注意这几种运算符的作用随操作的类型而定。
    ---------------------------------------------------------------------------------------
    数据类型转换:
    扩展类型转换(就是少位的往多位转)是安全的。整型转换为浮点型会损失精度。
    压缩类型转换(就是多位的往少位转)可能丢失信息。
    Java中的数据类型转换方式有三种:
    • 赋值类型转换
      如:float asd;int bcd;asd=bcd;这个时候bcd被自动转换为浮点型。但是反过来就会报错,这个时候需要用到强制类型转换。
    • 由少位的类型向多位的类型自动转换
      在进行运算时而需要修改其操作数的数据类型时发生。比如浮点型除整型,就会把整型转换成浮点型。还有类似一个数值与字符串拼接的时候也将发生。
    • 强制类型转换
      如上面所说的int=(int) asd;