Linux - 行者无疆 始于足下 - 行走,思考,在路上

Mac OS X遭遇记

3月1号回到玉泉,处理了许多杂事,找导师沟通了下毕业设计的问题。沟通的最终结果就是我又被发配到了手机客户端组,继续做GUI控件。事实上我最开始选的题目是《海量空间数据的高性能引擎研究》,我还是挺喜欢这个方向的,而且与我在Baidu的实习以及日后的工作都有很大的关联性。但是导师一句“题目较难,时间不够”就把我噎了回来,紧接着来一句“我还是希望你能够做一些连续性的工作”——就是去年四月份实验室做的Windows Mobile控件开发了。其实我是非常不喜欢这个项目的。对于一个崇尚自由、分享的Open Source Programmer来说,用着盗版的Windows+VS,盗用Open Source的成果来开发闭源软件,实实在在是一件不怎么惬意的事情——老实说我也算不上合格的Open Source Programmer,因为我至今也没有自己的Open Source软件。其次是我越来越讨厌关于Windows的一切,无论是作为一个User还是Programmer。我最近正计划着写一系列的Windows吐嘈文,构思良久,即将面世。

只不过这次不同,我所面对的不再是Windows Mobile,而是——iOS。

How?这是我脑子里最先冒出的想法——How to write an Win32-Styled GUI program under Windows(or maybe Linux) platform for iOS?我战战兢兢地问了下学长“实验室有苹果机吗?”,答曰“没有,用虚拟机”。

Oh,my god。在Windows平台上运行着虚拟机,在虚拟机里面运行着Mac OS X,在Mac OS X里面运行Xcode,在Xcode写Win32-Styled Program,然后将这个Win32-Styled的Program Load到虚拟机里面的Mac OS X里面的Xcode IDE里面的iOS模拟器上,调试!!!

What a Joke!

不过,吐槽归吐槽,活儿还是要干。鉴于前两次Hacintosh的惨痛经历,所以这才在也不敢在自己精心调制好的ThinkPad x201i上为所欲为,还是乖乖的虚拟机的好。幸好前两天买了根三星金条,武装到了4G内存,否则还真不敢想象在虚拟机里面玩Leopard。

高级的虚拟机咱不懂,所以诸如KVMXen就不在考虑之列了。剩下的,最开始接触电脑时玩的Microsoft Virtual PC,不知道现在活的怎么样。VMware,大概是三年前用过,印象就是臃肿,慢。VirtualBox,我的最爱,开源、免费、跨平台、轻量快捷。所以VirtualBox是试验的首选环境。

不过Mac平台的封闭性带来一个众人皆知的事实,那就是Hacintosh的成功性与人品——也无关,我的意思是说,Hacintosh的成功与否完全是莫名其妙的事情,无论是虚拟机还是实体机,能否Hacintosh,要看上帝的心情。

Hacintosh的版本有很多,比如东皇、iATKOS、iDeneb、OSXPCBETA等等,boot loader也有若干种方案,比如变色龙、EFI Emulation等等,个中详细可以参考OSx86。而由这些基本“元件”排列组合出来的网上作为“PC变Mac”的方案更是五花八门,让人目不暇接。照理说,对各种硬件的良好支持是一个OS安身立命的最基本条件,至于Mac如何在违背这个基本原则下打拼出自己的逍遥天地,容我另外一篇文章再做分析。

好了,回到正题,继续我的Mac OS X遭遇记。我按照老赵点滴上的指示在我的ArchLinux+VirtualBox 4.0上做实验,前面都是很顺利的,也出现了下面的Kernel panic情况:

mac in virtualbox: kernel panic

按照教程,重启之后就可以进入期盼的Leopard,可是我却陷入了无限的灰色风火轮等待中。重整多番,调整了多组参数,均以失败告终。

于是转投VMware,我按照VMware的要求,下载了300+M的VMware7.1的bundle,按照ArchWiki上的步骤,成功装上了VMware,但是确始终启动不起来。无奈,转投Windows吧。之所以坚持Linux,是因为我需要LaTeX,我需要Emacs+Auctex+cdlatex+outline-mode来完成我的毕业论文啊。

好在Windows下的VMware还算正常,安装过程也算顺利,我就不在细说了。具体过程可以参考《VMWare下安装MAC OS X Snow Leopard 10.6》,需要注意的主要是:

  • 安装之前用securAble检测下CPU是否支持虚拟化;
  • 内存至少1G,最好主机配上4G内存,而VMware配上2G内存,否则慢起来很要命,如果搞开发,硬盘最好20G以上;
  • 注意修改VMware目录下的.vmx下的guestOS由guestOS = "freebsd-64"改为guestOS = "darwin10";
  • 启动时始终需要darwin.iso来引导;
  • 成功安装系统后安装darwin.iso里面的vmtools,获得更好地使用体验;

放张图吧:

vmware mac os x

顺便感叹下,VMware的虚拟化技术还真是强大,2G虚拟内存跑Mac OS X,速度还真是不赖,界面效果也都能跑的出来。如果再弄个分屏软件,再插上一个LCD的液晶屏,就真是两个系统了。

至于Xcode和iOS SDK的安装就简单很多了,可能需要做一次系统升级。至于iOS上如何写Win32-Style的GUI程序,我现在也是丈二的和尚。至于额外的Macintosh吐槽文,还是等以后心情不错的时候再写吧。

x86-64 Arch Linux on ThinkPad x201i

前两天自用的Arch Linux系统出了点小问题,索性重新搞了一下,由i686迁移到x86-64平台。原先一直以为64位系统是高不可攀的贵族产品,后来才知道原来64位处理器最早是由AMD 1999年设计,几年前的Intel Core Duo早已经支持64位系统,只是软件产品和内存还跟不上,所以多数应用还是32位为主。

OS版本用的是Arch Linux 2010.05,在mirrors.sohu.com上下载支持 32 位及 64 位架构的 Dual 映像,用UltraISO刻录硬盘镜像到U盘上。基本的安装过程不再赘述,ArchWiki Beginner's Guide讲的明明白白。唯一注意的是分区格式化的时候需要格外注意,不要把自己原先的系统搞丢——我曾经有过惨痛的教训,不过幸好那次做了数据备份。不过100G的东西备份还原也是件耗时耗力的工作啊^)^。

基本系统装好后,装个Desktop Environment,然后再做一下系统美化和针对小黑的特殊配置。过程还是挺繁琐的,因此写下来做个备忘。先上张图,KDE4.6——我承认我越来越浮云了……

最新的Xorg已经变得十分人性化,再也不需要手工配置恼人的xorg.conf,最新的Linux内核驱动也能自动识别鼠标和键盘,不会再出现进入图形界面却无法使用鼠标键盘的窘境——至少两年前是这样的。有个东西叫做HAL,最近又出来个evdev。总体而言Linux的驱动程序还是比较混乱的,hal、evdev、mesa、xorg、xf86、wayland、alsa、oss、pulseaudio等等,令人头大。

字体用的是AUR里面打过ubuntu补丁的cairo-ubuntu、libxft-cairo、freetyp2-ubuntu以及WenQuanYi Micro Hei,加上次像素优化,效果还是不错,上图就是最好的说明。

网络客户端抛弃了废柴的KDE的networkmanager,采用了wicd,可以根据地点自动链接不同的无线网,而且非常稳定,从不崩溃。安装过程可以参考ArchWiki Wicd。关于蓝牙的配置,我用的是bluez和bluedevel,具体可以参考这里

剩下的都是小黑的特别配置。这方面的Wiki配置零零总总,并没有统一的解决方案。ThinkWiki是一个很好的去处,基本可以找到ThinkPad各个型号再主流Linux发行版上的安装配置。不过由此也看出开源软件的弊端——顶级的ThinkPad支持尚且如此繁琐,可见Linux真正要普及还有很长的路要走。废话少说,还是回到x201i上的设置吧。ThinkPad的设置主要有以下几处:

  • 电池电源控制
  • trackpoint小红点
  • Active Protection System,硬盘保护系统
  • 风扇控制

电池的电源控制主要是用来延长电池寿命的。电池的充电次数是有限的,因此减少电池的冲放电次数是演唱电池寿命的关键。tp_smapi是针对ThinkPad的一组内核模块,可以通过AUR(yaourt -S tp_smapi)安装。对电源的保护主要是设置电源的冲放电阀值。比如我们设置[start_charge=40, end_charge=90],意思就是当电池的电量低于40%的时候才开始充电,而一旦电量到达90%的时候就停止充电。举例说明,当我们野外需要频繁的野外工作时,如果不设置电池的充放电阀值[start_charge, end_charge],那么我们的电量可能是这样的:95(battery, discharge)-->80(AC power, charge)-->100(battery, discharge)-->70(AC power, charge)-->93(battery, discharge)-->70,而设置[start_charge=40, end_charge=90]后我们的电量变化就是这样的:95(battery, discharge)-->80(AC power, but not charge)-->80(battery, discharge)-->50(AC power, but still not charge since 50 >= 40)-->50(battery, discharge)-->27(If AC power now, charge, since 27 >= 40, charge until battery = 90)。看明白了吗?估计没有。反正我也有点晕。ArchWiki上提供了一个封装的脚本set_bat_thresh:

#!/bin/bash
#
# Bash script for setting the battery thresholds on ThinkPads using the tp_smapi interface.
# Written by Ignas Anikevicius (20/03/2010)

#HELP TEXT
if [ "x$1" == "x--help" -o "x$1" == "x-h" ]
then
  echo -e "
  WARNING!!! This script needs to be run as root in order to have effect!!!

  Possible options are:
    set_bat_thresh [BAT_N] [[LOWER] [UPPER]][--reset][-r] 
 
    [BAT_N] number of the battery (can be either 0 or 1). 

    LOWER - lower threshold.
    UPPER - upper threshold .
    [--reset] or [-r] sets the default thresholds. 

  execute to see this text:
    set_bat_thresh [--help][-h]
"
  exit 0
fi 

if [ ! -d /sys/devices/platform/smapi ]; then
  echo -e "\nSMAPI interface is NOT installed.\nPlease load the module.\n"
  exit 0; fi

#SETTING THRESHOLD VALUES
if [ "x$2" == "x--reset" -o "x$2" == "x-r" ]
then
  LOWER=96
  UPPER=100
else
  LOWER=$2
  UPPER=$3
fi

#VALUE TESTING
if [ ${LOWER} -ge ${UPPER} ]; then
  echo -e "\n  Please provide proper thresholds!!!  \n"
  exit 0
fi

#BATTERY NUMBER
BAT_N=$1
LOWER_F="/sys/devices/platform/smapi/BAT${BAT_N}/start_charge_thresh"
UPPER_F="/sys/devices/platform/smapi/BAT${BAT_N}/stop_charge_thresh"

#SETTING THE THRESHOLDS
echo ${LOWER} > ${LOWER_F}
echo ${UPPER} > ${UPPER_F} 

#ECHOING THE STUFF
echo -e "\nSetting battery thresholds for Battery ${BAT_N}:
  Threshold for charging to start: ${LOWER} 
  Threshold for charging to stop: ${UPPER} 
"
exit 0;

执行用:

set_bat_thresh 0 start_charge end_charge

至于trackpoint小红点,AUR里面有一个trackpoint脚本,用yaourt -S trackpoint安装,安装完毕将trackpoint加到/etc/rc.conf的DAEMONS里面。/etc/conf.d/trackpoint里面可以更改一些设置如:

  • SPEED: 小红点光标移动速度。
  • SENSITIVITY: 小红点敏感度。
  • PRESS_TO_SELECT: 小红点单击功能。

中键模拟用如下的脚本设置下(我也忘了是从哪里找到的了):

xinput set-int-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation" 8 1
xinput set-int-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation Button" 8 2

硬盘保护(Active Protection System)用的是AUR里面的HDAPS,参看ArchWiki,Applet用的是thinkhdaps,根据需要改下/etc/conf.d/hdapsd里面的设置,效果还不错,抱着笔记本在床上看电影的时候视频会一卡一卡的。

风扇控制貌似不太不要,而且设置不好会影响散热效果,降低笔记本的寿命。这个功能主要目的貌似是使笔记本更安静些。用的软件包是AUR里面的tpfand和tpfan-admin,tpfand.conf是copy来的,参考这里。用了之后好像也没啥特别的效果。

最后show下/etc/rc.conf里面的设置,日后重装的时候也好有个参考:

#
# /etc/rc.conf - Main Configuration for Arch Linux
#

# -----------------------------------------------------------------------
# LOCALIZATION
# -----------------------------------------------------------------------
#
# LOCALE: available languages can be listed with the 'locale -a' command
# HARDWARECLOCK: set to "UTC" or "localtime", any other value will result
#   in the hardware clock being left untouched (useful for virtualization)
# TIMEZONE: timezones are found in /usr/share/zoneinfo
# KEYMAP: keymaps are found in /usr/share/kbd/keymaps
# CONSOLEFONT: found in /usr/share/kbd/consolefonts (only needed for non-US)
# CONSOLEMAP: found in /usr/share/kbd/consoletrans
# USECOLOR: use ANSI color sequences in startup messages
#
LOCALE="en_US.UTF-8"
HARDWARECLOCK="localtime"
TIMEZONE="Asia/Shanghai"
KEYMAP="us"
CONSOLEFONT=
CONSOLEMAP=
USECOLOR="yes"

# -----------------------------------------------------------------------
# HARDWARE
# -----------------------------------------------------------------------
#
# MOD_AUTOLOAD: Allow autoloading of modules at boot and when needed
# MOD_BLACKLIST: Prevent udev from loading these modules
# MODULES: Modules to load at boot-up. Prefix with a ! to blacklist.
#
# NOTE: Use of 'MOD_BLACKLIST' is deprecated. Please use ! in the MODULES array.
#
MOD_AUTOLOAD="yes"
#MOD_BLACKLIST=() #deprecated
MODULES=(uinput tp_smapi thinkpad_acpi thinkpad_ec vboxdrv)

# Scan for LVM volume groups at startup, required if you use LVM
USELVM="no"

# -----------------------------------------------------------------------
# NETWORKING
# -----------------------------------------------------------------------
#
# HOSTNAME: Hostname of machine. Should also be put in /etc/hosts
#
HOSTNAME="lox-pad"

# Use 'ifconfig -a' or 'ls /sys/class/net/' to see all available interfaces.
#
# Interfaces to start at boot-up (in this order)
# Declare each interface then list in INTERFACES
#   - prefix an entry in INTERFACES with a ! to disable it
#   - no hyphens in your interface names - Bash doesn't like it
# 
# DHCP:     Set your interface to "dhcp" (eth0="dhcp")
# Wireless: See network profiles below
#

#Static IP example
#eth0="eth0 192.168.0.2 netmask 255.255.255.0 broadcast 192.168.0.255"
eth0="dhcp"
INTERFACES=(!eth0)

# Routes to start at boot-up (in this order)
# Declare each route then list in ROUTES
#   - prefix an entry in ROUTES with a ! to disable it
#
gateway="default gw 192.168.0.1"
ROUTES=(!gateway)
 
# Enable these network profiles at boot-up.  These are only useful
# if you happen to need multiple network configurations (ie, laptop users)
#   - set to 'menu' to present a menu during boot-up (dialog package required)
#   - prefix an entry with a ! to disable it
#
# Network profiles are found in /etc/network.d
#
# This now requires the netcfg package
#
#NETWORKS=(main)

# -----------------------------------------------------------------------
# DAEMONS
# -----------------------------------------------------------------------
#
# Daemons to start at boot-up (in this order)
#   - prefix a daemon with a ! to disable it
#   - prefix a daemon with a @ to start it up in the background
#
DAEMONS=(@syslog-ng @dbus !hal !network !netfs @acpid @tpfand @crond @hdapsd @laptop-mode @wicd @kdm bluetooth @trackpoint)

大概就这么多吧。都是些琐碎的东西,能用就好了。想想Linux的东西变动如此之快,有些东西是真的不必深究的。比如关于中键模拟有上面的方案,也有改xorg.conf的方案。比如hal这个东西,再比如X Window和未来的Wayland,比如ext4和btrfs。想想自己走的也有些偏了,过于追求工具化的东西,倒是忽略了最本质的知识,如体系结构,算法等等。这就比如户外旅行,总是想方设法装一辆拉风的自行车,却很少去骑车领略旅行的真谛。四年,四年前的我还只会开机关机,四年后的我折腾系统小打小闹颇有一套,最本质的计算机基础却一塌糊涂。希望自己的折腾之旅到此位置吧。接下来的关键词是,lisp、tcp/ip,hadoop。

geek之趣

有计算机就有码农,有码农就会用geek。穿着内衣坐在电脑前,每天面对着“枯燥的代码”,一如既往,这就是常人眼里的geek形象。殊不知,geek们自由geek自己的乐趣。比如linux就是一个叫做linus的geek无聊时的作品。

断续使用linux两年不到,学艺不精,不懂系统管理、不知道网络安全、不知道啥叫路由器网关,倒是对linux下面的一些小东西颇感兴趣,翻来覆去地折腾。本文权且列举一二,如果能帮助读者窥探到开源精神的一二,那可真是善莫大焉了。

  1. fortune:这个程序可以用来
    • 算命
    • 提高英文水平
  2. git-shell:git是一种分布式版本控制系统,git-shell是git工具中的一个命令。可能我们第一眼看上去会觉得git-shell一定是一个git的命令环境,我们进入git-shell,然后就可以在这个环境下敲各种各样的git命令,git-shell之于git,就相当于shell至于linux一样。而事实上,我们在shell中敲入git-shell,得到的确是:“fatal: What do you think I am? A shell?”,这语气好像是linus怒气冲冲地在审问你:“你是不是没有好好学习我的git系统,才会犯如此的错误!?”。查阅git-shell命令的manual,才知道原来git-shell不是一个shell,而是一个“Restricted login shell for GIT-only SSH access”。
  3. man PK woman:如果你不知道一个命令的作用或者你忘记了ls命令的某个参数怎么办?显然,用“男人(man)”命令查看“男人页(manual)”就行了。与此相对,编辑器的老大哥emacs是一个self-documenting的系统,linux的info系统就是基于emacs风格的key binding,为了将广大的“男人页”收归自己囊下,emacs“针锋相对”的搞了个“女人”——woman,美其名曰“to browse Unix manual pages 'W.O. (without) man'”。至于“woman”的来龙去脉,大家自己去参看emacs内部的info文档即可,或者看这里
  4. ffmpeg, hall of shame:ffmpeg是linux下面一个著名的多媒体处理软件。可以用来进行格式转换,视频的crop、padding,剪裁,编解码等等。ffmpeg同时提供了一套优质的多媒体编解码库,而良好的编解码库是一个播放器的基础。linux下的很多播放器都和ffmepg项目有密切的配合和依赖关系。ffmpeg是遵循GPL协议的,但是很多播放器“无耻地”使用了ffmpeg的代码,却没有遵循GPL协议开放自己的代码,因此就上了ffmpeg的“耻辱柱”……What a Shame!
  5. The Matrix:你是不是以为shell就是用来敲击命令而vim是用来编辑文件的?你看国《The Matrix》吗?事实上就有这么几个“无聊透顶”的人,为了让自己cool一些,抽出些无聊的时间写了几个无聊的程序——cmatrix and vim matrix plugin。借用vim的广告词——“linux,字符也可以如此精彩”。
  6. sl:如果统计一下linux用户中最常用的10个命令,ls、cd肯定是榜上有名。借助shell的智能补全功能,或许我们敲命令的出错率反而会比超短命令(ls、cd)的出错率还要低。比如ls命令,我们一不小心敲了个sl,还没等shell的补全反应过来,我们已经大大方方的敲了Enter,彻底了解了这一怨念。结果往往是“command not found”的沮丧和无奈。而偏偏有geek闲来无事,将这种沮丧和无奈变成了小小的火车,载走你的烦恼,造福子孙后代,功德无量也。
  7. emacs doctor:代码敲累了?心情不好了?外边又打雷下雨啦?网络莫名断掉了?……最近倒霉事连串,心里不爽是吧——没关系,来看看emacs的心理医生吧,让它陪你聊聊,24小时陪聊,而且还是免费的!type "M-x doctor",enjoy it!
  8. gimp naming problem:from gimp FAQ():
    • Q: Why and when was GIMP changed from "general image manipulation program" to "GNU image manipulation program"?
    • A: One day (I believe it was in 1997) RMS visited Berkeley, and Spencer and Peter met with him. They asked if they could change General to GNU, and it was done.
    • Q: GIMP is a stupid name. Why can't you change it?
    • A: GIMP is comfortable with its name and thinks that you should apologise for your rudeness.
  9. GNU
    • Q: What is GNU?
    • A: GNU is Not Unix.
                          (@@) (  ) (@)  ( )  @@    ()    @     O     @     O      @
                     (   )
                 (@@@@)
              (    )

            (@@@)
          ====        ________                ___________
      _D _|  |_______/        \__I_I_____===__|_________|
       |(_)---  |   H\________/ |   |        =|___ ___|      _________________
       /     |  |   H  |  |     |   |         ||_| |_||     _|                \_____A
      |      |  |   H  |__--------------------| [___] |   =|                        |
      | ________|___H__/__|_____/[][]~\_______|       |   -|                        |
      |/ |   |-----------I_____I [][] []  D   |=======|____|________________________|_
    __/ =| o |=-~O=====O=====O=====O\ ____Y___________|__|__________________________|_
     |/-=|___|=    ||    ||    ||    |_____/~\___/          |_D__D__D_|  |_D__D__D_|
      \_/      \__/  \__/  \__/  \__/      \_/               \_/   \_/    \_/   \_/

About framebuffer

初次接触framebuffer这 个概念是在去年的9月,那个时候安装archlinux,进入X后觉得console好丑,quark一来,在grub启动的menu.lst上加了一句 vga=792,瞬间console就变成1024*768的分辨率了。先是感到惊喜,再叹quark的神通,三来意识到自己和别人的差距。关于怎样开启framebuffer,grub的配置文件注释里面有很好的说明,这里是我的部分配置menu.lst:

#  FRAMEBUFFER RESOLUTION SETTINGS
#     +-------------------------------------------------+
#          | 640x480    800x600    1024x768   1280x1024
#      ----+--------------------------------------------
#      256 | 0x301=769  0x303=771  0x305=773   0x307=775
#      32K | 0x310=784  0x313=787  0x316=790   0x319=793
#      64K | 0x311=785  0x314=788  0x317=791   0x31A=794
#      16M | 0x312=786  0x315=789  0x318=792   0x31B=795
#     +-------------------------------------------------+
#  for more details and different resolutions see
#  http://wiki.archlinux.org/index.php/GRUB#Framebuffer_Resolution 

# general configuration:
default   0
timeout   3
color light-blue/black light-cyan/blue

# boot sections follow
# each is implicitly numbered from 0 in the order of appearance below
#
# TIP: If you want a 1024x768 framebuffer, add "vga=773" to your kernel line.
#
#-*

# (0) Gentoo Linux 
title  Gentoo Linux
root   (hd0,8)
kernel /vmlinuz-2.6.34-gentoo root=/dev/sda5 rootfstype=ext4 quiet vga=792
initrd /initrd

恰好今天下午 做嵌入式系统的实验,LCD 显示缓冲区体验,要求编程序载入一张图片到LCD显示缓冲区,我回到实验室琢磨琢磨,看到了gentoo开机启动时的那只小企鹅图片,tux,想到开机的时候没有启动X,屏幕上显示出了tux图片,那么可以肯定的是,这张图片一定是通过某种驱动直接“写到显存"里面。而在grub的启动是否采用framebuffer,则和这只tux的”生死“有着直接的联系,因此我敢肯定,framebuffer肯定是这次实验的突破口之一。说干就干,回到实验室查了很多资料,对Framebuffer的相关知识做一次小总结。

FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。这种接口将显示设备抽象为帧缓冲区。用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读 写操作,而写操作可以立即反应在屏幕上。该驱动程序的设备文件一般是 /dev/fb0、/dev/fb1 等等(具体内容请参见:基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南)。

Framebuffer需要内核的支持,如果没有/dev/fb0类似的文件,恐怕要重新编译内核了。我们可以做两个简单的小实验,看看frambuffer究竟有怎样的魔力:

cat /dev/fb0 > screenshot
# or, dd if=/dev/fb0 of=screenshot
# need super user privilege
clear

仔细观察你的屏幕,然后:

cat screenshot > /dev/fb0
# or, dd if=screenshot of=/dev/fb0
# need super user privilege
clear

是不是有点中病毒的感觉?其实,最简单的理解,/dev/fb0是屏幕显示区域内存的一个抽象,前面先把这部分“内存”保存到screenshot里面,然后再将screenshot里面的”内存“拷贝回去,就实现了屏幕的还原。不过,由于我们使用的GUI和CLI的自动刷新,整个屏幕并不能实现100%的“还原”。

一切皆文件,the great Unix Philosophy,通过读写/dev/fb0,我们可以得到对显示屏100%的控制!进一步的讨论可以参考对FrameBuffer的一夜hack。由此,我的嵌入式实验算是基本达到了第二个要求:写入LCD的缓冲区。载入图片是个复杂问题,毕竟图片的格式五花八门,有损压缩、无损压缩;位图、矢量图等等,就连最简单的bmp位图,想要载入,恐怕也要了解bmp图形文件格式,颇费一番周折。此时我又想起来去年的图形学程序,最后一个project就是载入bmp文件作为纹理贴到一个teapot上面,整个程序下来有600行,不便贴出,给出我当时做的作业,其中载入bmp文件的代码可以作为参考。

至于copy两个文件的c语言程序,我也写了两个,采用的是C语言的标准IO和Linux系统调用IO两种方式:

ANSI IO:

#include <stdio.h>
#include <stdlib.h>

#define BUFSIZE 1024

int copyfile(const char * infile, const char * outfile) 
{
    FILE *fp1, *fp2;
    char buf[BUFSIZE];
    int n;

    if((fp1 = fopen(infile, "r")) == NULL)
    { 
        perror("open file error");
        exit(1);
    }
    
    if((fp2 = fopen(outfile, "w+")) == NULL)
    { 
        perror("open file error");
        exit(1);
    }

    while((n = fread(buf, sizeof(char), BUFSIZE, fp1)) > 0)
    { 
        if((fwrite(buf, sizeof(char), n, fp2)) == -1)
         {
            perror("fail to write");
            exit(1);
        }
    }

    if(n == -1)
    { 
        perror("fail to read");
        exit(1);
    }
    fclose(fp1);
    fclose(fp2);
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf ("Usage: cp from to\n");
    }
    char * file1 = argv[1];
    char * file2 = argv[2];

    copyfile(file1, file2);
    
    return 0;
}

Linux IO:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

#define BUFSIZE 512
#define PERM 0644

int copyfile(const char *name1, const char *name2)
{
    int infile, outfile;

    ssize_t nread;
    char buffer[BUFSIZE];

    if ((infile = open(name1, O_RDONLY)) == -1)
    {
        perror("open file error");
        return (-1);
    }

    if ((outfile = open(name2, O_WRONLY | O_CREAT | O_TRUNC, PERM)) == -1)
    {
        perror("create file error");
        close(infile);
        return (-2);
    }

    while ((nread = read(infile, buffer, BUFSIZE)) > 0 )
    {
        if (write(outfile, buffer, nread) < nread)
        {
            perror("write file error");
            close(infile);
            close(outfile);
            return (-3);
        }
    }

    close(infile);
    close(outfile);

    if (nread == -1)
    {
        return (-4);
    }

    else return (0);
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf ("Usage: cp from to\n");
    }
    char * file1 = argv[1];
    char * file2 = argv[2];

    copyfile(file1, file2);
    
    return 0;
}

至于两种IO有什么样的区别和联系,我写了一份文档,可以作为入门参考。更进一步的了解已经远远跑题,可以参看jservHackingHelloWorld系列。

OK,本次实验超额完成!120分!^_^


言归正传,事实上,有了framebuffer,Linux的console可以变得无所不能!

先上一张图:

在gentoo下,这种效果需要fbsplash的支持,参照Gentoo Wiki(其实当初装gentoo的时候,自己也折腾过这个,但是一直没有启动起来,不明原因,大概是内核版本的问题,可能同样是内核版本的问题,我的bootchart也无法启动)。还有一个类似的项目叫splashy,不过貌似发展比较缓慢,而且应用也不多。

可能你觉得这就是极限了吧……非也非也!其实有framebuffer,再加上mplayer,我们甚至可以在这样的终端下看视频!!

crazy sand art

mplayer本身是支持多种VIDEO OUTPUT OPTIONS,其中的一种就是framebuffer:

       fbdev (Linux only)
              Uses the kernel framebuffer to play video.
                 <device>
                      Explicitly choose the fbdev device name to use (e.g. /dev/fb0) or the
                      name of the VIDIX subdevice if the device name  starts  with  'vidix'
                      (e.g. 'vidixsis_vid' for the sis driver).

       fbdev2 (Linux only)
              Uses the kernel framebuffer to play video, alternative implementation.
                 <device>
                      Explicitly choose the fbdev device name to use (default: /dev/fb0).

终端截图需要fbgrab的支持。我们在一个终端以super user权限运行:

sudo mplayer -vo fbdev2 videoname

在另外一个终端,同样以超级用户权限运行:

sudo fbgrab filename.png

注意:

  • mplayer -vo选项需要为fbdev2,fbdev不行
  • fbgrab生成的png格式图像需要转换成jpeg格式才能得到满意的效果,否则视频区域一片透明,这可能与图像压缩算法有关(具体我就不知道了)。

差不多了,All about framebuffer。下一次,写一写如何打造高效快捷的终端环境,敬请期待!

it民工搞gentoo与农民种庄稼之间的关系

夜半果然是头脑发达四肢简单的时光啊。忽然想到自己花一个月时间安装调试的gentoo系统和农民种庄稼是一个道理。种庄稼的流程大体是:

while(1)
{

    先在荒山野岭开辟一块地,打上标号;   \\gentoo:硬盘里面划出一块分区,给个分区号/dev/sdaX

    拔草松土浇水整地;                           \\gentoo:格式化文件系统

    准备锄头,铁锨,人力,物力,必要时加上电力;    \\gentoo:准备基本系统工具,gnutoolchain,编译器,基本目录结构

    买种子化肥,根据地面情况和气候环境情况进行不同的搭配;    \\gentoo:下载内核,根据系统硬件不同做不同的组合配置

    播种施肥种庄稼,必须保证天时地利人和,才能有好收成;       \\gentoo:编译内核,compiling,compiling,compiling,注意compiling过程中不能断电死机,否则重 新来过,隔断时间需要人力保证系统正常运行编译

    庄稼在成长,根据不同地区气候条件生长周期也不一样;          \\gentoo:内核在编译。根据硬件配置编译时间长短不一

    秋天到了,天气转冷,开始收获庄稼;                                  \\gentoo:cpu温度降了,说明内核编译完了,开始检查是否正确

    找亮卡车,告诉他哪块地,让它在一定时间内把庄稼拉回来;    \\gentoo:装个引导器,设置好分区和timeout,看能否启动系统

    if(收成好)
    {
        加工倒卖;                                                          \\gentoo:各种美化配置字体窗口环境,最终手续若干,得到成品
    }
    else
    {
        continue;                                                        \\gentoo: 重新来过
    }
}

妙哉妙哉!有空再完善下。睡了睡了。




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee