2011年10月27日星期四

check periodically if port is open from windows

因为远端的机器问题莫名其妙就连接不上了,各种原因。用netcatschtasks来定期检查本机上的端口是不是开着,没开着就重启。netcat的Windows版本见文末链接。

把以下代码存为文件test-7771.bat

@echo off

nc -z 10.17.17.177 7771
if ERRORLEVEL 1 shutdown -r -t 180

exit %RANDOM%

用以下命令添加任务计划,每10分钟执行test-7771.bat一次。

schtasks /sc MINIUTE /mo 10 /tn test-7771 /tr C:\test-7771.bat

有用的链接:
netcat (Windows), http://www.securityfocus.com/tools/139

2011年10月13日星期四

netsh portproxy not working within windows xp

netsh interface portproxy在Windows XP上边不起作用,一直报"connection refused"。因为缺少IPV6MON.DLL。需要使用ipv6 install来安装IPv6协议。如果还是不行,记得使用reset来重置之前所设置的项。具体请见文末链接。

SSH真的是非常好。今天拿到一个从路由器到内网机器的端口映射,只此一个。除去偶尔VNC来查看一下,还想要在里边多装几个Linux虚拟机,山寨一个词语,我需要“TCP port multiplexer”。嗯,SSH很好用。

参考链接
NETSH INTERFACE PORTPROXY do not work when doing port redirection between IPv4 and IPv4 addresses., http://support.microsoft.com/kb/555744/en-us
win7-xsnews.txt, http://psfreedom.com/win7-xsnews.txt

2011年8月21日星期日

Co-existence of python 2.x and python 3.x

此文用于备忘两个命令:ASSOCFTYPE

先安装的是2.7,然后再安装的3.2,3.2后来居上成为默认的.py文件解释器。如果平时都是使用2.x版本工作的话,这样就不行了。以下是解决方法演示


F:\>assoc .py
.py=Python.File

F:\>ftype Python.File
Python.File="C:\Python32\python.exe" "%1" %*

F:\>ftype Python.File="C:\Python27\python.exe" "%1" %*
Python.File="C:\Python27\python.exe" "%1" %*

F:\>ftype Python.File
Python.File="C:\Python27\python.exe" "%1" %*


这样就让2.7成为默认的解释器了。

发觉Python核心的开发流程应该很不错,之前对Python源代码的简单接触也让我对其兴趣渐增,应该要学习一下了。特别是关于测试、项目流程和组织方面,嗯。

2011年8月13日星期六

FFmpeg Notes

记录一下常用的选项,经常去ffmpeg-doc.html去翻那一大坨选项满不好的。

首先,Sheldon的“吓死喔了”

ffmpeg -i "The.Big.Bang.Theory.1x17.The.Tangerine.F
actor.720p.HDTV.x264-DIMENSION.[tvu.org.ru].mkv" -ss 00:11:02.450 -t 00:00:01.70
0 nearly_scared_me_to_death.mp3
-i:指定输入文件(input)
-ss:选择起始时间点(seek start point),格式HH:MM:SS[.xxx]
-t:指定时长(duration)


参考链接
FFmpeg Documentation, http://ffmpeg.org/ffmpeg-doc.html

2011年8月10日星期三

yszhou's First Haskell Function

这个暑假在杭州实习,前天晚上用手机翻到Haskell的主页,看到《Learn You a Haskell for Great Good》,很轻松的那种。之前尝试过《Real World Haskell》,也许英语水平不行?反正很挫。

今天晚上在CPyUG上看到有pyer感慨函数式编程,便把毕设时开小差下载下来的HaskellPlatform安装上,写了以下函数,用于实现Descartesian Product。算是一步一步更General吧。高级语言表达思维,硬件来确认,他们接起来的细节是什么?

enum :: Int -> [[Char]]
enum 1 = ["A", "T", "C", "G"]
enum n = [ x:enum_decr | x <- "ATCG", enum_decr <- enum (n - 1) ]

enum' :: [Char] -> Int -> [[Char]]
enum' init_value 1 = [ [x] | x <- init_value ]
enum' init_value n = [ x:enum_prev | x <- init_value, enum_prev <- enum' init_value (n - 1) ]

enum'' :: [a] -> Int -> [[a]]
enum'' init_value 1 = [ [x] | x <- init_value ]
enum'' init_value n = [ x:enum_prev | x <- init_value, enum_prev <- enum'' init_value (n - 1) ]

2011年7月25日星期一

type And object in Python

首先笔记以下在解释器中的记录:
>>> isinstance(type, type)
True
>>> isinstance(type, object)
True
>>> isinstance(object, object)
True
>>> isinstance(object, type)
True
>>>
在文章《Python Types and Objects》分析的初始阶段,有如下图。所以:
1. type是type的实例,在图中已经体现;
2. 由于type是object的子类,加上条件1,所以type是object的实例;
3. 由于ojbect是type的实例,type又是object的子类,所以object也是object的实例;
4. 在图上已经体现。

另外,"type"或者"class"在Python中有如下特点:
1. 能被子类化(subclassed),或者说被继承(inherited);
2. 能被实例化(instantiated),即“创造出实体”来。由“人”创出“张三”,由“int”创出“2”;
3. 它们的type(调用type())或者__class__都为<type 'type'>。即使是层次很深的继承亦如此。


参考链接:
Shalabh Chaturvedi, Python Types and Objects

2011年7月23日星期六

Using gogoc's IPv6 DNS Server

/etc/NetworkManager/dispatchter.d/下新添加一个文件,命名为99dnsgogoc。当NetworkManager探知新的网络事件时,就会按文件名的字典序依次执行目录里的那些脚本,见man NetworkManager。往99dnsgogoc里添加如下内容:

#!/bin/sh -e

GOGOC_DNSSERVER="nameserver 2001:5c0:1000:11::2"
# Insert disco.gogo6.com's AAAA record to /etc/resolv.conf's first line
sed -i "1i$GOGOC_DNSSERVER" /etc/resolv.conf
这样就会优先使用gogoc具有IPv6解析功能的DNS服务器,比如BlogSpot和Youtube就可以很方便的访问了。

参考链接
http://gogonet.gogo6.com/forum/topics/installing-gogoc-in-ubuntu?commentId=3731159%3AComment%3A118744

2011年5月27日星期五

备忘:手机摄像头的再利用[Nokia 7260]

我有一个Nokia 7260手机,黑红的,进大学时带来了北京。2008年换了新手机,一直放寝室柜子里,企图某天知识到位了练练手。拆卸之,至少把那个摄像头用上。

7260的摄像头是30万像素的,有夜间模式,感光其实还满好的。想起来,这个手机给我留下了不少好资料。如今,正要毕业了,大学余额不足30天,虽然知识储备还远远不足,想要对这个项目的情况有所了解,所以开始收集资料了。

首先找到了一份7260-schematic.pdf的文档,包含有7260较详细的线路图。Camera模块的编号是X1470,上面标注的型号是CLE9014-01E。文档里边还包含有它的时钟信号在示波器里的参数。

还没有拆机,囧。先记在这里,这事够复杂。现在的思路是:拿到它的datasheet,分析工作机制。非电子工程专业,猜测后边会需要用到一些控制器,把最小元器件集合从手机里剥离出来,跟控制器对接,根据datasheet写驱动,当然,这是很后很后的话了。


更新:
1. CLE9014-01E,虽然搜索没有找到完全对应的数据。不过,它应该指的是摄像头的插座,叫做Camera Module Sockets,貌似由一家日本公司(www.smk.co.jp)设计制造。2011-05-27
2. STV0900BE,图上写着HW accelerator,应该是硬编解码之类的东西。它跟Camera连着。还是不知道他们之间的关系。2011-05-27

2011年4月29日星期五

Toggle Proxy Settings in Windows Through Python

不是说ctypes很牛逼吗,不是说扩展功能很强吗,怎么做到的?不想使用pywin32这样的第3方库。找着找着,发现Python自备了一个叫做_winreg的模块,还好在解释器里import了,吃惊不小。

好吧,代码显示不太正常的样子,pastbin吧
import ctypes
import _winreg

# See http://msdn.microsoft.com/en-us/library/aa385328(v=vs.85).aspx
#: Causes the proxy data to be reread from the registry for a handle. No buffer is required. This option can be used on the HINTERNET handle returned by InternetOpen. It is used by InternetSetOption.
INTERNET_OPTION_REFRESH = 37
#: Notifies the system that the registry settings have been changed so that it verifies the settings on the next call to InternetConnect. This is used by InternetSetOption.
INTERNET_OPTION_SETTINGS_CHANGED = 39
# setup function
Wininet = ctypes.windll.Wininet
InternetSetOption = Wininet.InternetSetOptionW

HKEY_CURRENT_USER = _winreg.HKEY_CURRENT_USER
SUB_KEY_PATH = r'Software\Microsoft\Windows\CurrentVersion\Internet Settings'

def main():
    hkey = _winreg.OpenKey(HKEY_CURRENT_USER, SUB_KEY_PATH, 0, _winreg.KEY_READ | _winreg.KEY_WRITE)
    (ProxyEnabled, _) = _winreg.QueryValueEx(hkey, 'ProxyEnable')
    _winreg.SetValueEx(hkey, 'ProxyEnable', 0, _winreg.REG_DWORD, not ProxyEnabled)
    print 'enabled' if not ProxyEnabled else 'disabled'


    InternetSetOption(0, INTERNET_OPTION_REFRESH, 0, 0)
    InternetSetOption(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)

if __name__ == '__main__':
    main()

程序首先检查HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable的值,然后Toggle一下,0则设为1,1则设为0。然后通过InternetSetOption函数告知系统设置已变。

Chrome不自备代理控制功能,感觉Swichy的体验不好。之前尝试用显示的注册表操作命令完成,可是Chrome硬是不随之变化,非得再开一次那个Internet Options窗口才生效。特别是更新.pac文件的时候,真苦逼,居然假死。

想要接触Win32和Python的C扩展,希望对系统和编译器了解得多一些,但是Visual C++和Win32的那些宏真的很繁琐,即使用Python也不容易放开手脚。

更新:
[1]. 用ctypes调用RegOpenKeyEx和RegQueryKeyEx,http://pastebin.com/35zv649Q
[2]. 第一次写Windows API程序。真复杂。http://pastebin.com/kGWGJMmL

有用的链接:
[1]. InternetSetOption Function,http://msdn.microsoft.com/en-us/library/aa385114(v=vs.85).aspx
[2]. Option Flags,http://msdn.microsoft.com/en-us/library/aa385328(v=vs.85).aspx
[3]. The ctypes package,http://starship.python.net/crew/theller/ctypes/

2011年4月28日星期四

Variables With Underscores In Python

Python's magical underscored identifiers always surprised me!

__repr__, __unicode__, __str__, __len__, __gt__, __lt__, __eq__, __hash__, __get__, __set__, __getattr__, __setattr__, __del__, __iter__, __next__, __getitem__, __dict__, __blah__

所以……有木有!有木有!!下面讨论的场景主要是在类的定义中。可参见链接[1]。

1. 一个下划线
这是一个约定。使用单个下划线的标识符表示该符号是对象私有的,使用者不应直接操作之。

2. 两个下划线
在类的定义中,如果出现__identifier这样的符号,则不论其所处的语法上下文,都会被符号_classname__identifier代替,其中,classname是去掉下划线的类名。如下例:

>>> def __print_hello():
...     print 'hello'
...
>>> class Class(object):
...     def pack(self):
...             __print_hello()
...
>>> inst = Class()
>>> inst.pack()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in pack
NameError: global name '_Class__print_hello' is not defined
>>>
嗯,我就在第2种情况里挂了一次。。

链接:
[1]. Private Variables,http://docs.python.org/tutorial/classes.html#private-variables
[2]. The meaning of a single- and a double-underscore before an object name in Python,http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python

Streams in NTFS

使用Windows 7后发现,从浏览器下载的文件的属性多了些东西,例如:
"This file came from another computer and might be blocked to help protect this computer"
IE,Google Chrome,Firefox都支持这个功能。这个属性不会随着位置的移动和拷贝而丢失。"Unblock"之后的文件与原文件的各种哈希校验也一致。How Windows managed to track such kind of identity?

这个特性来自于NTFS的Streams概念。存放着数据之外的数据。打开一个命令行,执行以下命令:

echo Hello, Streams >test:stream
more <test:stream
第1条命令会创建一个test文件,文件的大小为0. 第2条命令会显示结果“Hello, Streams”。重定向符冒号后边的即是流的名称了,每个文件可以有多个。上边提到的识别功能即是利用NTFS Stream这种“数据之外的数据”做到的。

使用链接[1]里提供的工具,可以查看到一个文件包含的流信息。用那个工具检查从浏览器里下载的文件,有这样的结果:

F:\>streams breathe-life.jpg

Streams v1.56 - Enumerate alternate NTFS data streams
Copyright (C) 1999-2007 Mark Russinovich
Sysinternals - www.sysinternals.com

F:\breathe-life.jpg:
   :Zone.Identifier:$DATA       24

F:\>more <breathe-life.jpg:Zone.Identifier
[ZoneTransfer]
ZoneId=3
从链接[2]我们可以知道流的命名规范为:filename:stream name:stream type,所以呢,Zone.Identifier就是流的名字了,$DATA即流的类型。那么,如果清空掉这个流的信息会怎么样呢?其实就相当于“Unblock”操作了。

F:\>set /pvar=<nul >breathe-life.jpg:Zone.Identifier
在链接[3]里边有一个写流的例子,用C也可以的,就写了一个。
#include <stdio.h>

int main()
{
    FILE *fout;

    fout = fopen("test:stream", "wb");
    fprintf(fout, "Hello Stream Through Pure C.\n");
    fclose(fout);
    return 0;
}

链接[5]是比较全的一篇介绍,Data Streams是NTFS的特性,所以,当文件从NTFS向FAT转移时,流的信息会丢失。链接[6]来自维基,对Streams的背景进行介绍,在文件系统里边,除我们看到的常规文件属性信息外,还有一种叫做fork的信息,fork信息最大的不同是它没有大小限制,甚至可以比正常数据更大,Streams即是NTFS里的fork。


链接:
[1]. Streams v1.56,http://technet.microsoft.com/en-us/sysinternals/bb897440.aspx
[2]. File Streams,http://msdn.microsoft.com/en-us/library/aa364404(VS.85).aspx
[3]. Using Streams,http://msdn.microsoft.com/en-us/library/bb540537(v=VS.85).aspx
[4]. http://superuser.com/questions/38476/this-file-came-from-another-computer-how-can-i-unblock-all-the-files-in-a
[5]. Practical Guide to Alternative Data Streams in NTFS,http://www.irongeek.com/i.php?page=security/altds
[6]. Fork (file system),http://en.wikipedia.org/wiki/Fork_(filesystem)

2011年4月25日星期一

使用gogo6创建IPv6网络

1. 点击此链接,进去创建一个账号Freenet6账号,(注:Freenet6和gogoNET账号用处是不同的)。

2. 使用的操作系统Ubuntu 10.10,需要安装的包名为“gogoc”。

3. 配置/etc/gogoc/gogoc.conf。下面的配置是用于路由器方式的,eth1属于VMnet0网络,gogoc服务启动后,会使用radvd给VMnet0上的机器提供地址自动配置服务。原始文件配置文件的注释中有详细的说明,配置时只需要相应的uncomment就好了,赞!
userid=username
passwd=password
server=authenticated.freenet6.net
auth_method=any
host_type=router
prefix_len=64
if_prefix=eth1
log_stderr=0
log_file=3
4. "Not starting gogoc - no server key",或者plain方式可以成功,passdss-3des-1却不可以。参见文档/usr/share/doc/gogoc/README.debian,解决办法有两种:
    1. 使用/usr/sbin/gogoc -n启动gogoc,根据提示手动添加公钥
    2. 编辑/etc/default/gogoc,修改选项:CHECK_KEYFILE="no"
公钥文件位置:/var/lib/gogoc/gogockeys.pub,可以打开看一看。

5. 服务控制
    1. 打开,停止,重启服务:sudo service gogoc start|stop|restart
    2. 强制关闭:sudo killall gogoc radvd
    3. 打开和关闭开机自启动:sudo update-rc.d gogoc enable|disable

6. 修改gogoc启动radvd时的配置参数。相关的文件在/usr/share/gogoc/template/linux.sh,有这样的内容:
cat > "$rtadvdconfigfile" <<EOF
##### rtadvd.conf made by gogoCLIENT ####
interface $TSP_HOME_INTERFACE
{
  AdvSendAdvert on;
  AdvLinkMTU 1280;
  prefix $TSP_PREFIX::/64
  {
    AdvOnLink on;
    AdvAutonomous on;
  };
};
EOF
修改cat行和EOF行之间的内容就好了,比如把AdvLinkMTU调大。

移位和尾端

遭遇多次了,还是记下来好。曾经看到一些对尾端的描述,用的是“前前后后”、“左左右右”这些个相对参照,描述的内容一样,每各人每次的理解常常不一致。所以先定义一些“绝对参照”:

对于内存中数据的表示,屏幕上,纸上,从左到右,从上到下,地址从小到大。
对于逻辑上数据的表示,屏幕上,纸上,从左到右,从上到下,先是高位(MSB),再是低位(LSB)。

1. 移位操作是有独立意义逻辑意义的,不依赖尾端。以0x0102为例:
    <<. 左移4位,就增大16倍,变成0x1020
    >>. 右移4位,就用整数除法减小了16倍,变成0x0010

2. 尾端影响的是数据在内存、CPU、线路上存储,传输和处理时的排布。以0x0102为例,在大尾端机器内存中的顺序是01 02,在小尾端机器内存中的顺序是02 01。识记方法,我们用的x86电脑是小尾端的,小尾端,低地址对应低位,高地址对应高位。

3. 字节为单位,8比特
以IPv4和IPv6中的头部字段中的片偏移和标志位为例,演练一下移位操作和尾端。frag_off保存的是一个16位的大尾端数据,其中有13位是片偏移,3位是标志位,排布如下:
IPv4中:(0(1),DF(1),MF(1),Fragment-Offset(13))
IPv6中:(Fragment-Offset(13),Res(2),M(1))
其中,Res是保留位,全部置0,MF与M是等价的两个标志

从IPv4的格式转换为IPv6的格式
#define IP_OFFSET 0x1fff
#define IP_MF     0x2000

frag_off_6 = (ntohs(frag_off_4) & IP_OFFSET) << 3;
frag_off_6 &= 0xfff8;
frag_off_6 |= (ntohs(frag_off_4) & IP_MF) ? 0x0001 : 0x0000;
frag_off_6 = htons(frag_off_6);
总结:不纠结于那8+5=13的比特边界,先把数据转成宿主机的格式(ntohs),然后换照“绝对参照”中的逻辑,该怎么操作就怎么操作,操作完成后,再转成目标尾端(htons)。

4. Bit Field,下面这个结构定义是怎么回事?
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u8    ihl:4,
        version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
    __u8    version:4,
          ihl:4;
#else
#error    "Please fix <asm/byteorder.h>"
#endif
计算机在读写内存的时候,逻辑上最小的单位是1个字节,也就是8比特。IPv4头部中version和ihl各占4比特,编译器要把它们组装成1个字节。一般来说,传输时,version在前,ihl在后。因此,这2个4比特的组装顺序不是儿戏。

文章最开始规定的“绝对坐标”也是编译器和代码编写者之间的逻辑约定,地址前低后高。以小尾端为例,按第2条描述的识记方法,低(ihl)对应LSB,高(version)对应MSB,因此组装后的字节就是(version,ihl),Bingo!

如果代码就按defined(__LITTLE_ENDIAN_BITFIELD)来写,在大尾端机器中会怎么样呢?低(ihl)对应MSB,高(veresion)对应LSB,因此组装后的字节就是(ihl,version),反啦!

5. 有用的链接
[1]. Low Level Operators and Bit Fields, http://www.cs.cf.ac.uk/Dave/C/node13.html

2011年4月24日星期日

Chrome浏览器使用笔记

书签部分
Ctrl + Shift + B,显示或者隐藏书签栏。
Instapaper.com的“Reader Later”书签。网页内容很赞?Mark之。Instapaper.com提供的服务很完备,可以导出到移动设备上看(虽然我没有那些个高科技),也可以导出文章列表线下保存。还可以删除账号,这是非常难得的。


插件部分
Adblock Plus for Google Chrome
    必须的!去广告
Vimium
    简化版的Vimoperator,可能限于Chrome提供的接口限制。“一个按钮一个功能”很实用
Google Calendar Checker (by Google)
    长期伏网狩猎,浏览器中的日程管理自然不能少了
SingleFile & SingleFile Core
    通过DATA URL的方法,把网页变成一个文件,方便做Archive
YouTube Downloader
    YouTube是啥???
iReader
    仿的Safari Reader,规范化网页中的正文的风格,方便阅读
Screen Capture (by Google)
    截屏工具,用过一段时间,平时都是Disable状态。所以Firefox的Enable和Disable需要重启么!
SmoothScroll
    Firefox和Mac上Chrome的平滑滚动,Windows版的Chrome大概是忘了。毕竟不是原生态,我发现这个平滑滚动只是针对整个页面而言的,对于页面里边的如<textarea>无能为力,不过,这种情况是少数啦,推荐之,等原生的功能支持出来再卸了吧。

2011年4月23日星期六

apt-cache笔记

用于操作当前系统中包的缓存信息

1. 显示可选的版本,依赖和被依赖关系
apt-cache showpkg pkg(s)
2. 显示缓存中的统计信息
apt-cache stats
3. 从源码的角度提取包信息,包括编译依赖,项目主页,维护人等等
apt-cache showsrc pkg(s)
4. 当出所有的包信息,简要的(dump)和详细的(dumpavail)
apt-cache dump
apt-cache dumpavail
5. dpkg --print-avail,貌似更详细
apt-cache show pkg(s)
6. 搜索缓存
apt-cache search regex [regex ...]
默认使用POSIX regex搜索包的名字和描述文字,输出匹配的包的名字和简要描述。--full会使匹配的结果以apt-cache show的方式输出,巨详细,巨混乱。--names-only,会使搜索范围仅限于包的名字。多个正则表达式相当于做与操作
7. 显示依赖和被依赖关系
apt-cache depends
apt-cache rdepends

dpkg笔记

但愿这是一个不多不少的好工具。

维基百科的描述
dpkg is the software at the base of the Debian package management system. dpkg is used to install, remove, and provide information about .deb packages.
dpkg itself is a low level tool; higher level tools, such as APT, are used to fetch packages from remote locations or deal with complex package relations. Tools like aptitude or synaptic are more commonly used than dpkg on its own, as they have a more sophisticated way of dealing with package relationships and a friendlier interface.

dpkg是一个管理的范围限于本地。

安装和移除
1. 从.deb文件安装
dpkg -i, --install package_file...
2. 移除包
dpkg -r, --remove, -P, --purge package...|-a|--pending

dpkg-deb,.deb文件相关命令
1. 创建.deb包
dpkg -b, --build directory [archive|directory]
2. 列出.deb文件内容
dpkg -c, --contents archive
3. 从.deb文件中提取控制信息(control-information)
dpkg -e, --control archive directory
4. 提取文件
dpkg -x, --extract archive directory
5. 提取文件名
dpkg -X, -vextract archive directory
6. 显示包的控制字段(control field(s))
dpkg -f, --field archive [control-field...]
7. 显示.deb文件中所包含的tar文件
dpkg --fsys-tarfile archive
8. 显示包文件的综合信息
dpkg -I, --info archive [control-file...]

dpkg-query,查询已安装包的相关信息
1. 列出匹配的包,若不指定参数,则列出当前系统已安装的所有包(名字,版本,简要描述)
dpkg -l, --list package-name-pattern...
2. 列出某个包当前在系统中的状态
dpkg -s, --status package-name...
3. 列出与包相关的文件
dpkg -L, --listfiles package-name...
4. 从已安装的包中查找某个文件
dpkg -S, --search filename-search-pattern...
5. 显示某个包的细节信息,(信息源来自/var/lib/dpkg/available)
dpkg -p, --print-avail package-name...



参考资料:
[1]. Dpkg 常用指令操作快速参考,http://linuxtoy.org/archives/dpkg_reference.html
[2]. The Debian package management tools,http://www.debian.org/doc/FAQ/ch-pkgtools.en.html#s-dpkg

2011年4月13日星期三

一种调试内核模块的方法

1. 修改编译用的Makefile文件,增加变量EXTRA_CFLAGS
    EXTRA_CFLAGS := -g3
使得编译出的模块有用于调试的符号等信息。

2. 用objdump做一份综合模块各种信息的文件,包括二进制指令,反汇编生成的指令,还有源码。
    objdump -d -S LKM-To-Debug.ko > objdumped.txt
保存在objdumped.txt

3. 用串口连接被调试的机器,见这里

4. Kernel Oops或者Panic之后,查看从串口dump出来的信息。包括EIP,还有Code段等。利用这些信息和第2步生成的文件(objdumped.txt)进行分析,抓出异常原因,。


可参考文档:
1. Documentation/oops-tracing.txt

使用串口调试Kernel Panic

一开始,在Ubuntu环境下,尝试使用"linux-crashdump"工具集来处理。水很深,几经尝试没有成功。

1. 在VMware里边给虚拟机添加一个串口。
    Use named pipe: \\.\pipe\com_1
    This end is the server.
    The other end is an application

2. 给内核增加增加两个启动参数。
    console=ttyS0,115200 console=tty0
   使用"grub-mkconfig -o /boot/grub/grub.cfg"命令来更新GRUB2配置文件。重新启动后可以从"/proc/cmdline"看到启动参数。

3. 在PuTTY中建立一个Session,配置好"Serial line"和"Speed"项,连接即可。

4. 用快捷键"Alt+SysRq+C"或者命令"echo c > /proc/sysrqtrigger"来触发Kernel Dump,可以在PuTTY的对应的Session里边看到Dump信息。

另外,PuTTY的Session是可以记成日志的,在配置窗口左侧的"Logging"项中设置。


补充笔记:
1. 内核代码库中的相关文档。
    Documentation/oops-tracing.txt
    Documentation/serial-console.txt
    Documentation/networking/netconsole.txt

2. 如果没有指定console参数,内核就会按照VGA Card,Serial Port的顺序,直到找到第一个可作为System Console的设备。所以,一般来说,Dump信息只出现在屏幕上。

3. console参数可以写多个,输出将会在所有指定的设备上出现。

4. console参数指定的设备中,不能出现两个同类设备。如,同时指定两个串口设备作为System Console的输出就不可以。

5. console参数列表中的最后一个设备将会被用来打开"/dev/console"

6. 使用Serial Line来登录,在/etc/inittab中添加类似如下格式的信息:
    id:runlevels:action:process
如:"S1:23:respawn:/sbin/getty -L ttyS1 9600 vt100",则可以从ttyS1登录。参考"Configuring init to start getty: the /etc/inittab file"


可参考资料
1. Debugging Linux Kernel Lockup / Panic / Oops,里边有相关的内核配置选项