2012年10月11日星期四

VM7中CRUX 2.7的安装

 VM7中CRUX 2.7的安装

前言(废话):发现上一篇帖子还是去年11月的额,不知不觉有近一年的时间没有进行技术方面的学习了...果然搞科研的孩子伤不起啊喵~!最近又开始折腾各种配置,遇到了不少问题,尤其是在VMware中编译运行CRUX着实令人头疼...不是说过程很复杂,而是遇到了各种奇怪的问题难以解决,折腾了几个整天的时间终于有些眉目了。本文简要介绍在VM7安装CRUX以及前期配置中遇到的一些问题的解决方法。由于编译操作系统对于环境要求严格(不同环境下遇到的问题可能不同),因此不保证本文的方法能够适用于任意情况下的CRUX安装。

好吧,我们长话短说。首先VMware是必须的(我用的版本是VMware workstation7.0.0 build-203739,同学在8.0上貌似也可以),如果没有,没有...我也没有办法。CRUX选用的是2.7版,我用的是i686的版本,X86的版本也行,可以从http://crux.nu/Main/Download下载相应的iso。

先来看看俺是怎么失败的:
首先在VMware中创建虚拟机,选择自定义(custom),在系统安装选项(guest operating system installation)中选择从iso安装,并选择下载的CRUX的iso文件,系统选择Linux,Other Linux 2.6.x kernel,硬件选项除了硬盘类型改为IDE(默认是SCIS),其余全默认(虚拟机存储的路径自己决定吧),然后等待系统启动。
接下来的步骤我是按照这个教程进行的,貌似2.7的CRUX有个bug,不论你的硬盘类型是IDE还是SCSI,硬盘的设备路径都是/dev/sda(按理来说IDE的硬盘应该是/dev/hda),分区后的结果自然也不是hda1,hda2...而是sda1,sda2...自己注意一下就好。fdisk命令不懂可以自己找些教程,例如这个

另外,在fstab里面别忘了加入swap分区的内容(按照教程的内容应该加入/dev/hda2  swap swap default 0 0一行,自己根据情况修改)。lilo里面的append=quite注释掉有利于问题的发现。
经过漫长的编译和配置,总算到了激动人心的时候,reboot,系统启动,加载驱动,挂载硬盘,然后...就木有然后了...这里出现了致命错误:

   VFS: Cannot open root device 803 or unknown-block(8,3)
   Please append a corrent "root=" boot option
   kernel panic - not syncing: VFS: Unable to mount root fs on unknow-block(8,3) 


重启之后仍然不能解决问题,无解,只能咨询google了。

发现其他人也遇到了类似问题,尝试他们提供的解决方案,仍然不能解决问题...根据其他人的症状解决方法,想到可能是硬件驱动冲突问题(类似问题基本是修改硬件驱动配置解决的)。但是crux配置里面的硬件数量这么多,要怎么样找出究竟是哪个驱动有问题呢?

如果大部分驱动是没有用的,我们为什么不去除其他多余的所有驱动呢?按照这个思路,在以上提到的教程第6步
6、编译内核,安装内核文件及模块

$ cd /usr/src/linux-2.6.15.6
$ make menuconfig 
中的$ make menuconfig 命令之前,先输入以下命令:
$ make defconfig 
将编译选项恢复到默认配置,然后再按照以上提供的解决方案进行配置,其余步骤与教程相同。
终于得到了以下结果:
真是可喜可贺啊!

总结一下,需要注意的步骤如下:
  1. 在创建虚拟机时VMWare硬盘的SCSI方式选择busLogic
  2. 编译内核时一定要选上如下两个:
    Device Drivers --->
    Fusion MPT device support --->
    <*> Fusion MPT ScsiHost drivers for SPI [kernel 2.6.13] 


    SCSI low-level drivers --->
    <*>bus Logic SCSI support


    ext4文件系统默认没选上,一定要选择上,不然/boot不能mount

    将网卡编译入内核中

    Devices Drivers --->
    Network device support --->
    Ethernet (10 or 100Mbit) --->
    <*>AMD PCnet32 PCI SUPPORT 
  3. 在 $ make menuconfig 之前一定要 $ make defconfig ,否则驱动冲突
其余的按照教程操作就可以了。 
 

2011年11月29日星期二

转:hpp的使用

转自:http://hi.baidu.com/mengrui1001/blog/item/0501eecf3c06200590457e65.html

hpp,顾名思义等于.h加上.cpp,在boost、Xerces等开源库中频繁出现,偶在机缘巧合之下,学得一招半式,遂记录如下,以供参考学习。

    hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布烦人的lib与dll,因此非常适合用来编写公用的开源库。
    hpp的优点不少,但是编写中有以下几点要注意:
   
    1、不可包含全局对象和全局函数。
    由于hpp本质上是作为.h被调用者include,所以当hpp文件中存在全局对象或者全局函数,而该hpp被多个调用者include时,将在链接时导致符号重定义错误。要避免这种情况,需要去除全局对象,将全局函数封装为类的静态方法。(如果在.h文件中引用包含全局函数的hpp文件,必定出错。可以通过仅在cpp中include hpp文件来避免这种错误。最好的方法是将全局函数的定义和声明分别写到cpp和.h文件中)
    2、类之间不可循环调用。
    在.h和.cpp的场景中,当两个类或者多个类之间有循环调用关系时,只要预先在头文件做被调用类的声明即可,如下:
    class B;
    class A{
    public:
         void someMethod(B b);
    };
    class B{
    public:
         void someMethod(A a);
    };
    在hpp场景中,由于定义与实现都已经存在于一个文件,调用者必需明确知道被调用者的所有定义,而不能等到cpp中去编译。因此hpp中必须整理类之间调 用关系,不可产生循环调用。同理,对于当两个类A和B分别定义在各自的hpp文件中,形如以下的循环调用也将导致编译错误:
    //a.hpp
    #include "b.hpp"
    class A{
    public:
        void someMethod(B b);
    };
    //b.hpp
    #include "a.hpp"
    class B{
    public:
        void someMethod(A a);
    };
    3、不可使用静态成员。
    静态成员的使用限制在于如果类含有静态成员,则在hpp中必需加入静态成员初始化代码,当该hpp被多个文档include时,将产生符号重定义错误。唯一的例外是const static整型成员,因为在vs2003中,该类型允许在定义时初始化,如:
    class A{
     public:
       const static int intValue = 123;
     };
    由于静态成员的使用是很常见的场景,无法强制清除,因此可以考虑以下几种方式(以下示例均为同一类中方法)
    1.类中仅有一个静态成员时,且仅有一个调用者时,可以通过局域静态变量模拟
    //方法模拟获取静态成员
    someType getMember()
    {
       static someType value(xxx);//作用域内静态变量
       return value;
    }
    2.类中有多个方法需要调用静态成员,而且可能存在多个静态成员时,可以将每个静态成员封装一个模拟方法,供其他方法调用。
    someType getMemberA()
    {
       static someType value(xxx);//作用域内静态变量
       return value;
    }
    someType getMemberB()
    {
       static someType value(xxx);//作用域内静态变量
       return value;
    }
   void accessMemberA()
    {
       someType member = getMemberA();//获取静态成员
     };
    //获取两个静态成员
    void accessStaticMember()
    {
       someType a = getMemberA();//获取静态成员
       someType b = getMemberB();
     };
    3.第二种方法对于大部分情况是通用的,但是当所需的静态成员过多时,编写封装方法的工作量将非常巨大,在此种情况下,建议使用Singleton模式,将被调用类定义成普通类,然后使用Singleton将其变为全局唯一的对象进行调用。
     如原h+cpp下的定义如下:
    class A{
    public:
        type getMember(){
           return member;
        }
        static type member;//静态成员
    }
    采用singleton方式,实现代码可能如下(singleton实现请自行查阅相关文档)
    //实际实现类
    class Aprovider{
    public:
        type getMember(){
           return member;
        }
       type member;//变为普通成员
    }
    //提供给调用者的接口类
    class A{
    public:
        type getMember(){
           return Singleton<AProvider>::getInstance()->getMember();
        }
    }