Jan 11

收藏: PHP的hash函数 不指定

felix021 @ 2010-1-11 17:31 [IT » 程序设计] 评论(0) , 引用(0) , 阅读(5014) | Via 本站原创
更多内容,参见laruence大牛的这篇: http://www.laruence.com/2009/07/23/994.html

这么短一段代码,有这么多考究的地方,很值得学习:
1. 5381
2. hash << 5 + hash  --> hash * 33 (times 33算法)
3. -= 8
4. switch, break
...

static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength)
{
    register ulong hash = 5381;

    /* variant with the hash unrolled eight times */
    for (; nKeyLength >= 8; nKeyLength -= 8) {
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
    }
    switch (nKeyLength) {
        case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 1: hash = ((hash << 5) + hash) + *arKey++; break;
        case 0: break;
EMPTY_SWITCH_DEFAULT_CASE()
    }
    return hash;
}
Jan 10
第二篇把所有分区的大小都列出来了,不过还是漏了一点:
所有分区加起来,总共是1795,但是2G,用硬件厂商的单位换算,就是2,000,000,000B = 1907.35MB,而fdisk显示的是1883 MB,至少还应该有88MB的空间。

fdisk -l /dev/ndda没有看到另外的分区,根据block的数量来算,也没有找到这么大的地方,看起来应该是被隐藏了。不过还是可以大概估计出来这这88MB的用处——那就是用于WinCE的固件。当然,也可能是用于Android的固件,但是2个都用上空间不够大。而且WinCE的那个分区只用了2M多,说明固件肯定另外存了一份;而ndda4下面的4个逻辑分区都是Linux分区,所以肯定不会存在这里。综合一下,我觉得这88MB就是用来刷WinCE的固件了,而Andoid的,都放在ndda4里头。

由于我对Andoid没什么兴趣,决定把那467的空间搞出来。

注意:以下操作具有危险性,不熟悉Linux的同学,最好小心点儿,出了问题我可不负责,嗯。

具体的操作为:
1. 删除ndda4原有的分区
2. 建立一个新的分区
3. 格式化
4. 其他

第一步,用fdisk。说实话这是我第一次用linux下的fdisk=。= 不过还是挺简单的,如果有一些主分区、扩展分区、逻辑分区的知识的话。
V7里头这个Ubuntu它貌似是不支持卡上的逻辑分区的,ls /dev没能看到ndda5~ndda8就说明了问题。
所以应该把45678都给删掉,然后重新建立ndda4
具体操作:

root@SmartQ:/media# fdisk /dev/ndda

The number of cylinders for this disk is set to 57472.
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看看有哪些命令,输入d是删除分区:

Command (m for help): d
Partition number (1-8): 8

Command (m for help): d
Partition number (1-7): 7

Command (m for help): d
Partition number (1-6): 6

Command (m for help): d
Partition number (1-5): 5

Command (m for help): d
Partition number (1-4): 4

至此不需要的分区全都删掉了。然后看看现在的分区,命令是p,显示大致是这样的:


Disk /dev/ndda: 1883 MB, 1883242496 bytes
1 heads, 64 sectors/track, 57472 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Disk identifier: 0x3079ae40

    Device Boot      Start         End      Blocks   Id  System
/dev/ndda1              33       35232     1126400    b  W95 FAT32
Partition 1 does not end on cylinder boundary.
/dev/ndda2           35233       39328      131072    6  FAT16
Partition 2 does not end on cylinder boundary.
/dev/ndda3           39329       42528      102400    6  FAT16
Partition 3 does not end on cylinder boundary.

注意这个42528,是分区3的末尾,我们接下来需要创建一个分区4,从42529开始,命令是n
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p   #需要创建一个主分区,输入,这里输入p

Selected partition 4
First cylinder (2-57472, default 2): 42529   #这里输入开始
Last cylinder, +cylinders or +size{K,M,G} (42529-57472, default 57472):   #直接回车,默认是到末尾
Using default value 57472

Command (m for help): p #再看一下,已经创建好了。

Disk /dev/ndda: 1883 MB, 1883242496 bytes
1 heads, 64 sectors/track, 57472 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Disk identifier: 0x3079ae40

    Device Boot      Start         End      Blocks   Id  System
/dev/ndda1              33       35232     1126400    b  W95 FAT32
Partition 1 does not end on cylinder boundary.
/dev/ndda2           35233       39328      131072    6  FAT16
Partition 2 does not end on cylinder boundary.
/dev/ndda3           39329       42528      102400    6  FAT16
Partition 3 does not end on cylinder boundary.
/dev/ndda4           42529       57472      478208   83  Linux
Partition 4 does not end on cylinder boundary.

#接下来这里一定要慎重!!如果不确定,可以输入q退出,前面所有的都不算数
Command (m for help): w  #存盘
完了以后
#sync
#init 6 #重启命令

等到重启好了,格式化,挂载:
# mkfs.ext3 /dev/ndda4
# mkdir /media/ndda4
# mount -t ext3 /dev/ndda4 /media/ndda4

如果不想每次启动都这么弄,可以加入fstab
# vi /etc/fstab
增加一行
/dev/ndda4     /media/ndda4    ext3    defaults        0       0
:wq存盘退出,然后
# mount -a
在/media/ndda4下面就可以访问这个分区了。

到这里,手头的V7就多了一个可用的467MB的分区,爽!经过测试,Android已经不能启动了,而CE仍然没有问题 :)

-------------华丽的分割线--------------

接下来再做一些小改造:

1. 把ndda4挂载到/home分区,而不是只有128MB的ndda2
2. 把ndda2格式化成fat32,给WinCE用(后来发现一个问题,不建议这么整,详情见后文)

具体操作:

# mkdir /media/ndda2
# vi /home/fstab
原先home那一行和ndda4的那一行注释掉(就是前面加一个#就可以了),然后加上这两行:
/dev/ndda4      /home           ext3    noatime         0       2
/dev/ndda2      /media/ndda2    vfat    defaults        0       0
:wq存盘退出

然后
# cp -r /home/user /media/ndda4
# sync
# init 6  (重启命令)
重启以后,挂载在/home的就是/dev/ndda4了,空间大多了吧 哇哈哈

然后
# apt-get install dosfstools
安装好以后就有mkfs.vfat和mkfs.msdos了。

# mkfs.vfat /dev/ndda2
格式化成fat32文件系统

# mount -a
这样就挂上去了。

重启到WinCE下面,你会发现,怎么什么设置都没有了,先校准一下屏幕,打开“我的设备”,会发现一个新的NAND分区,里面是原先CE下的设置和文件。也就是说,WinCE在引导的时候,会在找到的第一个可用分区建立自己的目录结构,把那里当作自己的家。。。所以如果你不想把WinCE重新设置一边的话,建议还是不要这么搞了。此外,这样做可能还有一个问题:如果重新刷Ubuntu,可能会导致ndda2被重新格式化成linux分区,然后WinCE就会在NAND(也就是ndda3)上面再搞他自己的帝国了。

同时这也给我们一个启示:要将WinCE恢复原状,根本不需要重新刷机,只要在Ubuntu下挂载ndda3分区,把它全部清空,然后重启进入WinCE,就是全新的了。

OVER。

第四篇预告:重新划分所有分区。这个还真的有点危险了,我要仔细考虑一下是否有需要这么做。其实我是想把UBuntu的根分区扩容。
Jan 10
(这篇文章已经在bbs.zhiqi.com.cn发出去了,在这里润色一下再贴出来)

前面已经把openssh-server搞定了,接下来看看里头的东西。智器官方的介绍说的是2G的空间,其中用户可用128MB,听起来太少了。那其他的空间都哪里去了呢,看看先。

#df -lh 可以看到
引用

Filesystem Size Used Avail Use% Mounted on
/dev/ndda1 1.1G 579M 450M 57% / #这个是Ubuntu的根分区,用了579M,还有450M可用
/dev/ndda2 124M 13M 106M 11% /home #这个是用户分区,124(其实是128M,其中4M文件系统用了吧)
/dev/ndda3 99M 2.1M 97M 3% /media/tmp/ndda3 #这个是我自己挂载的,里面有Windows等内容,可以判断出来是WinCE的分区
/dev/mmcblk1p1 3.8G 2.7G 1.2G 71%
/media/MY FLASH DI #这个是SD卡 /dev/sda4 3.8G 2.5G 1.4G 66%
/media/WIN7 #这个是额外插上去的U盘,之所以识别成4,我想是因为前面已经有了123。

另外, # ls /dev 可以看到有个ndda,再 #fdisk -l /dev/ndda,可以看到
引用
root@SmartQ:/media/tmp# fdisk -l /dev/ndda Disk
/dev/ndda: 1883 MB, 1883242496 bytes
1 heads, 64 sectors/track, 57472 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Disk identifier: 0x3079ae40
Device Boot Start End Blocks Id System
/dev/ndda1 33 35232 1126400 b W95 FAT32 (Ubuntu /)
Partition 1 does not end on cylinder boundary.
/dev/ndda2 35233 39328 131072 6 FAT16 (Ubuntu /home)
Partition 2 does not end on cylinder boundary.
/dev/ndda3 39329 42528 102400 6 FAT16 (WinCE)
Partition 3 does not end on cylinder boundary.
/dev/ndda4 42529 57472 478208 5 Extended (扩展分区,肯定是Andoid的了)
Partition 4 does not end on cylinder boundary.
/dev/ndda5 42530 46436 125024 83 Linux
/dev/ndda6 46438 51321 156288 83 Linux
/dev/ndda7 51323 53154 58624 83 Linux
/dev/ndda8 53156 57472 138144 83 Linux

每个Block的大小是1024B,也就是1K,换算过来,从1~8共8个分区的大小是(MB)
1126400/1024=1100
131072/1024=128
102400/1024=100
478208/1024=467
125024/1024=122
156288/1024=152
58624/1024=57.25
138144/1024=134.91
其中第四个是扩展分区,其实就是后面四个逻辑分区的"合体",
很明显可以看出来各个分区的作用,已经标注在上面的引用里面了。

结论:
1. 第一个分区是Ubuntu的根分区,有450MB可用空间,多安一点软件其实没问题
2. 第二个分区是Ubuntu的/home分区,其实就是桌面上的我的文档,可用空间124MB,这就是官方宣称的128MB可用空间了
3. 第三个分区是Windows分区,有97MB的可用空间
4. 第四个分区的Andoid的,有467MB, 鉴于我觉得那个Andoid很鸡肋,完全可以拿来玩。
5. 综上所述,各个系统之间的可用空间是独立的。

下一步,准备拿/dev/ndda4开刀。
Jan 10
因为在那个触摸屏上打字太痛苦了,于是决定安装一个openssh-server。
查看了一下/etc/apt/sources.list,内容只有一行
引用
deb http://ports.ubuntu.com/ karmic main universe restricted multiverse
原来是karmic,9.10了哇,真是与时俱进。直接用的官方源。
# sudo passwd root 随便给root设置一个简单的password
# su - 切换用户为root
#apt-get update 发现住处那个ooxx的长城宽带,连上去的速度大约是100B/s以内。很爽。

# apt-get update 带到公司再来,这已经是今天了=。=
# apt-get install openssh-server
openssh-server 已经是最新的版本了。
共升级了 0 个软件包,新安装了 0 个软件包, 要卸载 0 个软件包,有 80 个软件未被升级。

&*@$ 居然已经安装了,抑郁。
# /etc/init.d/ssh start
* Starting OpenBSD Secure Shell server sshd               [ OK ]

然后在台式机上打开SecureCRT连上去,用户名密码就用root的那个,然后看到这个提示符,表示登录成功啦
root@SmartQ:~#

于是就不用忍受终端下用触摸屏打字的痛苦了..

p.s. 顺便安装了一些东西:gcc g++ build-essential vim ctags cscope,然后写了个hello smartq,没问题,嗯。以后应该会有用的,哇哈哈。另外,发现机器上已经有perl和python了,真是好东西哇好东西。
再p.s. apt安装的时候会先下载安装包,会放在/etc/cache/apt/archieves,如果确定不会删了再装,可以把它们都删掉 #apt-get clean,或者可以备份到卡上,免得下次下载很痛苦。


update 1 @ 2010-01-17

1. 更新源用国内的这个,速度很快
deb http://ubuntu.srt.cn/ubuntu-ports/ karmic main restricted universe multiverse

2. 安装个lrzsz,然后用SecureCRT连上去以后就很方便了
# sudo apt-get install lrzsz
# sz 文件名
可以下载到电脑上
# rz -e 回车
在电脑上选择文件,传输上去
Jan 10

入手智器SmartQ V7 不指定

felix021 @ 2010-1-10 14:31 [IT » 硬件] 评论(4) , 引用(0) , 阅读(7647) | Via 本站原创
昨天到中关村去,鼎好A2574试用了3个小时的SmartQ V7,然后终于决定买下来,一个V7,一个布袋,送一个烂耳机,一共1530。其间还有些纠结,反正没有买到可用的USB网卡,也没有买到想买的USB充电线,小抑郁。回来后在当当上买了一个KingMax的SDHC, 16GB, class6, 230。也就是总共花了接近1800。

折腾了很久,Ubuntu很慢,除去这个问题的话 用起来还算比较happy,此外就是屏幕不够大,那个键盘就占了好大的空间,很囧。之后试着看能不能把它转过来。WinCE软件不少,折腾起来阻力,而且全是玩软件,太无聊了。Android一点都不好玩。

后面慢慢贴一些“研究成果”出来grin
Jan 7

apache, mod_cgi 不指定

felix021 @ 2010-1-7 20:40 [IT » 网络] 评论(1) , 引用(0) , 阅读(6949) | Via 本站原创
编译apache的时候默认应该是有mod_cgi的,如果不确定,可以加上--enable_cgi。

在httpd.conf里面增加(或修改,因为可能已经有这个东西了):
引用
ScriptAlias /cgi-bin/ /某路径/cgi-bin/
如果你修改了“某路径”,那么后面对应的Directory一节也应该对应修改
引用
<Directory "/某路径/cgi-bin">                                                  
    AllowOverride None
    Options FollowSymLinks #如果不放心,这里还可以加上一个ExecCgi选项。
    Order allow,deny
    Allow from all
</Directory>

下面是一个简单的C编写的cgi程序,gcc -o printall simple_cgi.c,把printall放在cgi-bin目录下面。然后访问:http://localhost/cgi-bin/printall,可以看到输出。特别注意一下,cgi不仅要打HTTP实体,还要打HTTP头信息。如果你实在懒得写,在实体前面加上一个回车就行了:) 否则你会看到apache的error_log里输出诸如"malformed header from script. Bad header="这样的错误信息。
#include <stdio.h>
#include <stdlib.h>

extern char ** environ;

int main ()
{
    int i;
    puts("Content-Type: text/plain\n\n");
    for (i = 0; environ[i] != NULL; i++) {
        printf ("%s\n", environ[i]);
    }

    if (strncmp("POST", getenv("REQUEST_METHOD"), 4) == 0) {
        char buf[1025];
        while (1) {
            fgets(buf, 1024, stdin);
            printf( "%s", buf);
            if (feof(stdin)) {
                break;
            }
        }
    }
    return 0;
}

特别点出一下,GET请求的query_string是在environ["QUERY_STRING"]里面,而POST请求的输入,是从stdin中读取。
Jan 4
在发现有atoi这个函数之后的一段时间里(converts a string to an integer, cppreference.com),每当我需要把integer转换成字符串的时候,我就会想当然地写上itoa,直到编译器告诉我,这个函数不存在。反复几次以后,我终于记住了没有itoa,记住了应该用sprintf(现在想想,是应该用snprintf才对)。直到今天我才意识到自己从来就没有仔细想过,为什么有atoi,却没有itoa。也许还是自己求知欲太低了。

原因其实很简单,简单地说,就是因为不好处理返回值。atoi, atof, atol等函数之所以可以在C标准库中存在,可以列出来的有两个必要条件:一,需求使然;二,返回值类型是基本类型,可以使用匿名变量传递。itoa之所以不在C标准库中,我觉得并不是没有需求,而是因为返回值是字符串,也就是char数组,处理起来比较纠结。

在C里面,字符串始终是个硬伤。如果非要设计这么一个函数,有三种可选的办法:

一,使用一个static的char数组(貌似printf就是这么做的吧)。这有2个问题,1是数组的长度是固定的(当然,简单处理的话可以认为int最多就那么几位,只要初始化某个足够的长度肯定就OK),2是每次调用会覆盖上次的结果,特别地,会导致非线程安全。

二,每次调用,在函数内部malloc一段空间,写入,返回该空间的首地址。存在问题是,分配的空间函数内无法自行释放,需要调用者安排一个free,而这个free是非常容易被忽略的,这就存在了潜在的内存泄漏风险。

三,要求传入一个分配好空间的指针,函数将转换结果写入。这样实际上就是sprintf的做法,重复造轮子。而且还要考虑内存越界访问的问题,再增加一个参数n,然后这就是snprintf做的事情....

综合起来的结果就是:太麻烦了,不实现。

最后,推荐云风的一篇文章,这里探讨了与以上内容比较相关的”一个 C 接口设计的问题“
http://blog.codingnow.com/2009/01/c_interface.html
Dec 29
注: 以下内容稍有处理,隐去一些不适合放上来的内容。

felix021 10:14:18
我昨天跟同学(即sandy)有讨论了一下,他说,我举的例子属于“非本质性复杂”,就是说,是语言层面可以解决的,通过取舍,或者修正历史遗留问题解决,但是框架方面的,比如机制和策略的分离,这个属于本质性的复杂,不是语言层面可以解决的

zja 10:34:01
我觉得做出这个选择的最重要标准是系统的规模。
这句说的挺本质,
写的不错,
另外多发现一些现有框架的优点,
尽可能多的找出设计的的矛盾对立面
比如开放性,封闭性
开放性:当有新的需求到来的时候,能不能快速适应
封闭性:框架严格戒定了我能做什么,我不能做的开发都自行实现
两都又各有优缺点:开放的框架适应性强,封闭的框架清楚,明了,稳定

felix021 10:43:07
嗯 我们的框架非常强大 这个是肯定的

zja 10:43:15
实际类似这样的矛盾对立面尽可能多的了解到的话,
设计上就会提高了,想的面多了,
不存在怎么样做是最完美的,
只能说针对现有的情况,且实很好的解决了问题

felix021 10:43:22
只是我在使用过程中遇到一些困扰

felix021 10:43:39
这种感觉很像是我在用 C++的时候的那种感觉

felix021 10:44:17
仔细想想其实这是不可调和的矛盾,但是还是觉得有些别扭

zja 10:45:42
玩程序就像练武,
一开始不要总武当不好,少林不好,xx也不好,
不如深入的喜欢一门,比如武当,
当你对这一门武艺精通到一定程度,(内功)
那么这时候才是你该跳出来的时候,
其它武功哪地方好,应该熔合进来,
往往这时候,跳出来是最难的了。


felix021 10:46:03
这个比喻好~~受教

zja 10:47:16
如果没有专一的对一门武艺的深入研究,连架子都拉的不对,
内功就更不用提了,
那么根本没有理解道这门武艺一剑封喉的点,
框架有时候也可以这么理解,
分久必合,合久必分,

felix021 10:48:38
嗯~我内功还欠缺的很,这些是这实习几个月的感受。
以前对框架性的东西接触的少,呵呵。

zja 10:48:48
当你使一个框架的时候,总会觉得其它方式更好,
因为他的优点总是被乎略,缺点总是很容易被看到,
草总是远处的绿,
因此要更深入的去理解它的时候,
你要看穿这些东西,
比如这个大框架,比如...框架,我们都很容易发现它的缺点,
但我觉得多去发现它的优点,本质的东西掌握了一定层面,
可能再去想想它的缺点(跳出来)会更有意义,

felix021 10:51:39
嗯 学习这框架之后的确是感受到他们的强大 也是用了一段时间以后才发现有一些不合意的地方

zja 10:52:22
这东西就是一个往返的过程,
这说明进步了,
但我觉得可能还不够,可能过段时候你会又感觉到它的好,
再过段时候你又会感觉到他的不好,
就是多层面多角度的去看问题,
当然,这要你我们慢慢积累的经验,
往往许多东西走到一定层面,就出会现回归,
比如某server的接口拆分,
现在看起来当初合的有很多道理了,
但当初想拆的时候,同样有N多理由需要拆,
这就是一组矛盾,要辨证的去看,
我觉得没有绝对的错,也没有绝对的对,
看应用,看需求,看规模,

felix021 10:56:56
嗯。需求的变化,规模的增长,带来太多不确定性,不是可控的,只能在变化中学习,不断摸索不变的东西积累起来,最后才能以不变应万变。

zja 10:58:36
是的,
康神的一句话,现在记得很清楚,
基本原则不能违背,
基本原则遵守的好的,敌人再绕,总在我们手掌心,
但基本原则打破了,我们发现一个露洞修一个,发现一个修一个,总也修不完,

felix021 10:59:40
嗯 我该再好好回顾设计模式相关的内容 现在再去看 应该会有更深的体会

zja 11:00:14
多关注矛盾很有意义,
比如大小表问题,
比如分表与不分表问题,
比如缓存与一致性问题,等等,
看现有的如何很好的解决的,
这时候你才会想,我遇到这样的矛盾很纠结的时候,这是不是一个很好的参考点,

felix021 11:01:07
嗯 这样的矛盾是本质上的复杂性,如果能想清楚,就能在实际的设计、开发过程中做出最好的权衡

zja 11:01:37
是的,
其实再多想一步,
编程是这样,工作,生活也是这样,

felix021 11:03:29
嗯 我一直觉得程序和生活之间还是有很多相通的地方的
~多谢jiuan了,以上所说的内容我会再好好想想 :)
分页: 39/103 第一页 上页 34 35 36 37 38 39 40 41 42 43 下页 最后页 [ 显示模式: 摘要 | 列表 ]