作者: 下弦 古月
深入解析序列点
int i = 3;
i = i++;
cout << i;
结果是什么?有人可能会说是3,也有人可能会说是4,更多的人在骂出题的人白痴,但这语句究竟有何问题呢?未必每个人都清楚。
有些人也许马上会说,这是“未定义行为”。没错,这是一个典型的未定义行为。i = i++这个表达式合乎C++语法,能够顺利编译通过,但是执行的结果,标准说“未定义”。为什么是“未定义”,深究起来,要从序列点说起。
序列点是程序中这样的一些点:通俗地说,执行至此,之前的语句都已经彻底执行干净执行完了,之后的语句还完全没开始执行;更常见、更严谨但略晦涩的说法是,之前的语句对现场环境的改变已经全部完成,之后的语句对现场环境的改变还没有开始。啥是现场环境呢?就是程序执行到某一点的那个状态,包括变量的内容、文件的内容等。
这跟最开始那个例子有什么关系呢?关键的问题来了:标准规定,两个序列点之间,程序执行的顺序可以是任意的。没错,正如你猜的那样,C++标准规定一个完整的表达式结束之后有一个序列点,而例子中i = i++是位于两个序列点之间的。编译器可以先算完i++,再写结果给i,也可以先将i = i,再令i++.按前面的方法算,i先自增变为4,然后i++返回3,于是i被赋值为3;按后一种方法算,i先被赋值为3,随后自增变成4.标准说了,这两种处理方法,编译器你爱选那种就选哪种,随便。如果谁写的程序像这样依赖执行的顺序,让他自己哭去!
等等,有人要问了,++的优先级难倒不是高于=吗?显然应该先执行++啊。这里有个概念的问题,前一段说的编译器先算i = i,绝不是说令=的优先级比++还高了。如果那样的话,表达式将变成 (i = i)++,也就是i.operator = (i)。 operator ++,执行++的主体变成i = i这个表达式的返回值了。上一段所说的先计算i = i,实际上还是先计算i++,只不过是先返回了i的值,然后推迟了将i自增1的操作先去干别的(i = i)去了,回头再来给i自增1.
——“什么,你说先干别的就先干别的,凭什么!”
嗯,我再重复一遍,标准规定,两个序列点之间,程序执行的顺序可以是任意的。
——“不是吃饱了撑的嘛,标准搞这个干啥?严格按照顺序执行不就完了嘛”。
C++标准弄这么复杂自然是有道理的。C++是极为重视执行效率的语言,这样做给了编译器优化的空间。比如考虑
int j = i++;
如果非得把i++执行干净了再干别的,那就不得不 temp = i; i += 1; j = i; .如果允许编译器打乱顺序执行呢,直接 j = i; i +=1; 就好了,省了一个temp倒一次的过程。
多说一句,一些更高层的语言,不是像C++这种极为重视效率的,比如Java,上面的例子就完全没有问题。Java完全不允许你编译器乱搞,上面那个例子,在Java中一定是先把i++彻底执行干净了返回3,再进行赋值,赋值完之后不会再有别的操作了,所以结果一定是3.
如何避免由序列点造成的这种未定义行为,有一句经典但有点晦涩的编程规则:“在相邻的两个序列点之间,一个对象只允许被修改一次,而且如果一个对象被修改则在这两个序列点之间只能为了确定该对象的新值而读一次”。其实明白了序列点具体是怎么回事,这个规则应该就很容易明白了。由于序列点之间程序执行顺序不确定,一个对象被修改多次的话最后留下的是哪次的结果就不确定。另外如果一个对象同时存在读取和修改,只有根据读取的结果来修改才是合法的,否则就会出现是先改完再读还是先读完再改的混乱。
最后再说一下最新的C++2003标准中定义的序列点(详细说明请参考标准)
·完整声明之后
·完整表达式之后
·进入函数时与退出函数时
·|| && ?: , 四个操作符的第一个操作数之后
最后一个似乎有点奇怪,为啥 + – 操作符之前就没有序列点,|| &&之前就有呢?a+b之间没有序列点而a||b之间就有,不公平啊。
嗯,你猜的没错,是为了短路。
不过要是手建重载了默认的||和&&,他们可就视同普通函数,不会在第一个操作数之后有序列点了,切记。
本文引自 huiguixian 的博客
序列点
这篇文章大概会用到的术语有,序列点(sequence points),副作用(side effects)。
在C99标准文件5.1.2.3讲到了序列点问题,序列点的定义是一个程序执行中的点,这个点的特殊性在于,在这个点之前语句产生的所有副作用都将生效,而后面语句的副作用还没有发生。在这一点,所有的事都是肯定的,而在序列点间,不能肯定某一个变量的值已经稳定,所以总体说来C语言的序列点只是用来说明这一点的值是肯定的。如何理解呢?先讲一下什么是副作用。
一个表达式有一个值,而在写出这个表达式的时候可能只是想要取得这个表达式的值。但有些表达式会有副作用。而有些表达式没有副作用,有时候我们正是要利用表达式的副作用来工作。比如:
int a = 10;
int b = a; /* a这个表达式在这里没有副作用,这里只是想要取得 */
/* a这个变量的值10,而b = a这个表达式有副作用,它的 */
/* 副作用是使b的值改变成a的值。 */
这就是所谓的一个表达式的副作用。正是因为有了副作用,很多功能才得以完成。有些表达式既会产生一个值,也会产生副作用。如i++这个表达式既会产生一个值(它是i自增以前的值),也会产生副作用。
在一个序列点之间,连续两次改变,并且访问该变量,会带来问题,比如经典的:
int i = 1;
i = i++;
在一个序列点之间,改变了i的值,并且访问了i的值,它的作用是什么呢?是a[1] = 1;还是a[2] = 2呢?不确定,这种代码没有价值,并且老板肯定不会赏识你写出这么精简的代码,你会被开除的。
再比如更经典的:
int i = 1;
printf(“%d, %d, %dn”, i++, i++, i++);
i = 1;
printf(“%dn”, i++ + i++ + i++);
i = 1;
printf(“%dn”, ++i + ++i + ++i);
很多大学的C语言老师都会讲解这个问题,包括我的老师,在讲的时候笔者就没有弄明白,其实,这是一个不值得讲解的问题,这是在跟编译器较劲,不同的编译器可能会得出不同的结果(但是平常的编译器可能会得出相同的结果,让程序员私下总结错误的经验。),这种根据不同的实现而得出不同的结果的代码没什么用。i++ + i++ + i++只是一个表达式,在这个表达式的内多次访问了变量i,结果不确定。并且这又会引发另外一个有趣的问题,可能有人会认为在这条语句执行完成以后i自加了3次,那i肯定是4?这也不确定,可能很多编译器做得确实是4,但是,在C标准中有这样一条:当一个表达式的值取决于编译器实现而不是C语言标准的时候,其中所做的任何处理都会不确定。即,如果有一个编译器在i++ + i++ + i++这个表达式中只读取一次i的值,并且一直记住这个值,那么算第一个i++,因为i的值是1所以算出后i的值为2,再算第二个因为假设的是只读取一次i的值,那此时i的值还是1并且被加到2(因为没有经过序列点,所以i的值不能肯定为2),于是经过三次从1加到2的过程以后,最后i的值是2而不是期望的4,呵呵。
其实这要看编译器如何实现了,不过既然得看编译器如何实现,那这种代码也得被炒鱿鱼。
既然序列点这么重要,那现在就得讲讲一些重要的序列点了,这些重要的序列点要程序员自己平时总结。
1). 一个重要的序列点在完整表达式的结尾,所谓完整表达式就是指不是一个更大的表达式的子表达式的表达式,仔细理解。
int i = 1;
i++; /* i++是一个完整表达式 */
i++ + 1; /* i++就不是一个完整的表达式,因为它是i++ + 1这个完整表达式的一部分 */
具体的完整表达式的种类,可以查阅相关资料,C99的标准文档是一个不错的选择。
2). 逗号表达式。逗号表达式会严格的按照顺序来执行并且在被逗号分隔开的表达式之间有一个序列点,所以,前一个逗号表达式如果是i++,则后面的表达式可以肯定现在的值是原来的值加1(如果有溢出则另当别论)。如:
int i = 1;
i++, i++, i++;
printf(“%dn”, i);
现在的i肯定是4;
3). &&和||运算符。有一种短路算法来解决除法中的除0情况。如下
int a = 10;
int b = 0;
if (b && a/b) {
/* some code here */
}
其中在求b的值的时候会短路,即,a/b不会执行。因为b的值为0,这样可以放心的使用除法了。这两个运算符在使用的时候都可以当成一个序列点,如果前一个表达式的值已经可以认定这整个表达式的值为真或者为假,则后面的表达式没有必要再求值,是多余的。即如上面的a/b是多余的,不能求值,求值也会出错。它们之间的求值顺序是肯定的。
4). 条件运算符?:。在问号的地方也存在一个序列点,也没什么可讲。反正就是问号前后可以访问和改变同一个变量,并且这种访问是安全的。
最后,在一个表达式内的求值顺序没有固定顺序,还有一个表现是,如下:
funa() + funb() + func();
C语言标准没有规定这三个函数谁会先执行,如果对顺序有要求,可以用临时变量来缓解。
本文引自 东东的小窝
《悟空传》的感动
悟空传,更多的是一种回忆,时间流逝,多少人失去了自己当初的理想,而那些坚持理想的人,我们并不孤单!
1.我要这天,再遮不住我眼,要这地,再埋不了我心,要这众生,都明白我意,要那诸佛,都烟消云散!
2.也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大
3.生我何用?不能欢笑。灭我何用?不减狂骄。
4.我终不能改变那个开始,何不忘了那个结局呢
5.你跳不出这个世界,是因为你不知道这个世界有多大,一旦你知道了,你就超出了它。
6.你心中无爱,怎会懂珍惜二字。
7.我像一个优伶,时哭时笑着,久而久之,也不知这悲喜是自己的,还是一种表演,很多人在看着我,他们在叫好,但我很孤独,我生活在自己的幻想中,我幻想着我在一个简单而又复杂的世界,那里只有神与妖,没有人,没有人间的一切琐碎,却有一切你所想象不到的东西。但真正生活在那里,我又孤独,因为我是一个人。
8.若天压我,劈开那天,若地拘我,踏碎那地,我等生来自由身,谁敢高高在上.
9.因为我想活着,我不能掩藏我心中的本欲,正如我心中爱你美丽,又怎能嘴上装四大皆空。
10.原来一生一世那么短暂,原来当你发现所爱的,就应该不顾一切的去追求。因为生命随时都会终止,命运是大海,当你能够畅游时,你就要尽情游向你的所爱,因为你不知道狂流什么时候会到来,卷走一切希望与梦想。
11.天地何用?不能席被,风月何用?不能饮食。纤尘何用?万物其中,变化何用?道法自成。面壁何用?不见滔滔,棒喝何用?一头大包。生我何用?不能欢笑,灭我何用,不减狂骄。从何而来?同生世上,齐乐而歌,行遍大道。万里千里,总找不到,不如与我,相逢一笑。芒鞋斗笠千年走,万古长空一朝游,踏歌而行者,物我两忘间。嗨!嗨!嗨!自在逍遥……
12.这个世界上,有些人是没有家的。你让他回去,他找不到来时的路,找不到要去的地方,就会死在某个角落里。
13.所谓解脱,不过就是死亡。所谓正果,不过就是幻灭。所谓成佛,不过就是放弃所有的爱与理想,变成一座没有灵魂的塑像。
14.这个天地,我来过,我奋战过,我深爱过,我不在乎结局。
15.我虽然是只猪, 但我,不, 任, 你, 们, 宰!
16.相遇皆是缘 缘尽莫强求
17.我不知道为什么要因为失去而忧伤,为什么为了时光短暂而忧虑。我要去找到那力量,让所有的生命都超越界限,让所有的花同时在大地上开放。让想飞的就能自由飞翔,让所有人和他们喜欢的永远地在一起。
18.世上有什么比玩过家家更幸福的事?你想要的生活,你想得到的一切,都可以得到。
19.死就是什么也看不见,什么也听不见,什么也感觉不到,什么也不会想,就像你未出生时一样.
20.不要死 也不要孤独的活
21.当五百年的光阴只是一个骗局,虚无时间中的人又为什么而苦,为什么而喜呢?
22.是不是选择任何一个方向,都会游向同一个宿命呢?
23.我要这天再遮不住我眼。 我要这地再埋不了我心。 要这众生都明白我意。 要那诸佛都烟消云散!
24.你不觉得晚霞很美吗? 我只有看着这个,才能每天坚持西走下去.
25.“师父,我一直在想,天下万物,皆来于空,可这众生爱痴,从何而来?天下万物,又终归于空,那人来到尘世浮沉,为的又是什么?”
26.我知道天会愤怒。如果人触犯了它的威严。但天是否知道人也会愤怒?如果他已一无所有。当我乞求时,你傲慢冷笑。当我痛苦时,你无动于衷。现在我愤怒了。我要听到天的痛哭。我要听到神的乞求。我知道天会愤怒。但你知道天也会颤抖吗?苍穹动摇时,我放声大笑,挥开如意金箍棒,打它个地覆天翻。从今往后一万年,你们都会记住我的名字,齐天大圣孙悟空。
27.也许曾有过那样一个我,那样的生活过。他的身影印在这个时代里。我看见他的传说。
28.我若成佛,天下无魔,我若成魔,佛奈我何。
29.负尽千重罪,炼就不死心.
30.能记得你的人已经不在了,我也已经不在了,没有人再爱着你也没有人再恨着你,一切不过是虚无,我也只是虚无,在宇宙间飘忽,没有倒影,光线穿透我而去,没有人看见我.
31.如来是什么 如是道来.
32.世间没有一件造物会是完美的,但有时缺憾会更美。
33.你们慢聊,我不打扰了。我要去那幽深的雨巷散步,期盼再相逢一个丁香花样的妖精……
34.那猴王桀骜的狂笑着,鲜血从他的眼耳口鼻中流淌出来,那是太长的战斗震坏了五脏。“我是六耳猕猴?哈哈哈哈,我是六耳猕猴?”猴王狂笑着,支撑着他残破身躯屹立不倒的,除了那九万九千九百九十九斤的金箍棒,就只剩下他顶天立地的自尊。
35.我心中爱着你的美丽,又怎能嘴上装四大皆空。
36.道法法不可道,问心心无可问,悟者便成天地,空来自在其中。
37.长夜漫漫 还是醉些的好
38.我一闭上眼睛,世界上就只有我自己,所以我就会害怕,一睁眼,看见那么多的自己,就很安心了。风一吹,我们沙沙啦的响着,我就在这些声音中知道了自己的存在,安心的睡去。
39.对我来说,任何一个地方都是家。可有的人却把家放在世界某一个地方,所以他们才会找不到,才会死在路上。
40.我劝人清心忘欲,可生由空而生,又教之向空而去,不过是教来者向来处去。苍生之于世间,如落叶纷纷向大地,生生不息,本不用导,也许还有别的真义。
41.纷纷落叶飘向大地,白雪下种子沉睡,一朵花开了又迅速枯萎,在流转的光的阴影中,星图不断变幻,海水中矗起高山,草木几百代的荣枯,总有一片片的迎风挺立,酷似它们的祖先。
42.我像一个优伶,时哭时笑着,也不知道着悲喜是自己的,还是一种表演,很多人在看着我,他们在叫好,但我很孤独,我生活在自己的幻想中,我幻想着我在一个简单而又复杂的世界,那里只有神与妖,没有人,没有人间的一切琐碎,却有一切你所想象不到的东西。但真正生活在那里,我有孤独,因为我是一个人。这么想着的也许是唐僧,是孙悟空,是猪八戒,是沙和尚,是树上的女妖双儿,他们都是人,所以他们会这样想,尽管他们都不怎么像人,这也许就是他们痛苦的根源。
43.神不贪,为何容不得一点儿对其不敬?神不恶,为何要将地上千万生灵命运,握于手中?“人为什么想成为神,我想,是因为那样至少自己的命运,不用握在他人之手。”
44.我要让这天再也遮不住我的眼 让这地再也葬不了我的心命运是大海,当你能够畅游时,你就要纵情游向你的所爱,因为你不知道狂流什么时候会到来,卷走一切希望与梦想。
45.小白龙忽然觉得自己要哭了,这些天她没说一句话,只是听和尚说,看和尚读书,扫地,看和尚思索时紧缩的眉头,看和尚入睡时平和的面容。她觉得她已经离不开这些,东海龙宫里没有这样一个人,万里东海没有这样一个人,茫茫尘世也只有一个这样的人。
46.是不是所有的方向都会驶向同一个宿命
47.我走得再远也走不出那片天么?
48.也许,在每个人的心里都会有一个天宫,有一片黑暗,在那边黑暗的深处,会有一片水面,里面映出他心的影子,灵魂就居住在那里,可是当一个人决定变成一个神,他就必须抛弃这些,他要让那水面里什么也没有,什么也看不见,一片空寂之时,他就成仙了,可是心里是空空的,那是什么滋味?你知道么?你……”
49.当命运早已注定,而你却无法改变时,你会做些什么?是做一只望着月亮哭泣的猪?还是反抗到粉身碎骨的石猴?如果失去是苦,你还怕不怕付出如果坠落是苦,你还要不要幸福 如果迷乱是苦,该开始还是结束 如果追求是苦,这是坚强还是执迷不悟?
50.忘记了一切,是不是就没有了痛苦…..
51.生难道又不是梦幻么?你所得的你最终全会失去,你认为那是真的,你就会痛苦,而你知道那不过是一个游戏一个梦境,你就能解脱。人生在世,百年也好,千万年也好,都是未来前的一瞬,这一瞬后你什么都没有,你曾有的只有你的自己。你在世上永远地孤寂着,永远找不到能依托你的东西,除非你放弃你自己,融入到造物之中,成为万重宇宙一点尘埃,你就安乐了
52.等到那一刹那,黑暗的天空突然被一道巨大的闪电划开,孙悟空一跃而起,将金箍棒直指向苍穹,“来吧!”那一刻被电光照亮的他的身姿,千万年后仍凝固在传说之中。
— 今何在<悟空传>
在路由器上架设网站(5):动态域名
终于路由器上的网站运行起来了,但是觉得用ip访问太不科学了,
要是可以用域名访问就方便了!!
动态域名,Tomato DualWan内置有这个功能,
并且它还提供了一个很简单的域名解析服务WindDns
WindDns里面可以免费申请dns66.net的二级域名,对于没有顶级域名的来说非常方便!
下面来说说设置:
一.注册WindDns帐号,并登陆,
1.申请域名
进入域名管理,可以注册一个免费二级域名
例如:sharelife.dns66.net
2.添加解析记录
点击该域名进入域名记录
sharelife.dns66.net的域名记录
RR | 类型 | 值 | 优先级 | TTL | 线路 | 状态 | 操作 |
---|---|---|---|---|---|---|---|
sharelife.dns66.net | A | 183.132.231.152 |
—
|
300 |
默认
|
启用 | 修改 停用 删除 |
*.sharelife.dns66.net | A | 183.132.231.152 |
—
|
300 |
默认
|
启用 | 修改 停用 删除 |
A记录的值先随便填写,符合ip格式就行,动态域名会自动更新
第二条记录*是泛解析,
意思就是如a.sharelife.dns66.net / b.sharelife.dns66.net等等也会解析到这个ip上去
二.路由器设置
登陆路由管理–基本设置–动态域名
==============================================
动态域名 1
IP 地址 Use WAN1 IP Address 183.132.231.152 (推荐)
(如果本路由器是接在另一个路由器下面,则需要选择使用外部 IP 地址 (每十分钟检查))
定时自动刷新 1 天 (0 = 禁用此功能) //默认0也没问题
服务商 WindDns
URL http://www.winddns.cn/
用户名 admin@devsk.com //WindDns上注册的帐号密码
密码 ********
主机名 sharelife.dn66.net //这个域名是你在WindDns上申请的二级域名
通配符
MX
备份 MX
强制下次更新 勾选 //勾选以后,保存设置就会立即更新WindDns上的ip记录
保存后,更新成功应该可以看到如下提示:
最近 IP 地址 2013年12月31日 下午3:52:43:
183.132.231.152
最近更新状况 2013年12月31日 下午3:52:43:
Update successful
==============================================
然后在动态域名2和动态域名1设置一样,主机名填*.sharelife.dns66.net就行了
保存设置,访问域名试试!!
三.绑定其他域名(自己有顶级域名)
1.用CNAME记录
简单的就是在顶级域名的解析记录里面用CNAME记录,把域名指向dns66.net的二级域名
例如:我的devsk.com域名,我增加了这样一条记录.
==================================
记录类型 主机记录(RR) 记录值
CNAME home sharelife.dns66.net
==================================
该记录是把指定域名的ip解析为另外一个域名的ip,以用于只知道域名而不确定ip的情况
因此访问home.devsk.com就和访问sharelife.dns66.net一样了!
2.用NS记录
NS记录,域名解析服务器记录,即把子域名指定某个域名服务器来解析.
例如:
===============================
记录类型 主机记录(RR) 记录值
NS home ns1.winddns.net
===============================
该记录把home.devsk.com的解析交给了ns1.winddns.net解析服务器,
这样,就可以在WindDns的域名管理添加新域名,
WindDns的解析服务器地址有两个,加入一个就行了!
ns1.winddns.net
ns2.winddns.net
2.1注意:
WindDns里面无法添加二级域名,所以添加时填入顶级域名
比如:devsk.com,然后进入域名记录,添加记录.
devsk.com的域名记录
RR | 类型 | 值 | 优先级 | TTL | 线路 | 状态 | 操作 |
---|---|---|---|---|---|---|---|
home.devsk.com | A | 0.0.0.0 |
—
|
300 |
默认
|
启用 | 修改 停用 删除 |
*.home.devsk.com | A | 0.0.0.0 |
—
|
300 |
默认
|
启用 | 修改 停用 删除 |
这样,在路由的动态域名里面,主机名也要相应的修改就行了!
在路由器上架设网站(4):外网访问
偶尔会碰到这样的情况:辛苦忙碌了好久,一切就绪,内网访问正常,但是外网却不能访问.-_-!!
首先在路由器上查看到你当前的外网ip, 系统状态–wan1–ip地址,
然后在浏览器输入该地址,看看能否正常访问(访问该地址的电脑不能是通过该路由器上网的,这样是肯定可以访问的,这涉及到路由的原理,所以建议用手机2g/3g上网测试,才能真实反映外网的访问情况)
如果确定外网不能访问,这种情况大概有两个原因:
1.ISP封了80端口,
这样基本就没办法解决了,有能力就打电话找电信给你开-_-!!
这样你就只能把端口不设为80了,试试8080也行,随便了,这样访问地址就变成了 IP:端口号,很不和谐,不过也没办法
2.路由器的防火墙屏蔽了80端口
执行以下代码再试试外网访问:
iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
如果可以访问了,就把这代码放到路由器的系统管理–脚本设置–防火墙 里面就行了(因为iptables规则重启会失效,要么就保存规则,不过还是加到防火墙比较方便,看个人喜好)
在路由器上架设网站(3):安装Lighttpd&Mysql
在之前的准备工作做好了以后,现在开始在路由器上搭建一个web服务器了!我选择了Lighttpd和Mysql的组合.
1.相关软件安装
安装Lighttpd , fastCGI , Mysql:
Lighttpd 是一个德国人领导的开源Web服务器软件,其根本的目的是提供一个专门针对高性能网站,安全、快速、兼容性好并且灵活的web server环境。具有非常低的内存开销、cpu占用率低、效能好以及丰富的模块等特点。
Lighttpd是众多OpenSource轻量级的web server中较为优秀的一个。支持FastCGI,CGI,Auth,输出压缩(output compress),URL重写,Alias等重要功能.
/opt/bin/ipkg install libstdc++ /opt/bin/ipkg install php php-fcgi /opt/bin/ipkg install lighttpd /opt/bin/ipkg install mysql /opt/bin/ipkg install php-mysql
如果要开启网页的验证码等功能的支持,且网站程序已表明需要GD库支持,则要:
/opt/bin/ipkg install php-gd
如果你还需要开启 curl 还要安装
/opt/bin/ipkg install php-curl
2.设置相关程序自启动
在USB设置里,挂载后运行脚本 栏中输入:
mount -o bind /tmp/mnt/sda4/opt /opt /opt/bin/busybox swapon /tmp/mnt/sda4/swapfile/swapfile /opt/etc/init.d/S80lighttpd start /opt/etc/init.d/S70mysqld start
卸载前运行脚本:
/opt/bin/busybox swapoff /tmp/mnt/sda4/swapfile/swapfile /opt/etc/init.d/S80lighttpd stop /opt/etc/init.d/S70mysqld stop
注意:
1.挂载swapfile的命令按需执行,没有使用swap就不需要挂载卸载swapfile(以上代码中挂载的第2行,卸载的第1行)
2.sda4是我的u盘路径,具体路径需要自己按实际情况修改
安装完成后请重新启动你的路由器(自己重启服务也可以)。
3.软件安装完成后配置相关文件:
(一) 配置mysql
#号为root用户登陆linux后的提示符
1)、启动mysql
#/opt/etc/init.d/S70mysqld start
2)、修改mysql的root密码
#/opt/bin/mysqladmin -u root password 123
(123就是root的密码,根据自己需要自行设置即可)
3)、连接mysql
#/opt/bin/mysql -u root -p
出现提示时输入刚刚修改的密码,输入刚才设置的密码 123
4)、连接上mysql之后,创建数据库,mysql>是登陆mysql后的提示符
mysql> create database test;
5)、查看当前可用数据库
mysql> show databases;
是不是已经有上面创建的test的数据库了!
(二) 配置 lighttpd.conf
安装完成后先停用 Lighttpd 服务
/opt/etc/init.d/S80lighttpd stop
以下操作建议开启文件共享,直接在windows上操作,如果了解linux操作就无所谓了.
1)、备份lighttpd.conf (以免出了差错,可以重新来过)
#cp /opt/etc/lighttpd/lighttpd.conf /opt/etc/lighttpd/lighttpd.conf.bak
如需还原就用cp /opt/etc/lighttpd/lighttpd.conf.bak /opt/etc/lighttpd/lighttpd.conf
2)、修改lighttpd.conf
#vi /opt/etc/lighttpd/lighttpd.conf
如果你对 vi 编辑器操作方法不太熟悉,请先到百度找找。简单的使用方法(进入后按 i 键,就是改成插入方式。修改完成后,按 Esc 键,输入 冒号 再加上 wq 后回车)
3)、需要变更的内容为下面的,其他保持不变.
(1)server.modules中把下面行的”#” 去掉
# “mod_fastcgi” 改为 “mod_fastcgi”
(2)server.port中修改端口,默认为80,可改可不改,自己喜欢。 注意:有的ISP运营商把80端口封了因此使用80端口外网不能访问,而且路由的管理页面端口也是80,需要在路由设置里面修改,我把路由的管理页面设为了8080,请按自己的实际情况设置端口
server.port = 80
(3)修改server.event-handler 去掉# 并改成
server.event-handler = “poll”
(4)fastcgi.server中,把”#”去掉,改为:
fastcgi.server = ( ".php" => ( "localhost" => ( "socket" => "/tmp/php-fcgi.sock", "bin-path" => "/opt/bin/php-fcgi", "bin-environment" => ( "PHP_FCGI_MAX_REQUESTS" => "4000" ) ) ) )
4)、把 /opt/etc/lighttpd/conf.d/10-php-fcgi.conf
改名为 /opt/etc/lighttpd/conf.d/10-php-fcgi.conf.back
修改完毕,启动lighttpd试试。
#/opt/etc/init.d/S80lighttpd start
5)看看程序lighttpd有没有正常运行
#ps
看看是否有此进程,正常的应该就有了
/opt/sbin/lighttpd -f /opt/etc/lighttpd/lighttpd.conf
4.看看效果
浏览器打开192.168.1.1,如果一切正常,那么看到的应该是
lighttpd server is running.
此时可以把你的网页放到optsharewww目录内即可访问!!
在路由器上架设网站(2):安装optware
上一篇文章u盘格式化,已经将环境准备好了,接下来就要在路由器上装一些软件来实现一些更棒的功能,充分挖掘硬件潜能!
optware
安装optware
以下代码均在telnet到路由器后执行!
1、挂载opt分区
(tmp/mnt/sda4是我的u盘路径,具体路径可能不一样,需要自己查看)
在u盘上新建一个opt文件夹: mkdir /tmp/mnt/sda4/opt (如果开启了文件共享,直接在电脑上进入u盘文件系统新建opt目录)
挂载刚才在u盘新建的opt目录到路由器的opt目录: mount -o bind /tmp/mnt/sda4/opt /opt
2、准备安装optware
cd /opt wget http://bbs.dualwan.cn/downloads/optware-install.sh -O - | tr -d 'r' > optware-install.sh sh optware-install.sh
到此OPTware 已经安装好了,以后就可以通过 /opt/bin/ipkg install <软件名> 来安装其他软件了!
3、更新
/opt/bin/ipkg update /opt/bin/ipkg install busybox
4、建立swap分区(交换分区,虚拟内存)
我的共建立了64MB,如果你已经在使用swap分区,此步骤就可以省略了(路由器负载不大也可以不用建立交换分区,毕竟它会增加u盘读写,减少u盘寿命)
mkdir /tmp/mnt/sda1/swapfile dd if=/dev/zero of=/tmp/mnt/sda1/swapfile/swapfile bs=1024 count=65536
操作后,系统返回信息:
65536+0 records in
65536+0 records out
5、挂载swap
好了,swap文件建立完成.开始把swap挂载.
/opt/bin/busybox mkswap /tmp/mnt/sda4/swapfile/swapfile /opt/bin/busybox swapon /tmp/mnt/sda4/swapfile/swapfile
6、补充:ipkg的命令说明
1. ipkg update
下载并更新最新的软件包列表(这个列表的位置在/etc/ipkg.conf指定):
2. ipkg upgrade
更新所有已安装软件
3. ipkg list
在更新之后,我们可以用 ipkg list 这命令查看一下有什么软件包可供安装
4. ipkg install
安装软件包,有 2 种方法,例如我想安装 OpenSSH 的 SFTP 服务器,方便我以后上传文件到 路由器,我可以执行 ipkg list 或到 OpenWrt 的软件包网址取得软件 SFTP 服务器的资料:
之后可以选择第 1 个方法用软件包名来安装,这方法会自动把软件包下载并安装:
4.1. ipkg install openssh-sftp-server
或者选择第 2 个方法从网站把安装包(ipk格式)下载到路由器上,然后输入文件名安装:
4.2. ipkg install openssh-sftp-server_4.0p1-1_mipsel.ipk
5. ipkg list_installed
这个命令会列出 已经为你安装好的软件 (包括一些常用软件和驱动) 以及你后来安装的软件。
6. ipkg remove
当你的空间不足时,这个命令非常有用,先执行 ipkg list_installed 得出己安装的软件列表,然后找出你要删除的软件包名称,例如:
ipkg remove openssh-sftp-server
在路由器上架设网站(1):u盘格式化
在路由器上架设网站,以运行Tomato DualWan的华为hg227路由器为例.
首先要将外接u盘格式化为ext3格式.以运行mysql数据库.
Mysql需要在安装到ext3分区才能正常运行ext2应该也没问题,fat和ntfs格式是不行的,这个问题刚开始也困扰了我很久.-_-!!
如果只是静态网站,不装mysql也可以.
1.以下命令适用于K24内核(Tomato DualWAN 1.23和1.25系列)
1.1查看硬盘都有那些分区可以用下面的命令
fdisk -l /dev/scsi/host0/bus0/target0/lun0/disc
1.2把第一个硬盘分区格式化成ext3的命令
mkfs.ext3 /dev/scsi/host0/bus0/target0/lun0/part1
1.3如果想对硬盘重新进行分区
fdisk /dev/scsi/host0/bus0/target0/lun0/disc
2.以下命令适用于K26内核(Tomato DualWAN 1.28系列)(以该版本作为具体讲解)
1.1查看硬盘都有那些分区可以用下面的命令
fdisk -l /dev/sda
这是我运行的结果:
Disk /dev/sda: 509 MB, 509083648 bytes 255 heads, 63 sectors/track, 61 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/sda4 * 1 62 497120+ 6 FAT16 Partition 4 has different physical/logical endings: phys=(60, 254, 63) logical=(61, 227, 38)
1.2把硬盘分区格式化成ext3的命令
(从上面的运行结果可以看到我只有一个分区/dev/sda4)
mkfs.ext3 /dev/sda4
1.3如果想对硬盘重新进行分区
fdisk /dev/sda
Sda是硬盘名称,可以在路由管理的usb设置里面已连接的设备中看到
例如:
类型 | Host | 厂家 | 产品名称 | 挂载状态 |
Storage | 0 | Generic | STORAGE DEVICE Partition ‘sda4’ ext3 (485.47 MB) is mounted on /tmp/mnt/sda4 |
Yes[ 卸载 ] |
一般来讲第一个插入的u盘会显示为sda,具体路径需要自己按实际情况修改,我这就是sda,
Sda4就表示该分区是该u盘的第四个分区,实际上我的u盘只有一个分区,这也许是BUG也许是我误操作,正常来说他应该是sda1,对于linux的分区命名有兴趣的也可以去查下资料.
ext3格式的分区在windows上不能直接访问,但是在Tomato DualWan中usb应用中可以开启文件共享或者ftp服务器,这样就可以在连接到路由器的电脑上直接访问路由器上的u盘文件.
文件共享可能需要将工作组名称设置的和电脑一样.
ftp服务器拥有更高的权限,但是使用起来不是太方便.
两者可以都开启,按需使用!
让404错误页变公益广告
最近使用了百度加速乐来加速自己的网站,不过自己的主机在香港,而百度分配的节点也在香港,实际测试加速不会太明显,但是至少省下了自己的流量,还有其他一些功能总的来说还是相当不错的!
加速乐里面有个404公益页面,开启以后你的网站404页面就会随机显示为一个丢失的孩子的信息,10秒后跳回主页,个人觉得这个功能相当不错,于是稍微查了下资料,来自定义这个404功能.
1.如果使用加速乐,那么直接在管理页面开启就可以了
2.如果没有使用加速乐,可以手动添加代码.
2.1.使用腾讯的公益广告代码:
<script charset="utf-8" type="text/javascript" src="http://www.qq.com/404/search_children.js" ></script> //宽版代码 <script charset="utf-8" type="text/javascript" src="http://www.qq.com/404/search_children.js?edition=small"></script> //窄版代码
不过腾讯的数据库里面信息比较少.
2.2.使用加速乐的代码(该404公益项目已终止)
加速乐的代码可以显示公益广告时,10秒钟后自动跳回首页.
我只是简单的把加速乐显示的公益广告页面源代码保存到了本地,直接调用.实质是调用了几个js,想修改显示效果可以自己研究一下,把js下载下来全部放到本地来调用就行了.
一般网站的控制面板可以设置错误页,把404页面上传到主机后,设置一下就行了,有的主机管理设置是编辑404页面,而不是指定404路径,这样的话直接把下面的页面源码复制进去就行了.
或者是使用网站根目录下的.htaccess文件定义,在该文件中写入:
ErrorDocument 404 /404.html
=========================================
当然,对于wordpress来说,事情就有点麻烦了,因为wp默认在.htaccess里面把所有页面都转到了index.php,也就是说即使是404错误,也会转到index去处理,而wordpress有个404页面模版,那么修改方法就可以直接修改主题的404页面模版内容,使用js代码或者iframe都可以.要不然就是自己修改.htaccess的重写规则,具体可以百度google之.