博文

目前显示的是 十二月, 2009的博文

买了一个ndsi

今天买了一个NDSi LL。同事领我去中关村他朋友的店里买的,算下来比电玩巴士的要便宜200。比较不爽的是这个卡不支持即时存档,大大的丧失了掌机的便携性。发现一个不错的下载站:http://www.romulation.net/downloads/ 。NDS上每款已发行的正版游戏都有一个编号,我一般是先在duowan或者电玩巴士找到游戏的编号,然后来这里下载。比较可惜的是,他只有原始版本,没有汉化版。电玩巴士的ftp很慢而且老断,xunlei我又不喜欢,无奈。买回来之后一直在玩恶魔城苍月,可是越玩越累。然后就换换口味玩会儿太鼓达人。太鼓达人那个气氛啊,真是很high。

央视要进军网游界了

图片
最近整天报道网络游戏是怎么毒害青少年,网瘾成灾,广电总局出面点名批评那些低俗网游,最终忍无可忍,决定自己出手,自己招网游开发人员,自己研发自己运营。有图为证:http://www.cntv.cn/cntv/01/09/index.shtml

2009-12-27

图片
都说现如今的记者很无良。我有个学长,大我一届,叫徐新事。去年入案被捕,这个月刚宣判。http://tech.sina.com.cn/i/2009-12-21/13493695995.shtml,因敲诈罪获刑一年半。涉案之前,他虽然年纪轻轻刚来北京,却已经是这个圈内名声响当当的人物,真是让人唏嘘不已啊。其实不仅记者的嘴容易被收买,杀毒软件也是。如果你愿意把灰鸽子的代码拿来重新编译一遍然后加上你的数字签名并且给各家公司塞够钱,那你就可以堂而皇之的把它安装到各个电脑中。比如之前诺顿对winxp中文版的“误杀”,真的是误杀吗?再说我今天遇到的一个很奇怪的事情。因为很多QQ上的网友在组团聊语音,于是我就去下载YY。他们都用YY,尽管很多人根本从来不玩游戏。我第一次是用shareaza下载,刚下载完norton就报告说有病毒。第二次是用IE下载,非常正常。我把上面的操作重复了N遍,依然如此。用shareaza就说有病毒,用IE就没事。那好吧,就换一个谁都了解谁都放心的下载工具:wget。结果依然是报告有病毒。然后我继续做实验,创建了一个文件夹,并把它放在norton的监控例外中。然后等下载完成后,计算md5并和用IE下载下来的做比较。结果发现md5一致。然后,我把它从这个文件夹复制到别的文件夹,也正常。你可以重复这个实验:wget'http://yydl.duowan.com/2.0/setup/yy-2.1.2.exe'在下载进行到900K以后,按Ctrl+c终止,然后诺顿就会弹框。我的诺顿是NIS2010(正版)。你准备如何解释这个现象?

脚本语言有什么好?

除了不用编译就能执行之外,脚本语言有什么好?我今天在看groovy,就和N年之前看python一样,最终除了会写个hello world,还是什么都不会。用C++/java写底层引擎,用脚本语言实现逻辑。貌似这是非常被推荐的模式,可是我就是看不出,脚本语言在开发速度上有什么优势?尤其是面对eclipse这么强大的IDE,就算少写了几十个字符的代码,但是这要求写的时候非常细心的明白这个对象是什么类型、这个加法会不会溢出等等。

极端搞笑的调试方式

调试kernel是一件很费劲的事情。
我找到了三种方法:
1、用hlt指令。
loop: hlt
jmp loop
一但执行到这样的代码,vmware就会告诉说CPU已经被挂起。(真实环境中现象就 是死机)
通过这样的方式一点点的找到出错的代码
2、用0xB8000这块内存
0xB8000是BIOS保留的,指向屏幕。反正往这里写什么字符进去,屏幕上就能显示 什么。
于是我在我的代码中就插了很多这样的莫名其妙的代码 (VIDEO=0xB8000)
movb TMPL__XXXX_BODY_XXXX#39;c',VIDEO
movb $7,VIDEO+1
3、用gdb
只需要在vmx文件中加这么两行:
debugStub.listen.guest64 = "TRUE"
debugStub.listen.guest64.remote = "TRUE"
在vmware里运行的东西都可以拿gdb去调试。不过呢,要区分是32位还是64位的。 比如我在这里说我的guest os是64位的,但是当它真正进入64位模式之前,我用 gdb是连不上的。操作系统启动的时候,是从16位-〉32位—〉64位这样一步步走来 的。我希望在它开始执行64位代码的地方加个断点。于是我就放了个int 3在那 里。可是不管用。可能是因为之前我已经禁用中断了,idt还没设置,所以还不能 启用中断。一遇到int3,机器立马重启了。
于是我想,在main函数的开始执行个sleep(100000)也好啊。可是我压根不知道怎 么初始化rtc,更不要说实现这么复杂的函数了。
然后,我想了个很搞笑的下断点的方式。voidkmain(uint64_t magic,struct grub_multiboot_info* info){ for(int i=0;i<10000000 ;++i){ for(int j=0;j<100000000;++j){ if(j<0) goto begin; __asm ("nop"); } } begin: //.... } 果然,它停下来了。
那个if(j<0) goto begin也是个很搞笑的东西。
我本来是这么写的volat…

page size = 1G

今天看Freebsd的pmap的代码时候,发现原来某些AMD CPU支持1G的page size。你说,这该多爽啊!对于应用程序,几乎不会有用user space的TLB不命中。有没有人试过?

2009-12-11

我总是奇怪为什么我装完grub2后总是进入rescue模式。但是顺序的执行那些引导指令,都挺正常的,能启动。今天终于找到原因了。当时装的时候脚本出了点问题,我就把/usr/local/lib/grub/grub-mkconfig_lib里的make_system_path_relative_to_its_root函数改了,无论path是什么,它所在的filesystem的root directory都设置成”/”。而这个函数是用来计算prefix的,prefix变量的值是要被写入到core.img中的。我也是很偶尔的发现rescue模式下某些命令不能被正确执行是因为prefix变量不对,才想起这个的。唉,罪过啊罪过。我当时怎么这么干的啊!顺便,今天,我的U盘终于修好了。我把它装上grub2,终于在实际真实的环境中跑了一下我的os,哈哈!顺便,我发现格U盘的时候它默认采用的也是gpt格式。但是freebsd的gpart工具的add命令仿佛不能指定任意type,导致我没有办法添加类型为grub boot的分区,所以还是用mbr模式了。但是默认的分区方式在mbr后面只留了63个扇区的位置来装core.img。而我随便加点啥模块,就超过31K了。只好把它格了,重新挪了挪。

2009-12-10

真是不看不知道,一看吓一跳.没有想到多核CPU在实现加锁操作的时候会这么复杂.我最近遇到的一个BUG可能与membar有关。今天下了些paper正在看。

对于常量的优化

假如我在头文件中定义#define PAGE_SIZE 4096然后在cpp里写 int p=addr & (PAGE_SIZE-1) 。我想编译器肯定能把4096-1这个优化掉,它不会真的在运行的时候计算4096-1=4095这个值。可是假如我采用另一种方式去定义:在头文件中写extern const int PAGE_SIZE;。然后在某个.o中将它赋值给4096。我猜编译器是没有办法把那个减法给优化掉的。因为这个只有到最后一步链接的时候才能得知这个常量的值,更有甚者,这个常量有可能是通过dll动态载入进来的。而如果换成static const int PAGE_SIZE=4096。那么这个在编译的时候就能被优化掉。我特地用gcc -O2看了下确实是如此。假如在一个公用的头文件中用static const int xxxx=xxxx;的方式定义常量,链接后的大小真的会比#define的方式增大很多吗?

2009-12-06

奇怪了,内存哪里设置的有错?我在cr4里面设置了PSE选项,那么应该是2M的页面大小/\*\* 启用PAE \*/ movl %cr4,%eax \# Get CR4 orl $(CR4\_PAE | CR4\_PSE), %eax movl %eax,%cr4cr3里面的东西是这么设置的:#define PG_V 0x001 #define PG_RW 0x002 #define PG_U 0x004 #define PG_PS 0x080 //最后一级页表项这里必须设置 .align4096 // the others may not be needed, but this one MUST BE THERE .globl pml4_base // PML4 pml4_base: //都指向PT3的第一项 .rept (512) .quad (PT3 + PG_V + PG_RW + PG_U) .endr.globl PT3 PT3: //都指向PT2的第一项 .rept (512) .quad (PT2 + PG_V + PG_RW + PG_U) .endrPT2: //一个页面2M,512个就是1G i=0.rept (512) .quad (i<<21) + PG_V + PG_RW + PG_PS + PG_U i=i+1.endr理论上来讲,我将1G的内存映射满了整个64位地址空间(因高16位产生的空洞除外)。之后我在ia32-e long mode下从0x100000开始写操作,写到0x102fff的时候,我的机器就重启了。纳闷了很久我才想起来,kernel就是从物理地址的0x100000开始映射的,然后我用objdump/nm看了下,PML4就是从0x102000开始的。我猜是因为TLB有缓存,所以它在写完第一个4K页,开始写PT3的时候,才被CPU报错重启。freebsd下,elf64_exec这个函数通过bootinfo64.…

2009-12-05

今天把昨天抄来的代码改了改,精简了下,确保每行代码我都明白什么意思.下午3点出去打台球了.路上走了一个小时.然后玩了一个小时.然后中学同学喊我去吃饭,然后吃啊,八卦啊,最后去蒙着脸进豆瓣书店买了几本书回来.在进入ia32-e模式之前必须先设置PML4,我抄来的代码是用4K的页表。我想明天把它改成2M的,于是就只有3级页表结构了,好处理一些。我是这么想的,假如我有4G的内存,如果采用4K的页面大小,那么就是1M个页面,每个PTE是4字节,那么整个页表结构加起来大约需要4M内存。如果换用2M的页面,就是2K个页面,只需要8K内存。而现在服务器配备30G以上内存很常见,为什么不修改页面大小呢?

2009-12-04

最近在看grub2的代码,于是就想自己写一个很微型的kernel玩玩。于是就去读multiboot规范。可是它的最近的文档是5年前写的,而multiboot2仅仅是草稿。grub2的multiboot loader在启动的时候,也是优先查找第一版的magic number。multiboot 只是把kernel载入进内存,即便kernel是elf64,此时的机器状态也是在32位的保护模式下,并且没有开PG。之后需要漫长的过程,打开PAE、设置MSR、把cr3指向PML4、开启PG等等。我从网上抄了些代码总算是能运行了,摆脱汇编进入C语言的main函数。并且写了个hello world。这应该是我写过的最难写的hello world了。哭。在将要睡的时候,终于找到了freebsd的这段实现:/usr/src/sys/amd64/amd64/mpboot.S 依然是一如既往的精巧。明天再读吧!

关于freebsd刚刚被发现的rtld的BUG

貌似最早是在这里被公布的:http://seclists.org/fulldisclosure/2009/Nov/371问题是这样:如果一个具有setuid属性的可执行程序具有动态连接库,那么应该把LD_PRELOAD这样的环境变量先unset掉,否则会导致以新的userid执行额外的代码。写rtld的人对这一点很明确(/libexec/rtld-elf/rtld.c):trust = !issetugid(); /* * If the process is tainted, then we un-set the dangerous environment variables. The process will be marked as tainted until setuid(2) is called. If any child process calls setuid(2) we do not want any future processes to honor the potentially un-safe variables. */if (!trust) { unsetenv(LD_ "PRELOAD"); unsetenv(LD_ "LIBMAP"); unsetenv(LD_ "LIBRARY_PATH"); unsetenv(LD_ "LIBMAP_DISABLE"); unsetenv(LD_ "DEBUG"); unsetenv(LD_ "ELF_HINTS_PATH"); } 早期,4.4 bsd下的unsetenv函数是没有返回值的,必定成功的。可是后来为了与posix 1003.1-2001兼容,这个函数有了int类型的返回值用于标志成功与否。现在的unsetenv是这么实现的intunsetenv(constchar *name){ int envNdx; size_t nameLen; /* Check for malformed name. */if (name == NULL || (nameLen = __strleneq(name)) …