Category: Linux

发现一个Virtualbox的bug

写了个toy,线程A依次以红色{255,0,0},绿色{0,255,0},蓝色{0,0,255},白色{255, 255, 255},灰色{110, 110, 110}写入整个fb设备,每一种颜色写入完毕后都通知线程B读取fb设备的全部像素输出为jpeg格式的图片,B线程输出图像完毕后通知A线程继续写入下一种颜色。也就是说,两个线程是同步工作的。

内核启动参数设为vga=0×0318,意思是分辨率为1024×768,颜色为24bits。

Host OS是Win XP,虚拟机是Virtualbox3.2.10,Guest OS是Debian testing。测试时发现,Virtualbox中显示的颜色是完全正确的,但B线程输出的jpeg图片中,只有红色和绿色是正确的,剩下的三种颜色都错了:蓝色变成了黑色,白色变成了黄色,灰色变成了暗黄色。我查了很久都没找到原因。

只好换一个环境试试。

Host OS还是Win xp,虚拟机换成VMware Workstation 7.1.1,Guest OS还是一模一样的Debian testing,启动参数依旧是0×0318。这下环境是一样的了,同样的代码,编译运行。VMware中显示的颜色和B线程输出的jpeg图片都是正确的。无语了。

只好给Virtualbox.org报了bug。

今天下午畢設答辯,我是倒數第二個。等待是無聊的,實驗室又沒有網絡,也沒有找到wifi,索性打開筆記本連上Hero上網聊天。

本文描述的方法僅在如下環境測試通過:

Debian Sid 2.6.32-5-686

HTC Hero 2.1ROM

中國移動西安網絡

步驟如下:

1.用USB線連接筆記本和Hero,在Hero上選擇連接類型為“Internet共享”。

2.在Debian下執行sudo ifconfig -a,可以看到名為usb0的網卡

3.執行sudo dhclient usb0,給usb0申請IP,我這裡得到的是192.168.100.100

4.執行ping -I usb0 google.com來測試網絡是否通暢

然後就可以用筆記本上網了,很方便吧。^_^

EOF

Linux转换视频到mp4

Hero播放视频的效果好得让我相当的惊讶!赶紧把我喜欢的MV都弄到Hero上。
以后坐车有得看啦,HOHO

ganquan@debian:~$ mencoder -of lavf -lavfopts format=mp4 -oac lavc -ovc lavc -lavcopts aglobal=1:vglobal=1:vcodec=mpeg4:vbitrate=600:acodec=libfaac:abitrate=128 -af lavcresample=22050 -vf dsize=480:360:0,scale=0:0,expand=480:360,harddup -ofps 25 -srate 22050 -o output.mp4  inputfile

framebuffer分辨率色彩表

自己留一份,懶得搜。

色彩 640×400 640×480 800×600 1024×768 1280×1024 1600×1200
4bits ? ? 0×302 ? ? ?
8bits 0×300 0×301 0×303 0×305 0×307 0x31C
15bits ? 0×310 0×313 0×316 0×319 0x31D
16bits ? 0×311 0×314 0×317 0x31A 0x31E
24bits ? 0×312 0×315 0×318 0x31B 0x31F
32bits ? ? ? ? ? ?

EOF

在内核空间中,是不能直接使用open, read, write之类的系统调用直接访问文件的。那怎么在驱动中访问一个文件呢?

我们知道在内核中用struct file来表示一个打开的文件,file结构体中有一个字段f_op,它是struct file_operation的指针。有了这个指针,就可以对文件进行访问了。
代码如下:

struct file *filp;
mm_segment_t fs;

filp = filp_open("/path/to/your/file", O_RDWR, 0);

if(!IS_ERR(filp))
{
    fs=get_fs();
    set_fs(KERNEL_DS);

    filp->f_op->read(...);
    filp->f_op->write(...);

    set_fs(fs);

    filp->f_op->mmap(...);

    /* ... */
}

filp_close(filp, NULL);


f_op->read()和f_op->write()的第二个参数是char __user *,也就是说是用户空间的地址,所以在驱动中直接传递kernel空间的指针,这两个函数都会返回失败-EFAULT。因此,在f_op->read()和f_op->write()之前需要使用void set_fs(mm_segment_t fs);来改变kernel对内存地址检查的处理方式。
该函数的参数fs只有两个取值:USER_DS,KERNEL_DS,分别代表用户空间和内核空间,默认情况下,kernel取值为USER_DS。所以可以用set_fs(KERNEL_DS);来让这个两个函数可以接受内核空间的内存。在内核空间中其他用__user修饰的参数,需要用kernel空间的内存代替时,都可以用类似的方法。
另外一个常用的函数f_op->mmap()则不需要设置fs,因为它的参数中不需要用户空间的内存。事实上,在struct file_operation中,只有read和write函数需要用户空间的内存,其他函数都不需要设置fs。
EOF