momo zone

调核人的blog

Monthly Archives: 四月 2010

buffalo hp-g54-ap 到, 强大的dd-wrt装备

信号最强,也是最经典的11g的路由器 。 外观很一般,做工也不比其他的好哪里去,很难想象这个就是传说中最强的G路由。登录了一下原厂固件,没有多看,直接刷DD-wrt 了,过程中异常小心,怕变砖就亏大了。然而刷过之后还是让人吓一跳,dia灯闪-〉熄灭-〉dia灯和aoss灯亮-〉熄灭  如此循环不停,心想这次挂了,变砖了,尝试一次回复原厂固件,没想到成功了,但很不甘心,不能刷DD我拿它做甚? 去论坛找了一个别人在hp-g54-ap上验证过的dd版本,竟然刷成功了~~ 。 进入web 管理发现确实功能异常强大,就是16MB的内存确实小了点,有点想去加内存的欲望。中继很好用,就是速度慢点。这个路由器的信号接收能力不算最强(目前我用的发现最强的仍然是intel5350) 。我到楼下测了一下,吓出一身汗,7楼到1楼再离远20米啊,信号还有95% ,再离远20米还有85%,再用psp测试一下,速度依然很快……. 无语~
除了ipkg-opt 自带的软件库,再提供两个资源:
ddwrt for whr-hp-g54 文章:
ddwrt 初始设置介绍:
jtag:
Advertisements

reiserfs 挂了

7年间第二次挂,用fsck 修了几次(rebuild-tree),部分文件树乱了,不过在lost+found中还能找到,损失不是太大,用rsync 同步一下目录就ok了。
这次不能怪文件系统不可靠,而是我连续非正常关机5,6 次。 不过ntfs 好像连续非正常关机十几次都没问题哦。

大搬家

耗时 : 24小时
参战人数 : 4人(1名逃兵)
总物资量 : 30个大包 (重2吨)

搬前状态 : 精神饱满 ,跃跃欲试。
搬后状态 : 筋疲力竭 ,长眠不起。

总开支 : 300RMB

关于页设置部分的代码

据有人反映这部分的代码相当晦涩难懂,但我仔细读了一下,发现难度一般,但确实如果对页机制和指针不熟练的话确实非常难懂。这部分的难点是非常具有迷惑性,你会纠结于到底是线性(逻辑)地址还是物理地址这样的问题中,但其实这个问题根本称不上问题,因为kernel在处理这段代码时都是在核心态,而核心态的逻辑地址和物理地址在数值上是一致的。
看一下这部分中最为晦涩的一个函数(尽管它非常短):
 
 unsigned long put_page(unsigned long page,unsigned long address)
198 {
199         unsigned long tmp, *page_table;
200 
201 /* NOTE !!! This uses the fact that _pg_dir=0 */
202 
203         if (page < LOW_MEM || page >= HIGH_MEMORY)
204                 printk("Trying to put page %p at %pn",page,address);
205         if (mem_map[(page-LOW_MEM)>>12] != 1)
206                 printk("mem_map disagrees with %p at %pn",page,address);
207         page_table = (unsigned long *) ((address>>20) & 0xffc);
208            if ((*page_table)&1)
209                 page_table = (unsigned long *) (0xfffff000 & *page_table);
210         else {
211                 if (!(tmp=get_free_page()))
212                         return 0;
213                 *page_table = tmp|7;
214                 page_table = (unsigned long *) tmp;
215         }
216         page_table[(address>>12) & 0x3ff] = page | 7;
217 /* no need for invalidate */
218         return page;
219 }
 
这个函数的作用本身就不是很好理解:将指定地址所在的页放入主存。
这样描述很简练,但根本就不能够了解它到底做什么。那么就把它展开说得啰嗦点:将指定线性空间(address 1MB-4GB)所在页映射到指定物理内存页(page 1MB-16MB)中,且address是用线性地址表示,page是物理地址表示。
这段代码中还对page_table进行的变量复用(不可取啊,牺牲了可读性),207 行得到的page_table 其实是page_dir ,然后再次209,214 才是获得的page_table。还有一个疑问,入口参数的逻辑地址怎么得到的?  关于这个要看缺页处理函数do_no_page() (可以想象到unsigned long page 其实也是通过get_free_page()获得的)。也就是说每次处理一次缺页最多需要3次页相关操作,1:分配一个用于储存真正数据的页;2:分配一个数据页的页目录项;3:分配一个页目录。

关于ln 软链接的一个误区

前几天在做RT-thread 的RTOS的porting,由于源码包是通过软链接实现架构差异定制的,所以必须先通过create-link脚本创建软链接。打开这个脚本看到其中有这么一段
for m_list in `ls ../../src`
        ln -s ../../../src/$m_file src/$m_file
done
 
起初以为脚本有误,既然PWD都确定了,但loop和ln 是的层次不对。
后来通过测试我发现如果ln 需要通过相对路径进行链接,需要以目标文件(链接文件)为准,而不是PWD。
    

用eclipse调试kernel

发现用eclipse调试kernel是最佳选择。比古老的DDD和简陋的kdbg都强大不少。
不过配置过程中还是遇到不少问题:
1. 部分变量不会自动更新
2. 寄存器窗口在执行跳转后不能正常显示,只有拖动窗口后才能显示出来。
3. 开始执行gdbserver后需要很长时间才能连上。

第一个已证实是gdb的bug,更新到SuSE的gdb-2009就没有问题了。
第二个还不清楚,更新eclipse 和 jdk 后都没有解决。不过影响不是太大。
第三个升级eclipse到最新就ok了。

记录一下配置过程:
1. 不要新建项目直接把编译后的内核文件(tools/system)导入,导入类型为C/C++ Excutable。


2. 设置debug configurations : 
   设置Process Launcher:


3. 设置debugger


4. 设置connection


5. 万事具备,布置layout吧

adobe cs5 发布

图像/图形设计领域的重量级软件adobe cs5 发布了,这次带来的新特性感觉比cs3到cs4 时要多一些。
首先PS原生支持64Bit ,并且带来了GPU加速。
 
FL带来了新的视频编解码器,html5转换功能,以及Flash Builder 集成(拜托,adobe 现在才搞出一个像样的ide啊,早干什么去了)
 

关于do_hd_request中sec调整的疑惑

在这段代码里:
void do_hd_request(void)
{
    int i,r = 0;
    unsigned int block,dev;
    unsigned int sec,head,cyl;
    unsigned int nsect;

    INIT_REQUEST;
    dev = MINOR(CURRENT->dev);
    block = CURRENT->sector;
    if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
        end_request(0);
        goto repeat;
    }
    block += hd[dev].start_sect;
    dev /= 5;
    __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
        "r" (hd_info[dev].sect));
    __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
        "r" (hd_info[dev].head));
    sec++;
    nsect = CURRENT->nr_sectors;
……
}
在获得绝对磁头,柱面和扇区号 后进行了 sec++ 。起初疑惑不解,不过很快我想到一个困惑我很久的问题:0磁头,0柱面,0扇区 还是0磁头,0柱面,1扇区?我的意思是磁盘的绝对的0扇区应该是0磁头,0柱面,1扇区吧。换句话说,每磁道扇区的范围是1-63,还是0-63?抱歉,这真的是一个常识性问题,但确实出乎意料,因为答案是63 。也就是整块磁盘的起始都是0磁头,0柱面,1扇区。
于是这个sec++的问题也就不难理解了,因为后面的hd_out要按照CHS的规矩去定位扇区(从1开始),而do_hd_request是按照从0开始的规则,这里要+1 修正哦。用gdb 调试一下就看得出来。

big map is drawing…

进度比较慢,不知道什么时候能画完啊 ~~

关于sleep_on(&buffer_wait)的疑惑

在buffer.c 有这段:
 

static struct task_struct * buffer_wait = NULL;

 
……
 
struct buffer_head * getblk(int dev,int block)
{
…… 
 do {
  if (tmp->b_count)
   continue;
  if (!bh || BADNESS(tmp)<BADNESS(bh)) {
   bh = tmp;
   if (!BADNESS(tmp))
    break;
  }
 } while ((tmp = tmp->b_next_free) != free_list);
 if (!bh) {
  sleep_on(&buffer_wait);
  goto repeat;
 }
……
}
 
这里看到buffer_wait是空指针,即buffer_wait所指示的等待进程(控制块)不存在。那么把一个不存在的进程(控制块)指针的地址给sleep_on是什么意思?
了解到buffer_wait 起初是空的。而这个buffer_wait 是静态指针说明他是常驻内存,且地址永不变化。ok , 既然buffer_wait 是指向task struct ,那么*buffer_wait(原型) 就是指向N个task struct 。又想到buffer_wait 是静态指针,所以没错,*buffer_wait(原型) (或&buffer_wait) 就是指的等待队列喽。 参考sleep_on()的函数:
 

void sleep_on(struct task_struct **p)
{

……

 tmp = *p;
 *p = current;
 current->state = TASK_UNINTERRUPTIBLE;

……}

明白了,sleep_on 形参就是接收的等待队列指针哦。*p就是获得等待队列头的task struct 。而且&buffer_wait就是等待队列的起始地址(NULL的地址,即&NULL。NULL虽是0,但也有被分配地址哦:DS段 0x10(内核数据段))。刚开始我被搞糊涂了,以为起始地址被设置成NULL,正确的理解是等待队列的初始状态时没有任何进程等待。