技铸未来

做有意义的事
posts - 6, comments - 0, trackbacks - 0, articles - 0

2011年11月23日

工作几年来,一直从事Linux内核驱动方面的开发。从接触Linux到现在,读过不少Linux方面的书籍,现把认为很不错的一部分列出来和大家分享一下。 
   
  入门类 
  一直认为,在一个系统上学习开发之前,首先需要熟悉这个系统的使用。鉴于天朝的国情,绝大部分人第一个接触的操作系统就是Windows,因此对于这绝大部分人来说,如果要学习Linux开发,学会使用这个系统都是必不可少的一个环节。 
     
  现在的Linux初学者是幸福的,随着Linux桌面环境越来越易用,入门一个新的系统是非常容易的事情。虽然命令行对于提高工作效率更加有效,但我们完全 可以把熟悉命令的过程放到日常使用中进行。无论学习什么知识,在实践中学习都是高效而且有趣的。在这个阶段,我们也未必一定需要书籍。现在很多Linux 发行版的Wiki写得都非常详细,在使用某一种发行版时找到相应的Wiki阅读查询就可以了。而且,桌面环境变化太快,关于桌面的介绍类书籍几乎都没有必 要看,这类书籍大多刚一出版就过时了。 
  那入门类书籍里哪些比较有价值呢?我比较推荐涉及的技术相对比较稳定的书。比如,Linux基本的体系结构和命令一般都是经久不变的,甚至从上古时期的Unix开始就没太多变化,这类书籍讲解的知识也是以后大幅提高我们的生产力的基础。比如《鸟哥的Linux私房菜》,比如《Unix Power Tools》(中译名是“UNIX超级工具”),或者是为Linux+认证考试准备的《Linux+ Study Guide》。当然,这一类书籍其实都不必精读,快速浏览之后作为工具书备查就可以了。 
编程类 
  类Unix系统的编程书籍里,最经典的莫过于简称为APUE的《Advanced Programming in the UNIX Environment》(中 译名是“Unix环境高级编程”),这本书被广大Unix程序员(包括Linux)捧为“圣经”。借用葛大爷的广告词:“这就像进馆子一样,一条街上,哪 家人多我进哪家”。APUE对类Unix系统的编程接口讲解的非常全面详细,对于这本书,我们不仅要精读,还应该放在案头常备。 
  但是,APUE对于Linux编程初学者似乎稍深了一点,而且很多细节在Linux中并不会用到。讲述Linux编程的书籍里,《Advanced Linux Programming》应该更加适合初学者。不要被书名中的“Advanced”吓到,书里的内容还是很容易理解的。看完这本书再看APUE应该效果会更好。 
  如果要开发GUI程序,上面两本书就无能为力了。在Linux世界里,最常用的GUI Toolkit是GTK+和QT。 
  GTK+的书籍并不多,在线文档只适合查阅,并不是一个完整的学习体系。《Foundations of GTK+ Development》是其中很不错的一本书,喜欢GTK+的开发者可以拿来作为入门书籍。 
  相对来说,QT的书籍就很丰富了,这和QT具有良好的跨平台能力有很大关系,QT的书籍并不只是写给Linux程序员看的,在Windows和MAC OSX下同样可以使用QT开发程序。比较值得一看的QT类书籍有《C++ GUI Programming with QT4》、《Foundations of QT Development》、《The Art of Building QT Applications》,这三本都比较适合QT初学者阅读。另外,《Advanced Qt Programming》会介绍到QT一些比较高级的用法,适合有一定QT基础的读者阅读。 
内核类 
  对于Linux内核或者设备驱动的开发者,最全面最直接的学习资料一定是Linux内核代码及其文档。Linux内核的发布周期很短,相关书籍的出版完全跟 不上脚步。但随着内核代码的日益庞大,学习曲线越来越陡峭,入门者又非常需要书籍来作为指导,这确实是非常矛盾的事情。所幸,很多Linux内核技术作家 也是很勤奋的,经常会更新自己的作品。就像Robert Love,以2.6内核为蓝本的《Linux Kernel Development》已经更新到第三版了。LKD是非常适合内核初学者阅读的一本好书,对它的评价可以引用陈莉君老师的译者序: 
  相对于 Daniel P. Bovet 和 Marco Cesati 的内核巨著《 Understand the Linux Kernel 》,它少了五分细节,相对于实践经典《 Linux Device Drivers 》,它多了五分说理。可以说,本书填补了 Linux 内核理论和实践之间的鸿沟,“一桥飞架南北,天堑变通途”。 
  谢谢陈老师,她的译者序帮我引出了另外要谈到的两本经典书籍,对,就是《Understanding the Linux Kernel》和《Linux Device Drivers》。对于这两本书,如果要挑它们的缺点,我只能说,内容有点老,很多知识点都需要更新了,除此之外,我要说的是,是它们把我带上了内核驱动开发这条路上来,当然,还有LKD。 
  最近,我又发现一本分析Linux内核的优秀书籍,就是《Professional Linux Kernel Architecture》。这本书我目前正在读,写得非常好,而且因为此书相对较新(只是相对,2.6.24内核在现在看来也很老了),没有看过ULK的同学可以直接看这本书。 
工具类 
  工欲善其事,必先利其器。进行Linux开发,相关工具还是需要熟练使用的。比如,GNU Tool Chain、自动构建工具、编辑器、版本控制工具等等。 
  这里有一本包罗万象的书,叫做《Handbook of Open Source Tools》,书中介绍了各种各样的开源工具,可称之为开源技术的总决式。这本书试图面面俱到,因此并不深入,粗读即可。 
  GNU Tool Chain参考Redhat的《The GNUPro Toolkit》已经足够了,如果单独把makefile拎出来,还可以参考《Managing Projects with GNU Make》。 
  自动构建工具可以参考《Autotools》。如果您准备使用cmake,推荐cjacker的《Cmake实践》。《Mastering CMake》据说是cmake的权威书籍,但一直无缘得见啊。 
  说到编辑器,在Linux里最著名的莫过于Vim和Emacs,关于这两者的背景,可以去看看《为何Emacs和Vim被称为两大神器》。我几乎没用过Emacs,曾经在当当做活动时花9块钱买了一本《学习GNU Emacs》,有这本书作为Emacs的入门我想应该够了。Vim是我经常使用的编辑器之一(另一个是Kate,最初喜欢上Kate的原因之一就是它提供了Vim编辑模式),相关的书籍有两本值得一读:《A Byte of Vim》和《Hacking Vim 7.2》,但是对于初学者,首先跟着Vim自带的vimtutor练习效果会更好。 
Linux下的版本控制工具很多,有传统的Subversion,也有现在非常流行分布式工具如Git等。Subversion可以参考这本《Version Control with Subversion》,Git可以参考《Version Control with Git》或者《Git Internals》或者《Pro Git》。 
其它 
  除了以上几个类别,还有一些书籍值得推介。 
  比如《The Art of Unix Programming》,主要介绍了Unix系统领域中的设计开发哲学、思想文化体系以及社群文化等,覆盖面非常广。书中的一些内容和《Revolution OS》有相似之处,大家可以自己印证一下。对于这本书,我们也完全可以把它当做小说或者历史书来看,可以躺在床上看,也可以瘫在沙发上看,或者像怪怪那样坐在马桶上看,总之,不必一定要端坐在书桌前。 
  《Computer Systems: A Programmer's Perspective》 很多人都推荐过,这是一本非常经典的计算机体系方面的教材。CSAPP的内容基础全面,讲解简明扼要,易于理解,仔细读完之后对理清计算机体系结构甚至是 Linux内核都非常有帮助的。虽然中文名被译为《深入理解计算机系统》(这个译名很不贴切),但相比之下,为什么会让人感觉国内的同类教材更加“深奥” 呢?也许,这就是作者功力的差距吧。 
   
  注:这里列出的书大多都可以在library.nu上下载到,注册登录之后会有搜索框,用书名搜索即可。 

posted @ 2011-11-23 23:31 99式 阅读(223) | 评论 (0)编辑 收藏

2011年10月23日

1.__name__=="__main__"
__name__是module的属性
当一个脚本一module导入其他脚本的时候,__name__==module的文件名。所以如果在脚本中使用if __name__=="__main__":那么if以后的语句便不再执行(注:每次导入module时module都会自动运行的)。
但是如果脚本独立执行那么__name__=="__main__",也就是说if以后的句子也会执行
2.math的常用函数
函数(方法)示例 说明 
 acos(x) 求x的反余弦(结果是弧度) acos(2.0)等于0.0
 asin(x) 求x的反正弦(结果是弧度) asin(0.0)等于0.0
 atan(x) 求x的反正切(结果是弧度) atan(0.0)等于0.0
 ceil(x) 为x取整,结果是不小于x的最小整数 ceil(9.2)等于10.0
   ceil(-9.8)等于-9.0
 cos(x) 求x的余弦(x是弧度) cos(0.0)等于1.0
 exp(x) 求幂函数e` exp(1.0)等于2.71828
   exp(2.0)等于7.38906
 fabs(x) 求x的绝对值 fabs(5.1)等于5.1
   fabs(-5.1)等于5.1
 floor(x) 为x取整,结果是不大于x的最大整数 floor(9.2)等于9.0
   floor(-9.8)等于-10.0
 fmod(x,y) 求x/y的余数,结果是浮点数 fmod(9.8,4.0)等于1.8
 hypot(x,y) 求直角三角的斜边长度,直边长度为x和y:Sqrt(x2-y2) hypot(3.0,4.0)等于5.0
   
 log10(x) 求x的对数(以10为底) log10(10.0)等于1.0
   log10(100.0)等于2.0
 pow(x,y) 求x的y次方(xy pow(2.7,7.0)等于128.0
   pow(9.0,0.5)等于3.0
 sin(x) 求x的正弦(x是弧度) sin(0.0)等于0.0
 sqrt(x) 求x的平方根 sqrt(900.0)等于30.0
   sqrt(9.0)等于3.0
 tan(x) 求x的正切(x是弧度) tan(0.0)等于0.0
3.关于numpy的一些
import numpy as np
A=np.matrix([[1,2,3],
                     [1,2,3,]])
A.I矩阵的逆
A.T矩阵的转置
访问矩阵中的元素
A[1,0]就是A(2,1)元素

4.关于print的小记

print "wrong_info:%s" %wrong_info.items()
%s可代表任何类型

仅是学习笔记,不代表完全正确

posted @ 2011-10-23 17:10 99式 阅读(287) | 评论 (0)编辑 收藏

2011年10月19日

差错检测和纠正 

        物理过程所引起的差错,在某些介质中通常是突发的而不是单个的。网络设计者已经研究出两种基本的策略来处理差错。一种方法是在每一个要发送的数据块上附加足够的冗余信息,使接收方能够推导出已发出的字符应该是什么。另一种方法是只加足够的冗余位,使接收方知道差错发生,但不知道是什么样的差错,然后要求接收方重新进行传输。前者的策略是使用纠错码(error-correcting   code),而后者则使用检错码(error-detecting   code)。 

1.纠错码 

        在了解纠错码之前,先了解一个基本概念:海明距离。通常一帧包括m个数据(报文)位和r个冗余位或者校验位。设整个长度为n(即n=m+r),则此长度为n的单元通常被称作n位码字(codeword)。 

        给出任意两个码字,如10001001和10110001,可以确定它们有多少个对应位不同。在此例中有3位不同。为了确定有多少位不同,只须对两个码字做异或运算,然后计算结果中1的个数。两个码字中不同位的个数,称为海明距离(Hamming   Distance)。其重要性在于,假如两个码字具有海明距离d,则需要d个位差错才能将其中一个码字转换成另一个。 

        一种编码的校验和纠错能力取决于它的海明距离。为检测出d比特错,需要使用d+1的编码;因为d个单比特错决不可能将一个有效的码字转变成另一个有效的码字。当接收方看到无效的码字,它纠能明白发生传输错误。同样,为了纠正d比特错,必须使用距离为2d+1的编码,这是因为有效码字的距离远到即使发生d个变化,这个发生了变化的码字仍然比其它码字都接近原始码字。作为纠错码的一个简单例子,考虑如下只有4个有效码字的代码: 

        0000000000、0000011111、1111100000和1111111111 

        这种代码的距离为5,也就是说,它能纠正双比特错。假如码字0000000111到达后,接收方知道原始码字应该为0000011111。但是,如果出现了三位错,而将0000000000变成了0000000111,则差错将不能正确地纠正。 

2.检错码 

        检错码有时也用于数据传输。例如,当信道为单工方式,无法要求重传的情况下,大多数采用检错码加重传的方式。 

       
假设信道的出错是孤立的,信道的误码率为每位10-6。数据块的大小为100位。为1000位的数据块纠错,需要10个校验位;1兆的数据位将需要10000个校验位。若只需要检测一个数据块的一位错误,每块一个奇偶位就够了。每传送1000个数据块就需要额外传送一个数据块。错误检错+重传方式的整个开销,仅仅是每兆数据只有2001位,而海明码为10000位。 

        
假若在一个块上只加一个奇偶位,那么块的长的突发错误的检测率就会很糟糕,能够检测到差错的概率只有0.5,这是难以接受的。改进的措施可以采取将每个数据块组成n位宽k行高的长方形矩阵进行发送。对每一列的奇偶位分别进行计算,附加在矩阵上,作为矩阵的最后一行,然后按行进行发送。当块到达后,接收方检测所有的奇偶位。如果其中任何一个出错了,就需要重新传送整个块。 

        这种方法能够检测到单个程度为n的突发错误,因为每一列只有一位改变了。然而如果第一位变反,最后一位变反,且所有其它位都正确,则长度为n+1的突发差错将不会被检测到。假如一个块被一个长的突发差错或者短的突发差错所破坏,n列中的每一列的奇偶值碰巧正确的概率为0.5,那么这个出错块被接受的概率不应该是2-n。 

        虽然上述方法有时已经足够了,但是在实践中,另一种方法正在被广泛使用,即多项式编码(也叫循环冗余码,或CRC码)。多项式编码是基于将位串看成是系数为0或1的多项式,一个k位帧可以看成是从Xk-1到X0的k-1次多项式的系数序列。如果采用多项式编码的方式,发送方和接收方必须事先商定一个生成多项式G(x),生成多项式的高位和低位必须是1。要计算m位的帧M(x)的校验和,生成多项式必须比该多项式短。基本思想是:将校验和加在帧的末尾,使这个带校验和的帧的多项式能被G(x)除尽。当接收方收到带校验和的帧时,用G(x)去除它,如果有余数,则传输出错。 

        计算校验和的算法如下: 

        ①.设G(x)为r阶,在帧的末尾附加r个零,使帧为m+r位,则相应的多项式是XrM(x)。 

        ②.按模2除法用对应于G(x)的位串去除对应于XrM(x)的位串。 

        ③.按模2减法从对应于XrM(x)的位串中减去余数。结果就是要传送带校验和的帧,叫多项式T(x)。 

        以下三个多项式已经成为国际标准: 

        crc   -12     =   x^12+x^11+x^3+x^2+x+1 
    crc   -16     =   x^16+x^15+x^2+1 
    crc   -ccitt   =   x^16+x^12+x^5+1   

        这三个多项式都包含了x+1作为基本因子。当字符串长度为6位时,使用CRC-12;其余两个多项式用在字符串长度为8位的情况下。一个16位的校验和,如CRC-16或CRC-CCITT,可以捕捉到所有的单位差错和双位差错,所有奇数位数的差错,所有长度小于或等于16位的突发差错,99.997%的长度为17位的突发差错,以及99.998%的长度为18位或多于18位的突发差错。 

        虽然计算校验和的计算方法看起来相当复杂,但Peterson和Brown已经给出了一种简单的移位寄存器电路来进行计算,并用硬件来完成对校验和的校验。在实际应用中,几乎都在使用此硬件。 

posted @ 2011-10-19 21:09 99式 阅读(1954) | 评论 (0)编辑 收藏

2011年10月18日

看了opencv论坛的配置贴,很乱很麻烦。
想了想其实很简单。
1、先下载opencv(各种途径)
2、打开vs2010,如此贴(http://blog.sina.com.cn/s/blog_772645ff0100rxfh.html)配置你的VC++driectories。其中include directories是你安装的opencv目录中include文件中那群.h和.hpp所在的文件夹(这一点很重要,我的include文件下opencv文件下才包含这下文件)。lib directories类同。
3、新建项目在vs2010 目录中project|"你的项目名" properties 中菜单栏中选Linker|input  在additionaldepndecies中添加你需要的lib:
cxcore210.lib
cv210.lib
ml210.lib
highgui210.lib
cvaux210.lib(文件名一定要和你的安装的opencv中lib文件夹中lib名一致)
4、开始coding

posted @ 2011-10-18 23:09 99式 阅读(500) | 评论 (0)编辑 收藏

2011年8月9日

首次写的python小游戏,两个小蛇互相摇尾巴
from sys import exit
import pygame
from pygame.locals import *
class snake(object):
    def __init__(self,x,y):
        self.pos=[x/2,y-20]
        self.body=[]
        self.direct=0
        self.len=6
        self.alive=True
        self.vflag=False
        self.hflag=True
        self.speedflag=True
        self.speed=1
    def control1 (self,event):
        if event.key == K_LEFT and self.hflag:
            self.direct = 270
            self.hflag = False
            self.vflag = True        
        if event.key == K_RIGHT and self.hflag:
            self.direct = 90
            self.hflag = False
            self.vflag = True
        if event.key == K_UP and self.vflag:
            self.direct = 0
            self.vflag = False
            self.hflag = True
            print "a1"
        if event.key == K_DOWN and self.vflag:
            self.direct = 180
            self.vflag = False
            self.hflag = True
            print "a2"
    def control2 (self,event):
        if event.key == K_a and self.hflag:
            self.direct = 270
            self.hflag = False
            self.vflag = True        
        if event.key == K_d and self.hflag:
            self.direct = 90
            self.hflag = False
            self.vflag = True
        if event.key == K_w and self.vflag:
            self.direct = 0
            self.vflag = False
            self.hflag = True
        if event.key == K_s and self.vflag:
            self.direct = 180
            self.vflag = False
            self.hflag = True
    def update(self,size):
        self.body.insert(0,list(self.pos))
        self.body=self.body[0:self.len]          
        if self.direct == 0:
            self.pos[1]-=10
        if self.direct == 180:
            self.pos[1]+=10
        if self.direct == 90:
            self.pos[0] +=10
        if self.direct == 270:
            self.pos[0] -=10
        if self.pos in self.body:
            self.alive=False
            print "s1"
        if self.pos[0] not in range(size[0]):
            self.alive=False
            print "s2"
        if self.pos[1] not in range(size[1]):
            self.alive=False
            print "s3"
    def draw1(self,screen):
        for b in self.body :
            screen.fill( (255,0,0) , (b[0],b[1],10,10) )
        if len(self.body)==self.len:
            screen.fill( (0,255,0) , (self.body[-1][0],self.body[-1][1],10,10) )
        
    def draw2(self,screen):
        for b in self.body :
            screen.fill( (255,255,0) , (b[0],b[1],10,10) )
        if len(self.body)==self.len:
            screen.fill( (0,255,255) , (self.body[-1][0],self.body[-1][1],10,10) )
def main():
    pygame.init()
    SCREEN_SIZE = (640,480)
    screen =pygame.display.set_mode(SCREEN_SIZE,0,32)
    p1=snake( SCREEN_SIZE[0] , SCREEN_SIZE[1] )
    p2=snake(0,SCREEN_SIZE[1])
    time=0
    p1.speed=10
    pause=pygame.event.wait()
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
                return
            if event.type == KEYDOWN:
                p1.control1(event)
                p2.control2(event)
                if event.key == K_ESCAPE:
                    little = pygame.event.wait()
                    while little.type != KEYDOWN :
                        little = pygame.event.wait()
        if time%p1.speed==0:
            p1.update( SCREEN_SIZE )
        if time%p2.speed==0:
            p2.update( SCREEN_SIZE )
        if p1.body[0] == p2.body[-1]:
            p2.alive=False
        if p2.body[0] == p1.body[-1]:
            p1.alive=False
        if not p1.alive:
            print "p1 died"
            p1 = snake( SCREEN_SIZE[0] , SCREEN_SIZE[1] )
        if not p2.alive:
            print "p2 died"
            p2=snake(0,SCREEN_SIZE[1])
        screen.fill((255,255,255))#清空页面
        p1.draw1( screen )
        p2.draw2( screen )
        pygame.display.flip()
        time += 1
        pygame.time.wait(100)
if __name__== "__main__":
    main()
        

posted @ 2011-08-09 19:50 99式 阅读(211) | 评论 (0)编辑 收藏

2011年8月6日

总体说vim的配置文件有两个

一个是/etc/vimrc下的通用配置文件

另一个是~/.vimrc 用户配置文件,通常进行对用户配置文件操作

另外还需添加~/.vim文件夹用于相应配置

posted @ 2011-08-06 16:46 99式 阅读(125) | 评论 (0)编辑 收藏