分页: 107/112 第一页 上页 102 103 104 105 106 107 108 109 110 111 下页 最后页 [ 显示模式: 摘要 | 列表 ]
Oct 26

   1. 什么是grub

  grub 是一个多重启动管理器。grub是GRand Unified Bootloader的缩写,它可以在

多个操作系统共存时选择引导哪个系统。它可以引导的操作系统包括Linux,FreeBSD,So

laris,NetBSD,BeOSi,OS/2,Windows95/98,Windows NT,Windows2000。它可以载入操作系

统的内核和初始化操作系统(如Linux,FreeBSD),或者把引导权交给操作系统(如Win

dows 98)来完成引导。

2. grub的特点

  grub可以代替lilo来完成对Linux的引导,特别适用于linux与其它操作系统共存情

况,与lilo相比,它有以下特点:

支持大硬盘

  现在大多数Linux发行版本的lilo都有同样的一个问题:根分区(/boot分区)不能分

在超过1024柱面的地方,一般是在8.4G左右的地方,否则lilo不能安装,或者安装后不

能正确引导系统。而grub就不会出现这种情况,只要安装时你的大硬盘是在LBA模式下,

grub就可以引导根分区在8G以外的操作系统。

支持开机画面

  grub支持在引导开机的同时显示一个开机画面。对于玩家来说,这样可以制作自己

的个性化开机画面;对于PC厂商,这样可以在开机时显示电脑的一些信息和厂商的标志

等。grub支持640x480,800x600,1024x768各种模式的开机画面,而且可以自动侦测选择

最佳模式,与Windows那320x400的开机画面不可同日而语。

两种执行模式

  grub不但可以通过配置文件进行例行的引导,还可以在选择引导前动态改变引导时

的参数,还可以动态加载各种设备。例如你在Linux下编译了一个新的核心,但不能确定

它能不能工作,你就可以在引导时动态改变grub的参数,尝试装载这个新的核心进行使

用。Grub的命令行有非常强大的功能,而且支持如bash或doskey一样的历史功能,你可

以用上下键来寻找以前的命令。

菜单式选择

  在lilo下,你需要手工输入操作系统的名字来引导不同的操作系统。而grub使用一

个菜单来选择不同的系统进行引导。你还可以自己配置各种参数,如延迟时间,默认操

作系统等。

分区位置改变后不必重新配置

  lilo是通过读取硬盘上的绝对扇区来装入操作系统,因此每次分区改变都必须重新

配置lilo,例如你用PQ magic调整了分区的大小,那lilo在你重新配置好之前就不能引

导这个分区的操作系统了。而grub是通过文件系统直接把核心读取到内存,因此只要操

作系统核心的路径没有改变,grub就可以引导系统。 除此之外,Grub还有许多非常强大

的功能。例如支持多种外部设备,动态装载操作系统内核,甚至可以通过网络装载操作

系统核心。Grub支持多种文件系统,支持多种可执行文件格式,支持自动解压,可以引

导不支持多重引导的操作系统等。

3. grub的使用

安装grub

  如果已经安装了蓝点Linux2.0则grub是默认安装的。要把grub重新安装到主引导扇

区上,只需要简单打入makebootable命令就可以了。

制作grub启动盘

  首先确定grub已经安装,然后进入grub的目录,键入:

  #cd /boot/grub

  放入一张软盘,然后敲入命令:

  #dd if=stage1 of=/dev/fd0 bs=512 count=1

  #dd if=/stage2 of=/dev/fd0 bs512 seek=1

  这样就可以做好一张启动盘了。

开机

  安装了grub开机后会出现一个菜单,列出所有的启动选项。如果设置了启动画面则

会显示启动画面,按Esc键则可以取消启动画面显示菜单选项。蓝点Linux所带的grub的

命令提示是全中文的,在菜单下面详细列出如按e是编辑启动命令,按c是使用命令行等

。用上下键可以选择菜单项,按回车启动所选项。按e键可以编辑所选项的启动命令,你

可以用这个功能临时改变你的系统的启动参数,参见配置grub一节。按c键则进入命令行

模式。   

  在命令行模式下可以打入命令直接执行,例如你可以敲入poweroff关闭计算机。按

Tab键可以列出所有支持的命令。蓝点Linux已经把grub汉化了,其中一部分命令敲入名

字后会给出中文提示,显示命令的用法和参数。

4. 配置grub

  grub启动时会在/boot/grub/中寻找一个名字为menu.lst的配置文件,如果找不到此

文件则不进入菜单模式而直接进入命令行模式。

  menu.lst 是一个文本文件,你可以用任何一个文本编辑器来打开它。每一行代表一

个配置命令,如果一行的第一个字符为井号"#"则这一行为注释,你可以简单地用增加或

减少注释行来改变配置。

编辑menu.lst,一般会有以下各行

timeout second

设定在second秒之后引导默认的操作系统。

蓝点Linux默认是timeout 5,就是5秒没有其他指令就引导系统,如果设成-1,则grub会

一直等待直到用户选择一个选项为止。

default num

默认启动第num+1行选项,也就说default=0则默认启动菜单第一行的操作系统,defaul

t=1则启动第2行的系统,如此类推。

splash pathname/filename

指出开机画面的文件所存放的路径和文件名,如 splash /boot/logo/800x600x8.img 是

指用在/boot/logo路径下的800x600.img文件作为开机画面

title OSname title

后面的字符就是你在菜单项上所看见的选项,你可以写上操作系统的名字和描述,如用

title BluePoint Linux, Single Mode 代表这一选项是引导蓝点Linux的单用户模式。

下面结合两个系统引导描述来解释几个引导选项的意义

title BluePoint Linux, Default Mode

root (hd0,1)

kernel /boot/vmlinuz vga=auto root=/dev/hda2

hd0是指第一个硬盘(主硬盘) (hd0,1)是指第一个硬盘的第二个分区。 kernel /boot/v

mlinuz 是指出Linux核心的路径在/boot/vmlinuz中。vga=auto 是设定显示模式,root

=/dev/hda2是指把第一个硬盘的第二个分区作为根挂载点("/")。

title Microsoft Windows

root (hd1,0)

chainloader (hd1,0)+1

root (hd1,0)这是指第二个硬盘(从硬盘)上第一个分区

chainloader (hd1,0)+1 装入一个扇区的数据然后把引导权交给它。

5. 从软盘启动grub

  制作启动盘后可以用软盘启动引导硬盘上的操作系统 插入制作好的启动软盘,进入

BIOS设定软盘启动。软盘启动成功后就会进入grub的命令行模式

grub>

  要启动一个操作系统,首先指定引导哪个分区上的系统,例如要引导指第一个硬盘

上的第一个分区的操作系统,先键入

grub>root (hd0,0)

  接着如果要启动的是Windows系统,键入

grub>chainloader (hd0,0)+1

  注意(hd0,0)要随着硬盘和分区的不同而改变数字。 如果要引导Linux或其他系统,

应键入

grub>kernel (hd0,0)/boot/vmlinuz root=/dev/hda1

  注意hda1参数也要随着硬盘和分区的不同而改变,如从第二个硬盘的第一个分区引

导则用hdb1。

  最后敲入boot就可以启动系统了。

  在任何时候不能确定命令或者命令的参数都可以按Tab获得相关的帮助。用上下键可

以获得命令的历史记录。 其实这些命令就是menu.lst的启动描述,您也可以根据那些描

述来自己键入启动命令,最后敲入boot就可以引导系统了。
Oct 26

   (一)安装linux时安装grub.

安装redhat linux时会提示安装引导程序,如果选择grub为引导程序,建议把grub安装到硬盘的引导扇区MBR.grub
还可以引导其它操作系统,如 FreeBSD、NetBSD、OpenBSD、GNU HURD 和 DOS,以及 Windows
95、98、NT、2000、XP。

(二)grub的配置

一旦选择了grub为引导程序,下面我们来了解一下它的配置.

/boot/grub/grub.conf是grub产生一个引导选择菜单以及设置一些选项.下面是我的grub.conf:

#==========例子开始==========

# grub.conf generated by anaconda

#

# Note that you do not have to rerun grub after making changes to this file

# NOTICE: You have a /boot partition. This means that

# all kernel and initrd paths are relative to /boot/, eg.

# root (hd0,6)

# kernel /vmlinuz-version ro root=/dev/hda10

# initrd /initrd-version.img

#boot=/dev/hda

default=0

timeout=10

splashimage=(hd0,6)/grub/splash.xpm.gz

# --> Redhat linux 8.0 <--

title Red Hat linux (2.4.18-14)

root (hd0,6)

kernel /vmlinuz-2.4.18-14 ro root=LABEL=/

initrd /initrd-2.4.18-14.img

# --> Microsoft Windows XP <--

title Microsoft Windows XP

rootnoverify (hd0,0)

chainloader +1

#===========例子结束==========

配置选项解释:

以"#"开头的是注释行.

我这里有两个操作系统,分别是Red Hat linux和Microsoft Windows XP.

其中 timeout标识默认等待时间,我这设置为10秒,超过10秒用户还没作出选择的话,将自动选择默认的操作系统(我这里默认的是Redhat linux 8.0)

默认的操作系统是由default一项来控制的,default后的数字表明第几个是默认的,这里0表示第一个,1表示第二个.所以如果你想修改默认的操作系统,就修改default后的数字.

title一项是设置操作系统的名称,grub不支持中文(有点遗憾).

splashimage一项指定grub界面的背景图片,有兴趣的朋友可以修改grub的背景哦!

root
(hd0,6)标识从第一个硬盘,第7个分区来启动搜索引导内核.注意这儿的root与linux的root分区不同,此root非彼root也!
grub的硬盘标识方法与linux的有点不同.在linux中第一个主分区为hda1,第二个主分区为hda1,第一个逻辑分区为hda5,而在
grub中是以(hdx,y)来标识的,如第一个主分区为(hd0,0)第一个逻辑分区为(hd0,1)依此类推.所以这儿root后面的是你的
/boot所在分区标识.

知道了内核在哪儿,还要具体指出哪个文件是内核文件,这就是kernel的工作。

kernel /vmlinuz-2.2.18-14 ro root=LABEL=/.说明/boot/vmlinuz-2.2.18-14
就是要载入的内核。后面的都是传递给内核的参数。ro是以readonly的意思。注意我这里内核前面的路径是"/",因为我的boot单独分了一个区,
如果你没有为boot单独分区,那么内核前面的路径就是"/boot".

initrd用来初始的linux image,并设置相应的参数

再来看一看windows的定义段吧。

这里,我添加了一项来引导 WindowsXP。要完成此操作,GRUB 使用了"链式装入器"(chainloader)。链式装入器从分区
(hd0,0) 的引导记录中装入 winXP 自己的引导装入器,然后引导它。这就是这种技术叫做链式装入的原因 --
它创建了一个从引导装入器到另一个的链。这种链式装入技术可以用于引导任何版本的 DOS 或
Windows。如果你在计算机中装有win98,winme,win2k,winxp的话,chainloader会把引导权交与win的
NTLoader来引导.

(三)Grub启动盘的制作

要制作引导盘,需执行一些简单的步骤。首先,在新的软盘上创建 ext2 文件系统。然后,将其安装,并将一些 GRUB 文件复制到该文件系统,最后运行 "grub" 程序,它将负责设置软盘的引导扇区。

将一张空盘插入 1.44MB 软驱,输入:

# mke2fs /dev/fd0

创建了 ext2 文件系统后,需要安装该文件系统:

# mount /dev/fd0 /mnt/floppy

现在,需要创建一些目录,并将一些关键文件(原先安装 GRUB 时已安装了这些文件)复制到软盘:

# mkdir /mnt/floppy/boot

# mkdir /mnt/floppy/boot/grub

# cp /boot/grub/stage1 /mnt/floppy/boot/grub

# cp /boot/grub/stage2 /mnt/floppy/boot/grub

再有一个步骤,就能得到可用的引导盘。

在linux bash中,从 root 用户运行"grub",该程序非常有趣并值得注意,因为它实际上是 GRUB
引导装入器的半功能性版本。尽管 linux 已经启动并正在运行,您仍可以运行 GRUB 并执行某些任务,而且其界面与使用 GRUB 引导盘或将
GRUB 安装到硬盘 MBR 时看到的界面(即GRUB控制台)完全相同。

在 grub> 提示符处,输入:

grub> root (fd0)

grub> setup (fd0)

grub> quit

现在,引导盘完成了。

(四).恢复被windows破坏的grub.

如果你用grub来引导linux和windows,当windows出毛病重新安装后,会破坏MBR中的grub,这时需要恢复grub.

1.把linux安装光盘的第一张放到光驱,然后重新启动机器,在BOIS中把系统用光驱来引导。

2.等安装界面出来后,按[F4]键,也就是linux rescue模式。

3.一系列键盘以及几项简单的配制,过后就[继续]了。。。这个过程,我不说了,比较简单。

4.然后会出现这样的提示符:

sh#

5.我们就可以操作GRUB了.输入grub:

sh#grub

会出现这样的提示符:

grub>

我们就可以在这样的字符后面,输入:

grub>root (hdX,Y)

grub>setup (hd0)

如果成功会有一个successful......

这里的X,如果是一个盘,就是0,如果你所安装的linux的根分区在第二个硬盘上,那X就是1了;Y,就是装有linux系统所在的根分区。 setup (hd0)就是把GRUB写到硬盘的MBR上。

(五).用NTLoader来引导linux.

如果你在安装linux时没有选择安装grub,不必着急,现在我们来看看如何在安装linux后安装grub.并用windows的NTLoader来引导linux.

1. 安装grub

我用的grub是Redhat8.0带的grub安装包: grub-0.92-7.rpm

安装: rpm -ivh grub-0.92-7.rpm

其他安装方式也一样,只要你安装上grub就行了.RH8缺省用的grub, 1,2步骤可以省了.

2. 建立grub的环境

cp /usr/share/grub/i386-pc/* /boot/grub

3. 生成grub的配置文件/boot/grub/menu.conf

按照上面所讲的grub.conf来生成一个配置文件.

注意了, 这里我的linux在/dev/hda4,所以menu.conf那些分区位置为(hd0,3),

你的可能不一样了,不能完全照着"画瓢"噢! 下面第3步install的中的分区位置也应该和你的系统一致.

3. 安装grub至linux分区boot

将grub的stage1安装到/dev/hda4的boot扇区(hd0,3). 过程如下:

/sbin/grub (运行grub)

grub> install (hd0,3)/boot/grub/stage1 d (hd0,3) (hd0,3)/boot/grub/stage2 p (hd0,3)/boot/grub/menu.conf

(注意,上面"grub>"为grub的提示符,其后内容写在一行上.)

4. 取得grub的boot信息

过程如下:

dd if=/dev/hda4 of=/grub.lnx bs=512 count=1

这样得到grub的引导信息,只要用NT Loader来加载它就行了.

5. 将上面得到的grub.lnx弄到Windows的C盘根目录下

可以先把grub.lnx弄得软盘上,然后启动windows,拷贝到C:; 情况允许也可以直接在linux下拷贝到C:了. 我的C盘(即设备/dev/hda1)为FAT32, 可以直接从Linux下弄过去了. 如下:

mount -t vfat /dev/hda1 /mnt/c

cp /grub.lnx /mnt/c

umount /mnt/c

6. 修改NT Loader的boot.ini

在其中加入一行: C:grub.lnx="Redhat linux - GRUB"

加入后boot.ini的内容如下:

[boot loader]

timeout=15

default=C:oot.lnx

[operating systems]

multi(0)disk(0)rdisk(0)partition(1)WINDOWS="Microsoft Windows XP Professional" /fastdetect

[VGA mode]" /basevideo /sos

C:grub.lnx="Redhat linux - GRUB"

OK. 可以用NT Loader加载linux了, 其实上面过程基本上和用NT Loader加载LILO一样.其基本思想就是用NT Loader来加载LILO或grub的引导区(grub.lnx), 其中的关键就是LILO或grub的引导区的获取.

(六)活用grub的交互功能

grub具有强大的交互功能.学会了将会使你受益非浅!

1.grub没有显示菜单怎么办?

当开机后进入grub界面但没了菜单,只剩下一个grub>提示符,怎么启动呢?别急,看下面:

grub>cat (hd0,6)/boot/grub/grub.conf (为了看参数)

grub>root (hd0,6)

grub>kernel (hd0,6)/vmlinuz-2.4.18-14 ro root=LABEL=/

grub>initrd (hd0,6)/initrd-2.4.18-14.img

grub>boot

OK!启动了吧!以上有些数字要根据你的实际情况更改.

以上这个方法也可以用于测试新编译的内核.

2.进入单用户模式.

有时不小心把root用户密码忘了,只能进入单用户模式来重新设置root密码.方法如下:

开机进入grub界面,按C进入命令行模式,然后按照上面的方法进行,只是在第三步要在后面加入single参数
Oct 26

  这里介绍了在PHP中的面向对象编程(OOP,Object Oriented Programming)。将向你演示如何通过使用一些OOP的概念和PHP的技巧来减少编码和提高质量。祝你好运!



面向对象编程的概念:

不同的作者之间说法可能不一样,但是一个OOP语言必须有以下几方面:



抽象数据类型和信息封装

继承

多态



在PHP中是通过类来完成封装的:



[code:1:430ff1d506]


class Something {

// 在OOP类中,通常第一个字符为大写

var $x;

function setX($v) {

// 方法开始为小写单词,然后使用大写字母来分隔单词,例如getValueOfArea()

$this->x=$v;

}

function getX() {

return $this->x;

}

}

?>

[/code:1:430ff1d506]



  当然你可以按自已的喜好进行定义,但最好保持一种标准,这样会更有效。



  数据成员在类中使用"var"声明来定义,在给数据成员赋值之前,它们是没有类型的。一个数据成员可以是一个整数,一个数组,一个相关数组(associative array)或者是一个对象。



  方法在类中被定义成函数形式,在方法中访问类成员变量时,你应该使用$this->name,否则对一个方法来说,它只能是局部变量。



  使用new操作符来创建一个对象:



  $obj=new Something;



  然后你可以使用成员函数通过:



  $obj->setX(5);

  $see=$obj->getX();



  在这个例子中,setX成员函数将5赋值给对象的成员变量x(不是类的),然后getX返回它的值5。



  你可以象:$obj->x=6那样通过类引用方式来存取数据成员,这不是一个很好的OOP习惯。我强烈建议通过方法来存取成员变量。如果你把成
员变量看成是不可处理的,并且只通过对象句柄来使用方法,你将是一
个好的OOP程序员。不幸的是,PHP不支持声明私有成员变量,所以不良代码在PHP中也是允许的。



  继承在PHP中很容易实现,只要使用extend关键字。



[code:1:430ff1d506]


class Another extends Something {

var $y;

function setY($v) {

$this->y=$v;

}

function getY() {

return $this->y;

}

}

?>

[/code:1:430ff1d506]



  "Another"类的对象现在拥有了父类(Something)的全部的数据成员及方法,而且还加上了自已的数据成 员和方法。



你可以使用



[code:1:430ff1d506]

$obj2=new Something;

$obj2->setX(6);

$obj2->setY(7);

[/code:1:430ff1d506]



PHP现在还不支持多重继承,所以你不能从两个或两个以上类派生出新的类来。



你可以在派生类中重定义一个方法,如果我们在"Another"类中重定义了getX方法,我们就不能使 用"Something"中的getX方法了。如果你在派生类中声明了一个与基派同名的数据成员,那么当你处理它时, 它将“隐藏”基类的数据成员。



你可以在你的类中定义构造函数。构造函数是一个与类名同名的方法,当你创建一个类的对象时会被调 用,例如:



[code:1:430ff1d506]


class Something {

var $x;

function Something($y) {

$this->x=$y;

}

function setX($v) {

$this->x=$v;

}

function getX() {

return $this->x;

}

}

?>

[/code:1:430ff1d506]



  所以你可以创建一个对象,通过:



  $obj=new Something(6);



  构造函数会自动地把6赋值给数据变量x。构造函数和方法都是普通的PHP函数,所以你可以使用缺省参数。



  function Something($x="3",$y="5")



  接着:



  $obj=new Something(); // x=3 and y=5

  $obj=new Something(; // x=8 and y=5

  $obj=new Something(8,9); // x=8 and y=9



  缺省参数使用C++的方式,所以你不能忽略Y的值,而给X一个缺省参数,参数是从左到右赋值的,如果传入的参数少于要求的参数时,其作的将使用缺省参数。



  当一个派生类的对象被创建时,只有它的构造函数被调用,父类的构造函数没被调用,如果你想调用基类的构造函数,你必须要在派生类的构造函数中显示调用。可以这样做是因为在派生类中所有父类的方法都是可用的。



[code:1:430ff1d506]


function Another() {

$this->y=5;

$this->Something();

//显示调用基类构造函数

}

?>

[/code:1:430ff1d506]



  OOP的一个很好的机制是使用抽象类。抽象类是不能实例化,只能提供给派生类一个接口。设计者通常使用抽象类来强迫程序员从基类派生,这样可以确保新的类包含一些期待的功能。在PHP中没有标准的方法,但是:



  如果你需要这个特性,可以通过定义基类,并在它的构造函数后加上"die" 的调用,这样就可以保证基类是不可实例化的,现在在每一个方法
(接口)后面加上"die" 语句,所以,如果一个程序员在派生类中没有覆盖方法,将引发一个错误。而且因为PHP
是无类型的,你可能需要确认一个对象是来自于你的基类的派生类,那么在基类中增加一个方法来实义类的身份(返回某种标识id),并且在你接收到一个对象参
数时校验这个值。当然,如果一个邪恶不好的程序员在派生类中覆盖了这个方法,这种方法就不起作用了,不过一般问题多发现在懒惰的程序员身上,而不是邪恶的
程序员。



  当然,能够让基类对程序员无法看到是很好的,只要将接口打印出来做他们的工作就可以了。



  在PHP中没有析构函数。



  重载(与覆盖不同)在PHP中不支持。在OOP中,你可以重载一个方法来实现两个或重多的方法具有相同的名字,但是有不同数量或类型的参数(这要看语言)。PHP 是一种松散类型的语言,所以通过类型重载不起作用,然而通过参数的个数不同来重载也不起作用。



  有时在OOP中重载构造函数非常好,这样你可以通过不同的方法创建对象(传递不同数量的参数)。在PHP

中实现它的技巧是:



[code:1:430ff1d506]


class Myclass {

function Myclass() {

$name="Myclass".func_num_args();

$this->$name();

//注意$this->name()一般是错误的,但是在这里$name是一个将被调用方法的名字

}

function Myclass1($x) {

code;

}

function Myclass2($x,$y) {

code;

}

}

?>

[/code:1:430ff1d506]



  通过在类中的额外的处理,使用这个类对用户是透明的:



  $obj1=new Myclass('1'); //将调用Myclass1



  $obj2=new Myclass('1','2'); //将调用Myclass2



  有时这个非常好用。



多态

  多态是对象的一种能力,它可以在运行时刻根据传递的对象参数,决定调用哪一个对象的方法。例如,如果你有一个figure的类,它定义了一个
draw的方法。并且派生了circle和rectangle
类,在派生类中你覆盖了draw方法,你可能还有一个函数,它希望使用一个参数x,并且可以调用$x->draw()
。如果你有多态性,调用哪个draw方法就依赖于你传递给这个函数的对象类型。



  多态性在象PHP这样的解释语言(想象一下一个C++编译器生成这样的代码,你应该调用哪一个方法?你也不知道你拥有的对象是什么类型的,好,这不是重点)是非常容易和自然的。所以PHP当然支持多态性。



[code:1:430ff1d506]


function niceDrawing($x) {

//假设这是Board类的一个方法

$x->draw();

}

$obj=new Circle(3,187);

$obj2=new Rectangle(4,5);

$board->niceDrawing($obj);

//将调用Circle的draw方法

$board->niceDrawing($obj2);

//将调用Rectangle的draw方法

?>

[/code:1:430ff1d506]



用PHP进行面向对象编程

  一些"纯化论者(purists)"可能会说PHP不是一个真正的面向对象的语言,这是事实。PHP
是一个混合型语言,你可以使用OOP,也可以使用传统的过程化编程。然而,对于大型项目,你可能想/需要在PHP
中使用纯的OOP去声明类,而且在你的项目只用对象和类。



  随着项目越来越大,使用OOP可能会有帮助,OOP代码很容易维护,容易理解和重用。这些就是软件工程

的基础。在基于web的项目中应用这些概念就成为将来网站成功的关键。



  PHP的高级OOP技术

  在看过基本的OOP概念后,我就可以向你展示更高级的技术:



序列化(Serializing)

  PHP不支持永久对象,在OOP中永久对象是可以在多个应用的引用中保持状态和功能的对象,这意味着拥有将对象保存到一个文件或数据库中的能力,而且
可以在以后装入对象。这就是所谓的序列化机制。PHP
拥有序列化方法,它可以通过对象进行调用,序列化方法可以返回对象的字符串表示。然而,序列化只保存了对象的成员数据而不包话方法。



  在PHP4中,如果你将对象序列化到字符串$s中,然后释放对象,接着反序列化对象到$obj,你可以继续使用对象的方法!我不建议这样去做,因为
(a)文档中没有保证这种行为在以后的版本中仍然可以使用。(b)这个可能导致一种误解,在你把一个序列化后的版本保存到磁盘并退出脚本时。当以后运行这
个脚本时,你不能期待着在反序列化一个对象时,对象的方法也会在那里,因为字符串表示根本就不包括方法。



  总而言之,PHP 进行序列化对于保存对象的成员变量非常有用。(你也可以将相关数组和数组序列化到一个文件中)。



例子 :



[code:1:430ff1d506]


$obj=new Classfoo();

$str=serialize($obj);

//保存$str到磁盘上

//几个月以后

//从磁盘中装入str

$obj2=unserialize($str)

?>

[/code:1:430ff1d506]



  你恢复了成员数据,但是不包括方法(根据文档所说)。这导致了只能通过类似于使用$obj2->x来存取成员变量(你没有别的方法!)的唯一办法,所以不要在家里试它。



  有一些办法可以解决这个问题,我把它留着,因为对这篇简洁的文章来说,他们太不好。



  使用类进行数据存储

  对于PHP和OOP一件非常好的事情就是,你可以很容易地定义一个类来操作某件事情,并且无论何时你想用的时候都可以调用相应的类。假设你有一个
HTML表单,用户可以通过选择产品ID号来选择一个产品。在数据库中有产品的信息,你想把产品显示出来,显示它的价格等等。你拥有不同类型的产品,并且
同一个动作可能对不同的产品具有不同的意思。例如,显示一个声音可能意味着播放它,但是对于其它种类的产品可能意味着显示一个存在数据库中的图片。你可以
使用OOP或PHP来减少编码并提高质量:



  定义一个产品的类,定义它应该有的方法(例如:显示),然后定义对每一种类型的产品的类,从产品类派后出来(SoundItem类,ViewableItem类,等等),覆盖在产品类中的方法,使它们按你的想法动作。



  根据数据库中每一种产品的类型(type)字段给类命名,一个典型的产品表可能有(id, type, price, description, 等等字段)...然后在处理脚本中,你可以从数据库中取出type值,然后实例化一个名为type的对象:





[code:1:430ff1d506]


$obj=new $type();

$obj->action();

?>

[/code:1:430ff1d506]



  这是PHP的一个非常好的特性,你可以不用考虑对象的类型,调用$obj的显示方法或其它的方法。使用这个技术,你不需要修改脚本去增加一个新类型的对象,只是增加一个处理它的类。



  这个功能很强大,只要定义方法,而不去考虑所有对象的类型,在不同的类中按不同的方法实现它们,然后在主脚本中对任意对象使用它们,没有if...else,也不需要两个程序员,只有高兴。



  现在你同意编程是容易的,维护是便宜的,可重用是真的吗?



  如果你管理一组程序员,分配工作就是很简单的了,每个人可能负责一个类型的对象和处理它的类。



  可以通过这个技术实现国际化,根据用户所选的语言字段应用相应的类就可以了,等等。





拷贝和克隆

  当你创建一个$obj的对象时,你可以通过$obj2=$obj来拷贝对象,新的对象是$obj的一个拷贝(不是一个引用),所以它具有$
obj在当时的状态。有时候,你不想这样,你只是想生成一个象obj类一样的一个新的对象,可以通过使用new语句来调用类的构造函数。在PHP中也可以
通过序列化,和一个基类来实现,但所有的其它类都要从基类派生出来。





进入危险区域

  当你序列化一个对象,你会得到某种格式的字符串,如果你感兴趣,你可以调究它,其中,字符串中有类的名字(太好了!),你可以把它取出来,象:



[code:1:430ff1d506]


$herring=serialize($obj);

$vec=explode(':',$herring);

$nam=str_replace("\"",'',$vec[2]);

?>

[/code:1:430ff1d506]



  所以假设你创建了一个"Universe"的类,并且强制所有的类都必须从universe扩展,你可以在universe中定义一个clone的方法,如下:



[code:1:430ff1d506]


class Universe {

function clone() {

$herring=serialize($this);

$vec=explode(':',$herring);

$nam=str_replace("\"",'',$vec[2]);

$ret=new $nam;

return $ret;

}

}

//然后

$obj=new Something();

//从Universe扩展

$other=$obj->clone();

?>

[/code:1:430ff1d506]



  你所得到的是一个新的Something类的对象,它同使用new方法,调用构造函数创建出的对象一样。我不知道这个对你是否有用,但是Universe类可以知道派生类的名字是一个好的经验。想象是唯一的限制。
Oct 26
GTK/GNOME 系列widgets中, 输入和显示已经是国际化了的. 所以用它们编写中文软件十分容易. 把西文软件改写成中文软件也十分容易.



   * 在程序中包含 locale.h

   * 在gtk_init前设置locale: gtk_set_locale()

   * 接着调用 gtk_rc_add_default_file(\"rcfilename\"), 其中rcfilename中 含有缺省的fontset

   * 如果不用资源文件, 则应对widget设置fontset

   * 编译 gcc `gtk-config --cflags` entry.c -o entry `gtk-config --libs`

   * 把文件 gtkrc.zh 拷贝到当前目录下



在 gtk 的 text 组件中如果设置了font, 则不能正常显示中文. 解决的方法是把font释放(unref), 然后使用
gtk_fontset_load 字体集. 对于其它组件也是如此, 有的组件需要先拷贝一个 GtkStyle, 然后按上述方法解决.



下面的程序在显示中文时未使用中文平台, 输入使用的是Chinput中的XIM协议支持 , 输出结

果:}
" onmouseover="
function onmouseover(event) {
   if (this.alt) {
       this.style.cursor = "hand";
   }
}
" onload="
function onload(event) {
   if (this.width > screen.width - 333) {
       this.width = screen.width - 333;
       this.alt = "\u70B9\u51FB\u67E5\u770B\u539F\u56FE\uFF01";
   }
}
" alt="点击查看原图" src="http://www.linuxforum.net/chinese/develop/gtk/gtk.gif" />

//file entry.c

#include  

#include  

int main (int argc, char *argv[])

{

GtkWidget *window;

GtkWidget *vbox;

GtkWidget *entry;

GtkWidget *text;

GtkWidget *button;

gtk_set_locale();

gtk_rc_add_default_file(\"./gtkrc.zh\");

gtk_init (&argc, &argv); /* create a new window */

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

// gtk_widget_set_usize( GTK_WIDGET (window), 200, 500);

gtk_window_set_title(GTK_WINDOW (window), \"GTK Entry\");

gtk_signal_connect(GTK_OBJECT (window), \"delete_event\", (GtkSignalFunc) gtk_exit, NULL);

vbox = gtk_vbox_new (FALSE, 0);

gtk_container_add (GTK_CONTAINER (window), vbox);

gtk_widget_show (vbox); entry = gtk_entry_new_with_max_length (60);

gtk_entry_select_region (GTK_ENTRY (entry), 0, GTK_ENTRY(entry)->text_length);

gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);

gtk_widget_show (entry); text = gtk_text_new (NULL, NULL);

gtk_text_set_editable (GTK_TEXT (text), TRUE);

gtk_box_pack_start (GTK_BOX (vbox), text, TRUE, TRUE, 0);

gtk_widget_show(text); button = gtk_button_new_with_label (\"关闭窗口\");

gtk_signal_connect_object (GTK_OBJECT (button), \"clicked\", GTK_SIGNAL_FUNC(gtk_exit), GTK_OBJECT (window));

gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);

gtk_widget_grab_default (button);

gtk_widget_show (button);

gtk_widget_show(window);

gtk_main();

return(0);

}
Oct 26
最近经常有人发现ofstar的漏动。

真得让人感到系统安全是一个很重要的问题。

但是写过程序的人都会知道,

没有一个程序员敢肯定的说,我的程序百分百没有漏动。

俗话说的好:百密一梳

任何事情都不可能很完美。

但我们只能把事情做的尽可能的好

唉~~~

好像把话题扯远了

还是说回重点吧

如果被人发现已经现在了漏动。

就应该尽快的把漏动补好。

但是我们又不可以跑去问那入侵的人是怎样入侵的。

所以我们要做好安全日志

以前看过一些论坛的安全日志。

感觉做得不是很好。只把一些感觉很重要的数据记录起来

使人感觉很安全的

但是,入侵的人都是利用一些不起眼或感觉不重要的数据。

要真正做好这些安全日志,

应该从入侵的途径入手。

浏览器与服务器是通过cookie、get、post、上传实现c/s的。

这也成了入侵者入侵的主要的方式

上传是利用对文件的后缀过滤不而被入侵者所利用来上传木马之类的程序。

但很多程序对这个过滤的都比较成熟。因为不被加我的安全日志

因为都是提交的数据,所以我就想在某些重要的地方实行只要修改系统基本数据的就时候就把所提交的cookie/get/post全部记录。

以保证部分敏感的地方能记录入侵者的入侵方式,使以后能尽快的找到问题所在。解决问题



另外加一个自己对过滤数据的见解。

一、所以通过以上方式提交的数据都要经过过滤。

二、尽可能把变量定义成你想要的变量类型
分页: 107/112 第一页 上页 102 103 104 105 106 107 108 109 110 111 下页 最后页 [ 显示模式: 摘要 | 列表 ]