Jan 19

血的教训 不指定

felix021 @ 2010-1-19 01:13 [IT » 操作系统] 评论(3) , 引用(0) , 阅读(6406) | Via 本站原创
给Windows 7设置环境变量的时候,在用于分隔各个路径的分号前后,不要为了容易分辨而加上空格,否则你会死的很难看。

这就是经过十五分钟后我才发现的,让我吐血的教训。
Jan 18
今天windy在群里提出一个问题: 为什么下面这段代码输出了why?
$arr = 'windy';
if (isset($arr['why'])) {
  echo 'why';
}

因为已经有结果了,反推过去,很容易就会想到,php把字符串当作数组来用了。再通过
echo $arr['why'];
验证一下,发现输出的是w, 也就是$arr{0}的值,可以大致得出一个结论:当把字符串当作数组使用的时候,会自动把索引转换成整形,然后再当作字符串的偏移量读取返回。

由于此结论仅为猜测,想进一步证实,但是对php代码不熟悉,翻了zend_hash.c等文件都没找到北,因此请教了雪候鸟大人,得知真正的处理代码位于
@ php-5.2.8/Zend/zend_execute.c +1026
static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
这个函数的作用是:将container_ptr所指向的container这个容器中,索引为dim的值取出放在result所指定的内存中去。

具体实现的代码是
1063     switch (Z_TYPE_P(container)) {
1064         zval **retval;
....
1099         case IS_STRING: { //如果这个容器是string
1100                 zval tmp;
1101
1102                 if (dim == NULL) {
1103                     zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
1104                 }
1105
1106                 if (Z_TYPE_P(dim) != IS_LONG) {  //如果偏移量的类型不是LONG
1107                     switch(Z_TYPE_P(dim)) {
1108                         /* case IS_LONG: */  
1109                         case IS_STRING:  
1110                         case IS_DOUBLE:
1111                         case IS_NULL:
1112                         case IS_BOOL:
1113                             /* do nothing */   //允许STRING, DOUBLE, NULL, BOOL四种类型
1114                             break;
1115                         default: //其他类型都报错
1116                             zend_error(E_WARNING, "Illegal offset type");
1117                             break;
1118                     }
1119
1120                     tmp = *dim;
1121                     zval_copy_ctor(&tmp);
1122                     convert_to_long(&tmp);
1123                     dim = &tmp;  //将原来的dim转换成LONG
1124                 }      
1125                 switch (type) {
1126                     case BP_VAR_R:
1127                     case BP_VAR_IS:
1128                     case BP_VAR_UNSET:
1129                         /* do nothing... */
1130                         break;
1131                     default:
1132                         SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
1133                         break;
1134                 }
1135                 if (result) { //存放结果
1136                     container = *container_ptr;
1137                     result->str_offset.str = container;
1138                     PZVAL_LOCK(container);
1139                     result->str_offset.offset = Z_LVAL_P(dim);
1140                     result->var.ptr_ptr = NULL;
1141                     if (type == BP_VAR_R || type == BP_VAR_IS) {
1142                         AI_USE_PTR(result->var);
1143                     }
1144                 }
1145                 return;
1146             }
1147             break;

简单写了一点注释,只能大致看懂逻辑,其他边边角角的,暂时就没时间看了:'(
Jan 18

一段挺好玩的PHP源码 不指定

felix021 @ 2010-1-18 17:20 [IT » 程序设计] 评论(0) , 引用(0) , 阅读(4497) | Via 本站原创
@ php-5.2.8/Zend/zend_builtin_functions.c
1120 #ifdef ZEND_TEST_EXCEPTIONS
1121 ZEND_FUNCTION(crash)
1122 {
1123     char *nowhere=NULL;
1124
1125     memcpy(nowhere, "something", sizeof("something"));
1126 }
1127 #endif
Jan 17
p.s. @ 20100119 这是前几天写的,本来打算给godaddy加一个sockets扩展,但是失败了,还是发出来,记录一下。

godaddy的虚拟主机给的权限真是宽,允许自定义php.ini。
自定义的php.ini默认放在$HOME/html/php.ini,这个是针对php4的,我选择的是php5,所以应该是php5.ini。
//以下在虚拟主机上操作
$ cd ~/html
$ cp /web/conf/php5.ini .
$ vi php5.ini
然后修改max post size之类的参数吧~过一小段时间,再看phpinfo(),就出效果了。


编译php扩展的步骤
$ wget http://museum.php.net/php5/php-5.2.8.tar.bz2 //godaddy上面的是5.2.8, i386
$ tar jxf php-5.2.8.tar.bz2
$ cd php-5.2.8/ext/sockets
$ phpize    //注意,需要安装php5-dev (apt-get install php5-dev)
$ ./configure --with-php-config=/usr/bin/php-config  (最好$ whereis php-config 看一下路径)
$ make

拷贝到godday去
$ scp modules/sockets.so yourname@yourdomain:~/
然后修改php5.ini,增加
extension=sockets.so
发现无法正常加载,失望=。=
Jan 15
从标题就可以看出来,这篇的内容是大杂烩,主要是这几天玩的东西,一并说一下

总共5个东西

1. 交换分区
第三篇说的重新分区太危险了,万一SmartQ升级固件的程序不认,那就挂了。所以决定把那128MB拿来做交换分区。具体做法如下

建立一个100MB的文件
# dd if=/dev/zero of=/media/ndda2/swapfile bs=1MB count=100

格式化成swap所需的格式
#  mkswap /media/ndda2/swapfile

# swapon /media/ndda2/swapfile

如果不需要了,可以这样
# swapoff /media/ndda2/swapfile

可以把这个写入rc.local.


2. 键位映射
其实主要是xmodmap和xev这2个东西

先讲xev吧:
$ xev | grep keycode
然后按现有的几个键,可以看到,屏幕左边的三个分别是(112)Prior, (117)Next, (64)Alt,上面的三个(从左到右)分别是(124)XF86PowerOff(关机), (9)Esc, (36)Return(回车)。所以实际上可以用ALT+ESC来切换程序。

$ xmodmap -pke
可以看到现在的keycode被映射成什么东西

$ xmodmap -e 'keycode 112 = Up'
$ xmodmap -e 'keycode 117 = Down'
这样就可以把那两个按键变成上下,而不是翻页了。

$ xmodmap -e 'keycode 112 = Prior'
$ xmodmap -e 'keycode 117 = Next'
这样还原。


3. 快捷键
主要是修改 /home/user/.config/openbox/lxde-rc.xml
找到Keybinding这一节,按照格式修改即可。

比如默认的A-XF86PowerOff(Alt+Power组合键)是运行ts_calibrate,就是校正屏幕的,但是其实这个基本用不到,所以可以改成其他的,比如改成vlc,或者fbreader;默认的XF86PowerOff是打开那个系统设置(coman)程序,很容易被误按,我也改掉了。这样就多了2个可以自定义的快捷键,很爽。有兴趣的话还可以研究一下怎么增加其他组合按键,比如Alt+Enter :)
p.s. 需要运行一次首选项->窗口设置 才可以生效。


4. 虚拟键盘
系统自带的虚拟键盘是matchbox-keyboard, Nokia的N770什么的也在用。键盘的布局文件是存放在/usr/share/matchbox-keyboard这个目录下的,标准键盘用的就是keyboard.xml这个文件了。可以修改这个文件来实现自己想要的键位布局。昨天整了一个接近标准PC键盘的键位布局,效果见图:
下载文件 (已下载 1495 次)

点击在新窗口中浏览此图片
点击在新窗口中浏览此图片



5. 一个脚本,我存放在/usr/bin/run_app,然后XF86PowerOff映射为运行这个脚本,效果就是,按一下启动vlc,再按一下结束vlc。
#!/bin/bash
dir=$HOME/tmp
tmp=$dir/run_app.pid

if [ ! -d $dir ]; then
    mkdir -p $dir
fi

if [ -f $tmp ]; then
    kill `cat $tmp`
    rm $tmp -rf
else
    setsid vlc &
    echo $! > $tmp
fi
Jan 11

收藏: PHP的hash函数 不指定

felix021 @ 2010-1-11 17:31 [IT » 程序设计] 评论(0) , 引用(0) , 阅读(4809) | 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开刀。
分页: 2/3 第一页 上页 1 2 3 下页 最后页 [ 显示模式: 摘要 | 列表 ]