2009年5月23日星期六
2009年5月18日星期一
Google Blogger被封的解决方案
然后是RSS订阅的问题,如果不使用Google Reader,那么可以用feedburner烧制一个新的RSS地址,提供给他人使用,这个地址经过了feedburner服务器一层所以即是不用代理或是google reader也可以访问。
本博客烧制的新的RSS地址是:http://feeds2.feedburner.com/blogspot/swinging
C语言动态分配二维数组内存
谈的远了点。总之我需要动态申请一个二维数组,而一般方法:先申请一个指针数组再给每元素指针申请一个数组,这种方法得到的数组内存空间是不连续的,而int a[8][7]这样形式的申请的静态空间是连续的。由于上面提到的原因为了将数组赋值到mxArray结构所以需要的数组时内存连续的。google之后发现了一个方法,下改后代码如下:
void **darray_new(int row, int column, int size)原理是先申请一块连续的空间ptdhead (是最终的空间大小),但是只是这样无法通过a[1][2]的形式访问所以需要修改ptdhead[ncount](每个指针数组的元素指针的指向)使其指向正确的位置。
{
void **ptdhead = NULL; //////////在后面说明为什么要用void**类型
void **ptdBody = NULL;//////////在后面说明为什么要用void**类型
//
ptdhead = (void **)malloc(sizeof(void*)*row + sizeof(double)*row*column);
//sizeof(void*)*row是指针大小,sizeof(double)*row*column是所存元素大小
if(!ptdhead)
return NULL;
ptdBody = ptdhead + row ;
for(int ncount = 0; ncount < row; ncount++)
ptdhead[ncount] = ptdBody + ncount * column* sizeof(double)/sizeof(void*);
return ptdhead;
}
2009年5月13日星期三
[转]用Prism剥离WebQQ,超越QQ for linux!
说明:Mozilla Prism Firefox插件版在3.0.10上无法使用。
Mozilla Prism下载地址:[/url]http://prism.mozilla.com/started[/url]
Mozilla Prism的使用很简单,启动prism,出现如下界面:

URL:填写你将要分离的web地址(只要这一栏为没有填错就行了)
Name:随意填写。
一个独立的web程序就剥离出来了,脱离了firefox本身,现在就算firefox崩溃了,prism依然继续运行。

登录webqq后的界面,看起来完全是个独立程序,qq for linux真的可以下岗了!

prism看上去光秃秃的,唯一的设置按钮在右下角,可以设定字体颜色大小、代理地址、打印、甚至还有扩展插件。

通过Prism剥离出来的twitter,相信还有更好玩的一些web可以通过prism剥离出来应用。

转自:http://www.linuxhobby.com/article.asp?id=336
2009年5月12日星期二
[转]多态的理解
在我看来,答案无疑将是多态。封装是优点,继承是基础,重载是特点,而多态则是特征。
虽然这四者缺一不可,无论少了哪一个,就像一个人缺胳膊少腿,使OO将不再是完整的,但是前三者对于OO来说好比鼻子耳朵,而多态则是生殖器,没有多态的OO就象是被阉割的雄性,已经失去其典征。
什么是多态?
简单来说,多态是具有表现多种形态的能力的特征,在OO中是指,语言具有根据对象的类型以不同方式处理之,特别是重载方法和继承类这种形式,的能力。多态被认为是面向对象语言的必备特性。
多态有多种分类,通过了解这些分类可以更丰满对其认识,在这里就不再罗列,请各位参考 wiki大百科 和 javaworld .
多态与泛型(generic)
多态实际上就是泛型。
所谓泛型就是指我们不为特定的类型进行专门编码,而采用对不同类型进行通用编码的方式,无论是数据结果还是算法。
传统的泛型是指类似以Template function的方式使参数一般化,典型的应用是C++ STL,比如List、Vector以及algorithm。
而OO已能通过接口(Interface)和抽象类(Abstract Class)进行真正意义上的泛型了。在我看来,这就是OO最精彩的地方,也就是多态的威力。而对于传统意义上的Generic,我始终觉得其作用已经今不如昔了。
多态和继承(Inheritance)
严格来说,多态与继承、重载并不是孤立的,他们之间存在着紧密的联系,多态是建立在这两者的基础之上的(实际上继承就有用重载这一特性)。
传统的多态实际上就是由虚函数(Virtual Function)利用虚表(Virtual Table)实现的(早期C模拟OO特性时使用最多,C++的实现也是,后来的技术未作研究,是否使用VT不得而知),自然是离不开继承,换句话说多态实际上覆盖了继承。
正是由于继承与多态的紧密联系,使得我们很容易张冠李戴,那么如何区别呢?
举个常用的例子:
Abstract Class Sharp implement IHaveSide {
public bool isSharp(){
return true;
}
public abstract int getSides();
}
Class Triangle extends Sharp {
public override int getSides() {
return 3;
}
}
Class Rectangle extends Sharp {
pubilc override int getSides() {
return 4;
}
}
那么这种类的关系叫做继承,下面这种使用方式也是继承所带来的:
Triangel tri = new Triangle();
println("Triangle is a type of sharp? " + tri.isSharp());
而这种方式则是多态:
Sharp sharp = new Rectangle();
println("My sharp has " + sharp.getSides() + " sides.");
这两者区别在哪?很显然,继承是子类使用父类的方法,而多态则是父类使用子类的方法。
其技术上的区别是绑定时期,晚期绑定一定是多态。
现代软件设计
现代软件大量的使用框架、模式(非特指Deisgn Pattern),也就是将软件开发的一些共性进行抽象,提出普遍适用的软件结构。
无论是框架还是模式,他们都有一些明显的共同点 — 使用xml配置对象,大量使用接口采用所谓面向接口的方法,利用反射实现。
为什么要接口?因为需要抽象,需要将未知的对象在已有的框架中表现。
如何实现接口?多态!所谓反射,实际上就是一种晚期绑定的技术,这个技术实质上表现出来的就是多态这一特征。
面向方面开发(Aspect Oriented Programming)是一个热点,也是现代软件发展的趋势。定制、组件装配的软件开发方式在应用越来越复杂、需求变化越来越快的今天显得日趋重要。那么如何才能使今天的软件能够适应明天需要呢?如何使我开发速度更快?如何能更容易的修改应用?AOP则是解决这些问题的有效手段。
让我们看看框架容器的主要模式,Inversion of Control Containers(IoC)/Dependency Injection(包括setter injection, construct injection, interface injection等),其主要好处就是类之间的依赖,通过运行期的查找来进行绑定。那么他的基础是什么呢?还是多态!
我们可以看到,在现代软件的开发中,无数的思想象火花一样跳动。其中一类很重要的思想就是建立在多态这样一个很基本的特性,甚至可以说是一个语言概念之上的。在这里希望通过这篇文章抛砖引玉,引起更多的对与当今软件发展发向的思考,同时探究其根源。
2009年5月11日星期一
技巧:Linux I/O重定向的一些小技巧
Linux I/O 重定向虽然很简单,但在脚本编写、系统管理时却要常常打交道,搞清其中使用技巧非常有用。
首先说一下什么是I/O重定向,所谓I/O重定向简单来说就是一个过程,这个过程捕捉一个文件,或者命令,程序,脚本,甚至脚本中的代码块(code block)的输出,然后把捕捉到的输出,作为输入发送给另外一个文件,命令,程序,或者脚本。
如 果谈到I/O重定向,就涉及到文件标识符(File Descriptor)的概念, 在Linux系统中,系统为每一个打开的文件指定一个文件标识符以便系统对文件进行跟踪,这里有些和C语言编程里的文件句柄相似,文件标识符是一个数字, 不同数字代表不同的含义,默认情况下,系统占用了3个,分别是0标准输入(stdin),1标准输出(stdout), 2标准错误(stderr), 另外3-9是保留的标识符,可以把这些标识符指定成标准输入,输出或者错误作为临时连接。通常这样可以解决很多复杂的重定向请求。
标准输入通常指键盘的输入
标准输出通常指显示器的输出
标准错误通常也是定向到显示器
请看以下例子,来描述一下他们的关系
#ls /dev |
这个命令列出/dev目录下的所有文件,在屏幕上输出结果。
这里 /dev 就是作为命令ls的标准输入(从键盘输入),而打印在屏幕的结果就是标准输出(/dev目录中的内容)
还是回到标题,重定向就是把标准的输入或者输出更改成其他的方式,请参看如下例子
或者等同于
#ls /dev 1>filename #注意:"1"和">"中间没有空格 |
以上命令会把命令的标准输出重新定向到一个文件filename,而不是显示到屏幕上,如果不指明文件标识符,系统默认的就是1, 因此1可以省略
如果把上面例子重的">"改成">>"则表示把输出追加到filename文件的末尾,如果文件不存在则创建它。如下
#ls /dev >>filename |
也可以把标准错误重新定向到文件
#ls -qw /dev 2>filename |
显然 -qw是一个错误参数,通常会在显示器上报告一个错误信息,但由于把2标准错误(stderr)重新定向到了文件filename,因此显示器没有错误信息,而信息写到了文件里面
以下命令是把标准输出和错误都定向到文件
#ls /dev &>filename |
"&"在这里代表标准输出和标准错误,这里无论是正常输出还是错误信息都写到filename中了。
重新定义标准输入,输出,和错误的文件标识符
重新定义文件标识符可以用i>&j命令,表示把文件标识符i重新定向到j,你可以把"&"理解为"取地址"
请看以下例子
#exec 5>&1 |
表示把文件标识符5定向到标准输出,这个命令通常用来临时保存标准输入。
同样标准输入也是可以重新定向的,请参考下面例子
# grep search-word < filename或者grep word="" 0=""> |
一般来说grep命令在给定文件中搜索字符串,以上命令把文件filename作为grep命令的标准输入,而不是从键盘输入。
前面曾经提到,系统为每一个打开的文件指定一个文件标识符以便系统对文件进行跟踪,那么默认的文件标识符是什么呢?答案是0,也就是标准输入,或者可以说从键盘输入。当然这个文件标识符也可以自己指定,请参考下面例子
#echo 123456789 >filename 把字符串写到文件filename中 |
现在cat filename文件的结果就成了1234.6789
命令j<>filename表示把文件打开,并指明文件标识符为j
"&-"表示关闭文件标识符
有关关闭文件标识符的操作请参考下面
n<&- 关闭输入文件标识符n 0<&-或<&- 关闭标准输入stdin n>&- 关闭输出文件标识符n |
另外还有一些其他命令,如下参考
2. :> filename 或者 > filename |
表示把文件filename设置成空,也就是清空文件内容,如果文件不存在,则创建一个空文件,(等同于touch命令) :表示一个空输出,两个命令的唯一区别就是>filename不是在所有shell都可以正常工作的。
2009年5月8日星期五
想发起一个开源项目,集思广益下
“将菜单栏放到窗口上比起Mac的放到任务栏上更美观,而且这样可以极大的利用屏幕的空间,充分利用窗口的空间,这种方法也类似于一些国产的软件——遨游”
但是这样也存在一个问题:“菜单项过多会影响窗口栏上的点击范围”。
至于程序的可行性,主要要完成的有两个方面,一个是新的窗口管理器,另一个是gtk程序去掉菜单栏(这个Gnome下已经有全局菜单Global Menu Bar项目实现了这个功能,可以参考它们的源码),所以主要是窗口管理器,可以hack现有的Metacity或者是再重写一个。
现在想集思广益下!谁有什么更好的想法?
预计能在7月中旬完成可行性分析,再决定是否继续!
Firefox下的Gnome do——Ubiquity
看一下它的宣传视频就知道了。这已经不是一个新项目了,我最近才试用它,个人感觉非常棒!
Ubiquity for Firefox from Aza Raskin on Vimeo.
2009年5月7日星期四
介绍一个不错的学习软件设计的网站
这个网站:sourcemaking相当适合于学习软件的设计,它提供这方面的知识,主要分为四个部分:设计模式、重构、UML和AntiPattern。
[转]缓冲区溢出攻击
“十年来攻击和防卫的弱点”——缓冲区溢出*攻击
寒路
大凡上网久点的网人对缓冲区溢出应该是知道的,因为它的确是一个众人皆知、非常危险的漏洞,它是个不分什么系统、什么程序,都广泛存在的一个漏洞。以缓冲 区溢出为类型的安全漏洞是最为常见,也是被黑客最多使用的攻击漏洞。所以了解缓冲区溢出方面的知识对于黑客也好或者管理员也好也或者是一般的网人也好都相 对是有必要的。
缓冲区溢出的概念和原理
缓冲区是内存中存放数据的地方。在程序试图将数据放到机器内存中的某一个位置的时候,因为没有足够的空间就会发生缓冲区溢出。而人为的溢出则是有一定企图 的,攻击者写一个超过缓冲区长度的字符串,然后植入到缓冲区,而再向一个有限空间的缓冲区中植入超长的字符串可能会出现两个结果,一是过长的字符串覆盖了 相邻的存储单元,引起程序运行失败,严重的可导致系统崩溃;另有一个结果就是利用这种漏洞可以执行任意指令,甚至可以取得系统root特级权限。大多造成 缓冲区溢出的原因是程序中没有仔细检查用户输入参数而造成的。
缓冲区是程序运行的时候机器内存中的一个连续块,它保存了给定类型的数据,随着动态分配变量会出现问题。大多时为了不占用太多的内存,一个有动态分配变量 的程序在程序运行时才决定给它们分配多少内存。这样想下去的话,如果说要给程序在动态分配缓冲区放入超长的数据,它就会溢出了。一个缓冲区溢出程序使用这 个溢出的数据将汇编语言代码放到机器的内存里,通常是产生root权限的地方,这就不是什么好现象了。仅仅就单个的缓冲区溢出惹眼,它并不是最大的问题根 本所在。但如果溢出送到能够以root权限运行命令的区域,一旦运行这些命令,那可就等于把机器拱手相让了。
?缓冲区溢出漏洞攻击方式
缓冲区溢出漏洞可以使任何一个有黑客技术的人取得机器的控制权甚至是最高权限。一般利用缓冲区溢出漏洞攻击root程序,大都通过执行类似 “exec(sh)”的执行代码来获得root 的shell。黑客要达到目的通常要完成两个任务,就是在程序的地址空间里安排适当的代码和通过适当的初始化寄存器和存储器,让程序跳转到安排好的地址空 间执行。
●在程序的地址空间里安排适当的代码:
其实在程序的地址空间里安排适当的代码往往是相对简单的,但也同时要看运气如何。如果说要攻击的代码在所攻击程序中已经存在了,那么就简单的对代码传递一 些参数,然后使程序跳转到目标中就可以完成了。攻击代码要求执行“exec(‘/bin/sh’)”,而在libc库中的代码执行 “exec(arg)”,当中的“arg”是个指向字符串的指针参数,只要把传入的参数指针修改指向“/bin/sh”,然后再跳转到libc库中的响应 指令序列就OK了。当然了,很多时候这个可能性是很小的,那么就得用一种叫“植入法”的方式来完成了。当向要攻击的程序里输入一个字符串的话,程序就会把 这个字符串放到缓冲区里,这个字符串包含的数据是可以在这个所攻击的目标的硬件平台上运行的指令序列。缓冲区可以设在像:堆栈(自动变量)、堆(动态分配 的)和静态数据区(初始化或者未初始化的数据)等的任何地方。也可以不必为达到这个目的而溢出任何缓冲区,只要找到足够的空间来放置这些攻击代码就够了。
●将控制程序转移到攻击代码的形式:
所有的这些方法都是在寻求改变程序的执行流程,使它跳转到攻击代码,最为基本就是溢出一个没有检查或者其它漏洞的缓冲区,这样做就会扰乱程序的正常执行次 序。通过溢出某缓冲区,可以改写相近程序的空间而直接跳转过系统对身份的验证。原则上来讲攻击时所针对的缓冲区溢出的程序空间可为任意空间。但因不同地方 的定位相异,所以也就带出了多种转移方式。
1、 unction Pointers(函数指针)
在程序中,“void (* foo) ( )”声明了个返回值为“void” Function Pointers的变量“foo”。Function Pointers可以用来定位任意地址空间,攻击时只需要在任意空间里的Function Pointers邻近处找到一个能够溢出的缓冲区,然后用溢出来改变Function Pointers。当程序通过Function Pointers调用函数,程序的流程就会实现。这个你可调用Linux下的superprobe程序体验一下。
2、 ctivation Records(激活记录)
当一个函数调用发生时,堆栈中会留驻一个Activation Records,它包含了函数结束
时返回的地址。执行溢出这些自动变量,使这个返回的地址指向攻击代码,再通过改变程序的返回地址。当函数调用结束时,程序就会跳转到事先所设定的地址,而 不是原来的地址。这样的溢出方式也是较常见的。你在使用漏洞扫描(Unix下的SATAN或者NT下的Retina)器时,最好是多注意“stack smashing attack”的字样。呵呵。
3、 Longjmp buffers(长跳转缓冲区)
在C语言中包含了一个简单的检验/恢复系统,称为“setjmp/longjmp”,意思是在
检验点设定“setjmp(buffer)”,用longjmp(buffer)“来恢复检验点。如果攻击时能够进入缓冲区的空间,感觉 “longjmp(buffer)”实际上是跳转到攻击的代码。像Function Pointers一样,longjmp缓冲区能够指向任何地方,所以找到一个可供溢出的缓冲区是最先应该做的事情。
●植入综合代码和流程控制
常见的溢出缓冲区攻击类是在一个字符串里综合了代码植入和ctivation Records。攻击时定位在一个可供溢出的自动变量,然后向程序传递一个很大的字符串,在引发缓冲区溢出改变ctivation Records的同时植入代码(权因C在习惯上只为用户和参数开辟很小的缓冲区)。植入代码和缓冲区溢出不一定要一次性完成,可以在一个缓冲区内放置代码 (这个时候并不能溢出缓冲区),然后通过溢出另一个缓冲区来转移程序的指针。这样的方法一般用于可供溢出的缓冲区不能放入全部代码时的。如果想使用已经驻 留的代码不需要再外部植入的时候,通常必须先把代码做为参数。在libc(熟悉C的朋友应该知道,现在几乎所有的C程序连接都是利用它来连接的)中的一部 分代码段会执行“exec(something)”,当中的something就是参数,使用缓冲区溢出改变程序的参数然后利用另一个缓冲区溢出使程序指 针指向libc中的特定的代码段。
对缓冲区溢出有兴趣的朋友,有必要找找eEye公司开发的Retina发现IIS4.0的那个缓冲区溢出漏洞引起的很多黑客攻击实例来看看。你可以在 http://www.safefan.com(傲气雄鹰网络安全小组)找到关于它们的资料,做为网络管理人员最因该熟悉它们。
程序编写的错误造成网络的不安全性也当受到重视,因为它的不安全性已被缓冲区溢出表现的淋漓尽致了。
█缓冲区溢出的防患
缓冲区溢出的漏洞被发现到利用以来一直都是网络安全领域的最大隐患,很多安全人士均对这些漏洞做了仔细的研究,但是缓冲区溢出的完全防止往往因为这样那样的人为或者其它的因素仍显得有点力不从心。在这篇文章里,就目前缓冲区溢出漏洞的几种保护方法做个简单的描述。
正确的编写代码
我想在编写代码的时候一般不会有人故意想要发生错误的,但是丝毫的错误往往会造成严重后果(C语言多是字符串因0收尾,往往就是一个很不安全例子)。所以正确的编写代码是很关键的。
在编写时以免错误发生最原始的方法就是用gerp来找出源代码中较容易产生的漏洞的库的调用。像对sprintf和strcpy的调用,这两个函数都不会 检查参数输入的长度。有的在编写的时候采用了sprintf和strcpy的替代函数来防止,但是还是会有问题发生的。因为这些错误的隐蔽性,所以就出现 了查错工具faultin-jection。faultin-jection可以通过人为随时产生一些缓冲区溢出来找到代码的安全漏洞。只能说 faultin-jection等类似的工具可以让编写时缓冲区溢出的漏洞更少一点,而完全的没有则是不现实的。因为它们确实不可能找到所有的溢出缓冲区 的漏洞。编写时重复的检查代码的漏洞可以使程序更加完美和安全。
?非执行的缓冲区
在老版的UNIX系统中,程序的数据段地址空间是不可执行的,这样就使得黑客在利用缓冲区植入代码时不能执行。但是现在的UNIX和Windows系统考 虑到性能和功能的速率和使用合理化,大多在数据段中动态形式的放入了可执行的代码,为了保证程序的兼容性不可能使用所有程序的数据段不可执行间。但可以通 过只设定堆栈数据段不可执行,这样就很大程度上保证了程序的兼容性能。UNIX、Linux、Windows、Solaris都已经发布了这方面的补丁。
检查数组边界
数组边界检查完全没有缓冲区溢出的产生,所以只要保证数组不溢出,那么缓冲区溢出攻击也就只能是望梅止渴了。实现数组边界检查,所有的对数组的读写操作都 应该被检查,这样可以保证对数组的操作在正确的范围之内。检查数组是一件叫人头大的事情,所以利用一些优化技术来检查就减少了负重。可以使用Compaq 公司专门为Alpha CPU开发的Compaq C编译器、Jones&Kelly的C的数组边界检查、Purify存储器存取检查等等来检查。
所有的缓冲区溢出漏洞都归于C语言的“功劳”。如果只有类型-安全的操作才可以被允许执行,这样就不会出现对变量的强制操作。类型-安全的语言被认定为 Java和ML等,但作为Java执行平台的Java虚拟机是C程序,所以攻击JVM的途径就是使JVM的缓冲区溢出。。。。。。。
程序指针完整性检查
程序指针完整性检查在程序指针被引用之前检测到它的改变,这个时候即便是有人改变了程序的指针,也辉因为系统早先已经检测到了指针的改变而不会造成指针对 利用的。但程序指针完整性检查不能解决所有的缓冲区溢出问题;如果有人使用了其它的缓冲区溢出,那么程序指针完整性检查就不可能检测到了。可话又说回来 了,程序指针完整性检查在性能上却有着很大的优势,并且有良好的兼容性。
2009年5月6日星期三
[转]ldconfig命令的用途
为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig.此执行程序存放在/sbin目录下.
ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文 件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so) 所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.
ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.
ldconfig命令行用法如下:
ldconfig [-v|--verbose] [-n] [-N] [-X] [-f CONF] [-C CACHE] [-r ROOT] [-l] [-p|--print-cache] [-c FORMAT] [--format=FORMAT] [-V] [-?|--help|--usage] path...
ldconfig可用的选项说明如下:
(1) -v或--verbose : 用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字.
(2) -n : 用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib,/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录.
(3) -N : 此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache).若未用-X选项,ldconfig照常更新文件的连接.
(4) -X : 此选项指示ldconfig不更新文件的连接.若未用-N选项,则缓存文件正常更新.
(5) -f CONF : 此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf.
(6) -C CACHE : 此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表.
(7) -r ROOT : 此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的).选择此项时,系统默认的配置文件/etc/ld.so.conf,实际对应的为ROOT/etc/ld.so.conf.如用-r /usr/zzz时,打开配置文件/etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件.用此选项,可以大大增加动态链接库管理的灵活性.
(8) -l : 通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接.选择此项时,将进入专家模式,需要手工设置连接.一般用户不用此项.
(9) -p或--print-cache : 此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字.
(10) -c FORMAT 或 --format=FORMAT : 此选项用于指定缓存文件所使用的格式,共有三种:old(老格式),new(新格式)和compat(兼容格式,此为默认格式).
(11) -V : 此选项打印出ldconfig的版本信息,而后退出.
(12) -? 或 --help 或 --usage : 这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出.
举三个例子:
例1:
# ldconfig -p
793 libs found in cache `/etc/ld.so.cache'
libzvt.so.2 (libc6) =>; /usr/lib/libzvt.so.2
libzvt.so (libc6) =>; /usr/lib/libzvt.so
libz.so.1.1.3 (libc6) =>; /usr/lib/libz.so.1.1.3
libz.so.1 (libc6) =>; /lib/libz.so.1
......
#
注: 有时候用户想知道系统中有哪些动态链接库,或者想知道系统中有没有某个动态链接库,这时,可用-p选项让ldconfig输出缓存文件中的动态链接库列 表,从而查询得到.例子中,ldconfig命令的输出结果第1行表明在缓存文件/etc/ld.so.cache中找到793个共享库,第2行开始便是 一系列共享库的名字及其全名(绝对路径).因为实际输出结果太多,为节省篇幅,以......表示省略的部分.
例2:
# ldconfig -v
/lib:
liby.so.1 ->; liby.so.1
libnss_wins.so ->; libnss_wins.so
......
/usr/lib:
libjscript.so.2 ->; libjscript.so.2.0.0
libkspell.so.2 ->; libkspell.so.2.0.0
......
/usr/X11R6/lib:
libmej-0.8.10.so ->; libmej-0.8.10.so
libXaw3d.so.7 ->; libXaw3d.so.7.0
......
#
注: ldconfig命令在运行正常的情况下,默认不输出什么东西.本例中用了-v选项,以使ldconfig在运行时输出正在扫描的目录及搜索到的共享库, 用户可以清楚地看到运行的结果.执行结束后,ldconfig将刷新缓存文件/etc/ld.so.cache.
例3:
# ldconfig /usr/zhsoft/lib
2009年5月5日星期二
设计模式学习的一点心得
简单例子:
public class Factory{使用工厂的原因:当Sample类的构造函数中的需要的大量的操作时,就违背了面向对象的原则.封装(Encapsulation)和分派(Delegation);我们需要将创建实例的责任与使用实例的责任分开, 使得语句
public static Sample creator(){
....
if (which==1)
return new MySample();
else if (which==2)
return new HisSample();
}
}
Sample sample=new Sample(参数);
就是简单的责任:使用Sample 这个实例;至于创建Sample 的任务就交给了Factory 工厂模式.还有,如果Sample 有个继承如MySample, 按照面向接口编程,我们需要将Sample 抽象成一个接口.现在Sample 是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:
Sample mysample=new MySample();
Sample hissample=new HisSample();
随着项目的深入,Sample 可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.
设计模式之Builder
简单例子:
public interface Builder {使用Builder的原因:在Java 实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池."池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder 模式中Director 类使之能诊断"断肢"断在哪个部件上,再修复这个部件。
//创建部件A 比如创建汽车车轮
void buildPartA();
//创建部件B 比如创建汽车方向盘
void buildPartB();
//创建部件C 比如创建汽车发动机
void buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director 类中
进行.
//从而实现了解耦过程和部件
Product getResult();
}
public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC 最后组成复杂对象
//这里是将车轮 方向盘和发动机组装成汽车的过程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
设计模式之Singleton(单例模式)
简单例子:
public class Singleton {应用反向:整个系统中类的实例只有一个。
private static Singleton _instance = new Singleton();
public static Singleton getInstance() {
return _instance;
}
}
调用方法:
Singleton.getInstance()
设计模式之Facade(外观)
Facade 的定义: 为子系统中的一组接口提供一个一致的界面.
较易理解,或许你在不知不觉中已经用过了,不再阐述。
设计模式之Proxy(代理)
Proxy 是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy 是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理.
设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问.
为什么要使用Proxy?
1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive 论坛系统中,就使用Proxy 进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive 中就通过类似ForumProxy 这样的代理来控制这两种用户对论坛的访问权限.
2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.
举例两个具体情况:
(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy 来代替真正的图片.
(2)如果那个对象在Internet 的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy 来代替那个对象.总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java 内存.
所以,有些人认为Java 耗费资源内存,我以为这和程序编制思路也有一定的关系.
*简单例子:
以Jive 论坛系统为例,Forum 是Jive 的核心接口,在Forum 中陈列了有关论坛操作的主要行为,如论坛名称 论坛描
述的获取和修改,帖子发表删除编辑等.
在ForumPermissions 中定义了各种级别权限的用户:
public class ForumPermissions implements Cacheable {因此,Forum 中各种操作权限是和ForumPermissions 定义的用户级别有关系的,作为接口Forum 的实现:ForumProxy 正是将这种对应关系联系起来.比如,修改Forum 的名称,只有论坛管理者或系统管理者可以修改,代码如下:
/**
* Permission to read object.
*/
public static final int READ = 0;
/**
* Permission to administer the entire sytem.
*/
public static final int SYSTEM_ADMIN = 1;
/**
* Permission to administer a particular forum.
*/
public static final int FORUM_ADMIN = 2;
/**
* Permission to administer a particular user.
*/
public static final int USER_ADMIN = 3;
/**
* Permission to administer a particular group.
*/
public static final int GROUP_ADMIN = 4;
/**
* Permission to moderate threads.
*/
public static final int MODERATE_THREADS = 5;
/**
* Permission to create a new thread.
*/
public static final int CREATE_THREAD = 6;
/**
* Permission to create a new message.
*/
public static final int CREATE_MESSAGE = 7;
/**
* Permission to moderate messages.
*/
public static final int MODERATE_MESSAGES = 8;
.....
public boolean isSystemOrForumAdmin() {
return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
}
.....
}
public class ForumProxy implements Forum {而DbForum 才是接口Forum 的真正实现,以修改论坛名称为例:
private ForumPermissions permissions;
private Forum forum;
this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization,
ForumPermissions permissions)
{
this.forum = forum;
this.authorization = authorization;
this.permissions = permissions;
}
.....
public void setName(String name) throws UnauthorizedException,
ForumAlreadyExistsException
{
//只有是系统或论坛管理者才可以修改名称
if (permissions.isSystemOrForumAdmin()) {
forum.setName(name);
}
else {
throw new UnauthorizedException();
}
}
...
}
public class DbForum implements Forum, Cacheable {
...
public void setName(String name) throws
ForumAlreadyExistsException {
....
this.name = name;
//这里真正将新名称保存到数据库中
saveToDb();
....
}
...
}
凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy 打交道,由
ForumProxy 决定是否有权限做某一样事情,ForumProxy 是个名副其实的"网关","安全代理
系统".
先写这么多了,懒了
2009年5月3日星期日
认识下linux下程序的国际化(C语言实例)
not: xgettext是国际化的工具,提取出源文件中的字符串,生成*.po的文件,而msgfmt是本地化的工具,首先是人工的翻译*.po文件中的字符串,然后使用msgfmt生成*.mo文件,再编译后,程序启动时会扫描系统环境提取mo文件中的字符串代替原来的英文。测试实例(helloworld):
#include将程序这样改写以后,就叫国际化了,简单吧?但不是说这样程序就能根据系统环境显示相应的界面了,我们还需要将它本地化;我们将程序保存为test_locale.c;;
#include;
#include; //包含了两个头文件
#define _(STRING) gettext(STRING) //定义了_(STRING)宏,只是为了简化
#define PACKAGE "test_locale" //定义了软件包的名字,最后生成的.mo文件名应该命名为这个
#define LOCALEDIR "./po" //定义了mo文件将要存放的位置
int main(int argv,int*argc[])
{
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR); //bind软件包与mo文件存放的位置
textdomain (PACKAGE);
printf(_("hello,world!\n")); //将_(STRING)宏应用到了字符串上
}
利用xgettext生成test_locale.po文件
xgettext -k_ -o test_locale.po test_locale.c-k 指定翻译字符以何种宏定义括起,我们在前面使用的是 _( ) 所以用 -k_
编辑test_locale.po文件成:
接下来再利用msgfmt生成test_locale.mo文件
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-03 23:25+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" //注意修改charset的值
"Content-Transfer-Encoding: 8bit\n"
#: hello_I18N.c:15
#, c-format
msgid "hello,world!\n"
msgstr "你好,世界!\n" //翻译
msgfmt -o test_locale.mo test_locale.po将test_locale.mo文件放在之前设定的LOCALEDIR/xxxx/yyyyy目录下,其中的xxxx和yyyy稍后就明白了;
现在再来看看程序的运行结果
当系统环境 LANG=en_US的时候,结果如下:
hello,world!
当系统环境 LANG=zh_CN.UTF-8的时候,结果如下:
你好,世界!
就是说,在程序运行时,会根据LANG自动到LOCALEDIR/zh_CN/LC_MESSAGES寻找mo文件,从而正确显示;所以上文中的xxxx和yyyy就是zh_CN和LC_MESSAGES。
2009年4月30日星期四
[转]Facebook 如何管理150亿张照片(值得学习)
旧的 NFS 照片架构
老的照片系统架构分以下几个层:
# 上传层接收用户上传的照片并保存在 NFS 存储层。
# 照片服务层接收 HTTP 请求并从 NFS 存储层输出照片。
# NFS存储层建立在商业存储系统之上。
因为每张照片都以文件形式单独存储,这样庞大的照片量导致非常庞大的元数据规模,超过了 NFS 存储层的缓存上限,导致每次招聘请求会上传都包含多次I/O操作。庞大的元数据成为整个照片架构的瓶颈。这就是为什么 Facebook 主要依赖 CDN 的原因。为了解决这些问题,他们做了两项优化:
# Cachr: 一个缓存服务器,缓存 Facebook 的小尺寸用户资料照片。
# NFS文件句柄缓存:部署在照片输出层,以降低 NFS 存储层的元数据开销。
新的 Haystack 照片架构
新的照片架构将输出层和存储层合并为一个物理层,建立在一个基于 HTTP 的照片服务器上,照片存储在一个叫做 haystack 的对象库,以消除照片读取操作中不必要的元数据开销。新架构中,I/O 操作只针对真正的照片数据(而不是文件系统元数据)。haystack 可以细分为以下几个功能层:
# HTTP 服务器
# 照片存储
# Haystack 对象存储
# 文件系统
# 存储空间
存储
Haystack 部署在商业存储刀片服务器上,典型配置为一个2U的服务器,包含:
# 两个4核CPU
# 16GB – 32GB 内存
# 硬件 RAID,含256-512M NVRAM 高速缓存
# 超过12个1TB SATA 硬盘
每个刀片服务器提供大约10TB的存储能力,使用了硬件 RAID-6, RAID 6在保持低成本的基础上实现了很好的性能和冗余。不佳的写性能可以通过高速缓存解决,硬盘缓存被禁用以防止断电损失。
文件系统
Haystack 对象库是建立在10TB容量的单一文件系统之上。文件系统中的每个文件都在一张区块表中对应具体的物理位置,目前使用的文件系统为 XFS。
Haystack 对象库
Haystack 是一个简单的日志结构,存储着其内部数据对象的指针。一个 Haystack 包括两个文件,包括指针和索引文件:
Haystack 对象存储结构
指针和索引文件结构
Haystack 写操作
Haystack 写操作同步将指针追加到 haystack 存储文件,当指针积累到一定程度,就会生成索引写到索引文件。为了降低硬件故障带来的损失,索引文件还会定期写道存储空间中。
Haystack 读操作
传到 haystack 读操作的参数包括指针的偏移量,key,代用Key,Cookie 以及数据尺寸。Haystack 于是根据数据尺寸从文件中读取整个指针。
Haystack 删除操作
删除比较简单,只是在 Haystack 存储的指针上设置一个已删除标志。已经删除的指针和索引的空间并不回收。
照片存储服务器
照片存储服务器负责接受 HTTP 请求,并转换成相应的 Haystack 操作。为了降低I/O操作,该服务器维护着全部 Haystack 中文件索引的缓存。服务器启动时,系统就会将这些索引读到缓存中。由于每个节点都有数百万张照片,必须保证索引的容量不会超过服务器的物理内存。
对于用户上传的图片,系统分配一个64位的独立ID,照片接着被缩放成4种不同尺寸,每种尺寸的图拥有相同的随机 Cookie 和 ID,图片尺寸描述(大,中,小,缩略图)被存在代用key 中。接着上传服务器通知照片存储服务器将这些资料联通图片存储到 haystack 中。
每张图片的索引缓存包含以下数据
Haystack 使用 Google 的开源 sparse hash data 结构以保证内存中的索引缓存尽可能小。
照片存储的写/修改操作
写操作将照片数据写到 Haystack 存储并更新内存中的索引。如果索引中已经包含相同的 Key,说明是修改操作。
照片存储的读操作
传递到 Haystack 的参数包括 Haystack ID,照片的 Key, 尺寸以及 Cookie,服务器从缓存中查找并到 Haystack 中读取真正的数据。
照片存储的删除操作
通知 Haystack 执行删除操作之后,内存中的索引缓存会被更新,将便宜量设置为0,表示照片已被删除。
重新捆扎
重新捆扎会复制并建立新的 Haystack,期间,略过那些已经删除的照片的数据,并重新建立内存中的索引缓存。
HTTP 服务器
Http 框架使用的是简单的 evhttp 服务器。使用多线程,每个线程都可以单独处理一个 HTTP 请求。
结束语
Haystack 是一个基于 HTTP 的对象存储,包含指向实体数据的指针,该架构消除了文件系统元数据的开销,并实现将全部索引直接存储到缓存,以最小的 I/O 操作实现对照片的存储和读取。
本文国际来源:http://www.facebook.com/FacebookEngineering#/note.php?note_id=76191543919&ref=mf
中文翻译来源:COMSHARP CMS 官方网站
编译安装Vala Toys for GEdit
按照:http://code.google.com/p/vtg/wiki/Compile的步骤编译安装。
不过需要注意的是它的依赖(我选的svn里的版本,vala语言的版本也是0.7.1):
- glib (at least 2.12.0)
- gtk+ (at least 2.10.0)
- gedit (at least 2.22.0)
- gtksourcecompletion 0.7.0 - http://github.com/chuchiperriman/gtksourcecompletion/downloads
- gnu readline (required only for vsc-shell)
- vala 0.7.x GIT - git://git.gnome.org/vala - (master commit 66ee67c85209b6cbc8f488c2bd003b0bc3a9fc3b)
sudo apt-get install libreadline5-dev gedit-dev
就可以了。如果不装全会出现错误:

gtksourcecompletion需要编译安装,这个容易./configure, make, make install就可以了。
就下来正式安装就是:
./autogen.sh --prefix=/home/zmm/.gnome2/gedit/plugins --datadir=/home/
zmm/.gnome2/gedit/plugins
make
make install

即可,最后完成了安装。不过如何启用这个插件呢?
很简单,将~/.gnome2/gedit/plugins/lib/gedit-2/plugins下的东西移到~/.gnome2/gedit/plugins/即可。在重新打开Gedit在首选项/插件中启用vala toy即可。

附录:目前插件还在开发之中,发现new project选项不是很好用。期待以后改正,目前可以用
/home/zmm/.gnome2/gedit/plugins/bin目录下的vala-gen-project生成工程打开。vsc-shell的功能还在琢磨中...
vs2005打开项目后自动关闭问题
找到了以下的回复:
我遇到过类似的问题,发现是VMware(我用的是6.0)搞的鬼(因为我把它的几个自动启动的服务 VMware Authorization/VMware DHCP Service/VMware NAT Service给设成手动并停止了)前几天为了试装一下leopard装了一个vmware。现在没什么需要了,干脆卸了。
visual Studio 可以正常使用.
重启之后万事大吉了!
2009年4月29日星期三
编译vala过程
sudo apt-get install flex bison
然后解压源码之后输入
./configure本人使用./configure时加了参数--perfix=/usr/local所以导致了一个安装完后运行时的一个错误:
make
sudo make install
valac: error while loading shared libraries: libvala.so.0: cannot open shared object file: No such file or directory
应该是共享库的路径没有/usr/local/lib。
解决方法很简单就是修改/etc/ld.so.conf加入/usr/local/lib一行,然后运行sudo ldconfig
之后就可以了。
[Shell]set、env、export的区别
env 显示当前用户的变量
export 显示当前导出成用户变量的shell变量
每个shell有自己特有的变量(set)显示的变量,这个和用户变量是不同的,当前用户变量和你用什么shell无关,不管你用什么shell都在,比 如HOME,SHELL等这些变量,但shell自己的变量不同shell是不同的,比如BASH_ARGC, BASH等,这些变量只有set才会显示,是bash特有的,export不加参数的时候,显示哪些变量被导出成了用户变量,因为一个shell自己的变 量可以通过export “导出”变成一个用户变量。
2009年4月28日星期二
自己动手丰衣足食,hack了一个gnome主题
2009年4月19日星期日
面向对象中类、对象、实例
例如代码:
class Boy{上述代码中Boy是类,b是对象同时又是实例。
string name;
public Boy(String name){
this.name = name;
}
public static void main(String[] args) {
Boy b = new Boy();
}
}
***类:是具有相同属性特征和行为规则的多个“对象”的一种统一描述。
***对象:是对现实世界中实体的一种模拟工具。
***实例:是某某的具体的实体。例如java中对象是类的实例。
有些情况下描述不一样,如GLib库实现的面向对象编程。
对象的结构分为三部分:
- 对象的ID标识(唯一,无符号长整型,所有此类对象共同的标识);
- 对象的类结构(唯一,结构型,由对象的所有实例共同拥有);
- 对象的实例(多个,结构型,对象的具体实现)。
这种情况与java有所不同
