为什么你应该从现在就开始延时摄影

如果你是初学者并且喜欢摄影

大多数对于初学者的建议都是,对一个主题拍摄100张照片,籍此熟悉器材并建立直觉.对于喜欢这种机器的人们来说,这个过程就算有趣,也显得单调.并且由于人们(也可能只有我一个人)天生的懒惰,把每一种技术,每一种场景都试一遍需要巨大的精力

最近boss讲道,可能初学者直接进入实战当中,才是进步最快的方式.这跟我们的直觉也相符:经验增加最快的方式肯定是实践

我们知道,延时摄影因为拍摄时间跨度长,操作者对摄影中最为关键的主题–光线,也会有充分的认识.这也是避免黑天鹅的很有效的方法

由于时间跨度长,大多数操作都需要手动设定.这就要求操作者对每个参数的准确含义都有清晰的认识.另外一方面是器材,定时拍摄起码需要使用到遥控器,通常时候用不到.如果不是专业的摄影师,RAW文件格式通常情况下认识不需要,但是这里因为光线变化多的关系,为了后期制作方便,完全有必要使用

延时拍摄有助于促进我们使用先进的器材和技术,比如中灰滤镜和HDR技术.后期播放的时候连续播放,就要求照片有统一的光线基调,也有助于提高后期制作软件的使用,并且主角一直是摄影的主角–光线

Posted in 技术 | Leave a comment

怀念张婉琴老师

2003年我读初三第二学期,正是中考最关键的时候.我们那个班属于诡异中的诡异,一年内换了三任语文老师

不过老实说,语文这个东西,突击的难度还是比较大的.中国的应试教育虽然糟糕,句子结构分析和作文里的遣词造句还是能看出来一个人的语文修养的

所以考试临近,还有三个月的时候,她组织我们在课间看电影.哈利波特和泰坦尼克号都是在那个时候第一次看的.那时我很不喜欢哈利波特这个电影–相信我同学里面很多人都跟我一样的感觉.一方面极少看外国电影,看见外国人不习惯,另一方面,对魔法这种类型的电影也表示不能理解.第二个电影还好,不过rose脱衣服的那个镜头把其他部分的吸引力完全掩盖了,那时虽然已看过类似的小电影或者文字,堂而皇之的跟同学一起,还是有一种特别慌张的感觉

她解释说,哈利波特是国外特别流行的电影.我们都特别不以为然.甚至觉得,你是大人了,看脱衣服的电影可以,不用给我们看呐

虽然是在小乡村,还是能够看得出她的特别,她老公是我们学校的音乐老师,我上过他的课.我现在还记得我们在外面读书,他们牵手走过的画面

此后一度不记得她了.多年以后的现在,我经历并度过了最艰难的黑天鹅危机以后.却又想起了她,我觉得她是正确的,而我才明白

Posted in 扯淡 | Leave a comment

KD树

很早就看到关于这个数据结构的内容,只是一直不能在直觉上理解这个查询的算法,所以没有写出来

我用两维的情况来举例,即平面.一个完成的KD树是一个平衡二叉树,每一个非叶子节点代表平面中的一个超平面,二维超平面即直线.也就是说,用直线将平面分割成小的矩形.图在这里:http://en.wikipedia.org/wiki/File:Kdtree_2d.svg

查找的时候从根开始,计算距离,把当前点(根)做为最佳,接着计算左子树,发现左子树更接近,最佳变为左子树,然后计算左子树的子树,距离都比左子树远,则最佳点仍然是左子树

关键的地方在于,如果查找的点和当前最佳(即左子树)形成的圆(查找点为圆心,当前最佳为边)不与其父节点(此处为根)划分的超平面(直线)相交,则右子树中不可能存在比当前最佳更近的点,也就不需要查询右子树了

我的理解如下:如果查找点和最佳点与父节点的超平面相交,则说明另外一面可能存在更近的点,所以需要再去查找最佳点.如果不相交,则说明另外一面所有点都比本最佳点远,则不需要查找.图在这里:http://en.wikipedia.org/wiki/File:KDTree-animation.gif

其他相关的复杂度等内容在维基说的非常详细.KD树适用于维数比较低的数据,即如果有K维的数据,点的数目N应该是N>>K^2.如果是高维数据,则应该使用接近最近邻居(approximate nearest-neighbour methods)算法,下次说

Posted in 技术 | 1 Comment

KAD网络基本原理

KAD是一个非集中式的p2p计算机网络,它使用UDP进行通迅.

网络中的每个节点被赋于一个160bit长的ID,全球唯一.(冲突的情况会在导引的过程中解决)每两个节点之间的距离由两个ID的异或算法决定,两个ID异或的结果是一个二进制数字.这表明,两个ID之间高位不相同对两者的距离有重大影响

每个节点都包含一个”邻居”表,该表有160项,每项表示跟自己的ID有多少位前缀相同,同时又跟自己距离最近的那些ID.这使得它们可以迅速地找到任意一个ID的节点.(相当于一个二叉树)

资源存储在跟资源本身ID最接近的那些用户身上.这说明KAD是一个合作网络.这也是所谓”吸血驴”的基础

加入网络需要先计算自己的ID,这是一个随机数,然后找到一个在KAD网络中的用户,并递归地查询跟自己最近的那些邻居.填满160个邻居表.这个过程也可以用来检测是否有ID冲突,这其实概率很小

Posted in 技术 | 1 Comment

netfilter框架

本文中使用的工具为lxr,只注重整个大的流程,不关注其中的细节和精确的原理.内核版本为2.6.38.5

netfilter框架从NF_HOOK这个宏进入,做一系列的工作之后返回.这里选择ip_input.c:443中的   NF_HOOK(NFPROTO_IPV4,NF_INET_PRE_ROUTING,skb,dev,NULL,ip_rcv_finish);开始分析.NF_HOOK中第一个参数为协议类型,目前支持的协议有6个,从netfilter.h:55开始,第二个参数为hook点,目前支持5个值,从netfilter.h:46开始,第三个参数为通过的数据包,第四个参数为进入设备,第五个参数为出口设备,因为选择ip_input位置,所以出口设备为空,第六个参数为回调函数,这里是ip_rcv_finish

NF_HOOK直接调用NF_HOOK_THRESH,后面加了一个参数值是INT_MIN,最小的整数值.这个数字的用处后面会看到.NF_HOOK_THRESH又直接调用nf_hook_thresh,返回值如果为1,则调用回调函数,本例中就是上面的ip_rcv_finish.如果不关注nf_hook_thresh中的调试功能的四行代码,这个函数又直接调用了nf_hook_slow,再不出现真正的函数我就要烦了

171 elem = &nf_hooks[pf][hook];
172 next_hook:
173 verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,
174 outdev, &elem, okfn, hook_thresh);
175 if (verdict == NF_ACCEPT || verdict == NF_STOP) {
176 ret = 1;
177 } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
178 kfree_skb(skb);
179 ret = -(verdict >> NF_VERDICT_BITS);
180 if (ret == 0)
181 ret = -EPERM;
182 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
183 if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
184 verdict >> NF_VERDICT_BITS))
185 goto next_hook;
186 }

跳过nf_hook_slow函数中锁的那几行,可以看到这个函数的功能是,根据pf和hook的值(上面的协议类型和hook点值,各种可能的组合为5*6=30种)从nf_hooks中得到一个链表.然后调用nf_iterate函数执行函数,根据返回值操作,如果返回NF_ACCEPT或者NF_STOP,都返回1,即NF_HOOK最外层的回调函数需要调用.如果返回值为NF_QUEUE,则调用nf_queue函数,如果失败,则返回再次调用nf_iterate.这里关注流程,不进去看nf_queue函数,进入nf_iterate

nf_iterate逐个调用链表中的函数,并根据返回值做出不同操作,这里的hook_thresh就是刚才的MIN_INT,相当于调用门槛,这里用最小值即每个函数都调用,别处可以使用较大的门槛

nf_hooks是一个list_head结构,这里可以看出它其实是一个nf_hook_ops结构,其成员用pf,hooknum和priority,以及回调函数hook.这就是整个调用的流程

插入数据的方法有两种,一种是直接插入一个nf_hook_ops,另一种是插入一个表xt_table,内核中只有极少的部分直接使用,用法特别简单,可以参考/net/decnet/netfilter/dn_rtmsg.c.剩下的模块都使用了表,可见直接使用nf_hook_ops把模块插入到nf_hooks中是一个不太礼貌的行为,而且使用表可以和用户态的iptables很方便地通信,是值得鼓励的行为

使用表的方式的模块很多,包括iptable_filter.c,arptable_filter.c,iptable_security.c,iptable_mangle.c和iptable_raw.c.这里分析最常用的iptable_filter.c,文件只有100多行,只分析netfilter相关的内容,在iptable_filter_init中只有一个需要看的函数xt_hook_link.它的参数是一个xt_table结构体和一个回调函数iptable_filter_hook,这个函数只做了检查工作,具体工作交给了ipt_do_table函数,所有使用表的模块都可以使用这个函数.xt_table结构体中pf还是pf,priority还是priority,hooknum变成了valid_hooks,可见表可以在多个hook点上作用.还有一个private,是xt_table_info结构体,应该是存放具体的表格信息.进去看注册函数xt_hook_link

这个函数用汉明距离算了hooks的总数,然后申请了足够多的nf_hook_ops,然后注册.这些nf_hook_ops回调函数的参数都是相同的,只是位置不同,在回调的时候都调用相同的iptable_filter_hook,然后在ipt_do_table中根据挂载点不同可以进行不同的操作,表的注册过程到此结束

其实xt_table更强大的功能在于可以和用户态程序(iptables)方便地通信,而且它的match,target方法也使得添加规则的方法无比灵活,多个match和target可以组合出很多规则,非常方便(比较遗憾的是,它的功能还是不太能满足我的需求,要不然也不用看这个了…)

我们来看xt_limit.c中的match相关的内容,target是类似的.

这个模块注释中讲使用了simple token bucket filter算法,有兴趣的时候可以参考维基,这里只分析netfilter部分,这样以来其实只需要关注一下xt_register_match就可以了.另外它的xt_match结构中的match叫做limit_mt,这个函数以sk_buff指针为参数,即通过的包,和另外一个xt_action_param,这个参数是各个模块使用的,里面定义的一个matchinfo和targetinfo,用来保存私自数据.其他的参数由table框架外的函数填写,是对包的一些重要信息的描述.xt_register_match出奇地简单,它把match插入到xt这个全局变量里就完事了

这样做非常合理,正是策略机制分离的设计方法的体现,match和target只是提供机制,那么保存在这个链表里面就足够了.至于具体的策略,则由上层的iptables添加.支持iptables功能的数据在xt_table_info这个结构里,它是xt_table结构的private成员指向的内容,但在刚才iptable_filter.c中初始化中并没有private的信息,回头再去看看这个人有100多行的文件

在xt_hook_link之前还有一个函数,register_pernet_subsys,这个函数的功能是注册proc子系统,在用户态/proc部分.但它有一个参数叫iptable_filter_net_ops,只是两个初始化和既出函数,初始化函数为iptable_filter_net_init,跟xt_table_info相关的工作可能就是在这个函数中完成的.它先根据packet_filter结构申请了一个ipt_replace结构,然后又根据ipt_replace注册了一个table.然后释放了ipt_replace,工作完成

ipt_alloc_initial_table参数是一个xt_table,返回一个ipt_replace,这不是一个函数,而是一个宏,所以宏里面直接使用了参数名称,在”函数”表面看来没有使用参数.首先申请了一个结构体,里面又包含三个结构体,分别是ipt_replace,ipt_standard,ipt_error.然后把参数里的name复制到repl的name中.然后是一系列的是初始化,然后返回.不过…返回的是ipt_replace结构,这里其实是上面说的三个.原因在文件上面的注释里…也就是说ipt_standard和ipt_error都做为ipt_replace中最后一个参数entries来使用了.然后进入ipt_register_table函数

ipt_register_table为每个cpu都申请了一个xt_table_info,呃,原因不明.然后进入translate_table函数,然后把repl中的信息复制到xt_table_info中.并做了一系列的检查,最后,把信息复制到每个cpu中.netfilter在软中断中调用,虽然同时只能在一个cpu上执行,但每个cpu都有自己的一份数据,所以里面的数字设置要注意,总的数目应该是设置数目和cpu数量的乘积(以上想法都是猜测的)

然后调用xt_register_table,这个函数将private赋值为xt_table_info.到这里,match和target的注册都分析完毕.还剩最后一个,添加规则.

ip_tables.c文件的初始化函数为ip_tables_init.它注册了内置的规则.然后设置添加了一个setsockopt接口选项,提供一个回调函数,可见,iptables是调用setsockopt来实现规则向内核传递的.那么需要分析的只有一个函数do_ipt_set_ctl

do_ipt_set_ctl函数接收用户态的数据之后,把它们并入到内核的规则中去.首先检查了超级用户权限.之后一个switch到两个函数,分别是do_replace替换原来的规则和do_add_counters添加新的规则.

先看只添加的内容,do_add_counters函数,用户态传入的数据是一个xt_counters_info结构,其中有表的名字name,规则的数目counters,和最后的规则xt_counters,是一个零数组.xt_counters包含两个成员,pcnt和bcnt,分别是包的个数和比特大小.然后使用vmalloc申请内存,这个函数可以申请大块内存,然后才拷贝真正的数据.根据名称从寻找对应表,如果不存在就返回错误,因为表总共只有数个,这里用线性查找.添加了entry的计数和比特数目,do_replace是类似的工作原理

ipt_do_table函数先做了一些准备工作,把一些必须数据计算出来,然后根据pf和hooknum寻找match,找到之后执行函数,并根据结果来决定是否要执行相应的target

Posted in 技术 | 1 Comment

软弱

有个姑娘给我讲故事说,为什么当初跟男朋友分手.因为两人有一次有一个特别严重的矛盾,对方没有那么理智地去理性解决,反而做出一些特别幼稚的事情.你越是退后,他却反而变本加厉了.最后只能结束

我相信每个人都有这样的时候,或者是性格的限制,毕竟世界上顽强的人是少数.如同人们痛苦的时候越哭越想哭了,因为陷入那种情绪里,反而心理上觉得舒服.他又何尝不知道那样的幼稚.我跟她说,既是如此,那个时候,谁,什么,能让他醍醐灌顶如梦方醒呢.方式肯定有,只是通常意识不到而已,这也就是刻意练习的重要性

小时候一段时间拿了一个爸爸的刮胡刀片玩,特别锋利,那时理解大约就是削铁如泥了.后来就不停地有手掌到处不明真相的受伤.直到有一天,我意识到是这个刀片的原因,马上扔掉,后来就再也没有那样痛苦了.那时可能想不到,应该做个刀鞘才是

Posted in 扯淡 | 4 Comments

不知道为什么,这次回家印象非常深刻,感觉家乡变化很大,或许是前些时候回去没有去多多看吧

初一的时候去黄河边上,比四五年前去时变化了许多,原先广阔的河床现在都被石头坝隔开,过得几年大约就可以养鱼种地了

我是学计算机的,通常都宽慰初学者:这个东西其实也很简单,大约比摇控器复杂那么一点点,你可以随便按,反正也按不坏

又一日,给别人拍照要用他家的打印机打印出来.我之前也没操作过这个玩意,鉴于他们家之前只使用基础的复印功能,我还是觉得应该我去试.不料,连接上以后刚打开电脑打印机开始走纸,走到中央又停住了.然后连接失败,因为没有驱动.又没有网络,所以只能暂时歇着了

我去手机里面查看卡纸了应该怎么办,那边已经开始操作,关了打印机,强行要把纸抽出来.后来留一小段在机器里,取了摄子,拿出来了.我才在网络上找到,讲不能抽纸出来,打印机不具备这样的部件,应该顺着打印机出来,浪费一张纸

再开的时候就不能用了,我解释说,应该是它走到中间的一个过程卡住了,现在又没了纸,不能继续下去.只能找到设置方法强制重新启动了,说明书最后还是没找到.恰好他家第二天要连接网络,我说,那第二天吧,下载了驱动程序,就能连上重启了

出来的时候天已经黑了,幸好还有路灯,一阵风吹来感觉好冷

Posted in 扯淡 | Leave a comment

具体数学第一章

本章是本书的开篇,主要讲了最基本的一个功能:递归. 列举了三个例子,第一个是汉诺塔,这个计算机专业的同学都非常熟悉;第二个是平面上直线相交问题;第三个问题是约瑟夫问题

可能由于是第一章的缘故,三个问题难度都不大,包括后 面的习题,热身,练习,考试三类题目都不是很难.但却给了我两个非常重要的启示,从某个角度去接近这个传说中的人

第一点是,解决问题以后,求解更通用的问题.书中的三个示例在练习题中都出现了”加强”版.当然最后一个问题示例中讲解得更深入,习题中的问题反而显得简单了

第二点,追求极致.很多讲算法的书都会将本书列为参考 ,即使没看过,也从一定程度上了解这本书的特点.最后一个示例中,作者很轻松地指出,递归的本质是数的进制.或者说这两者本质上是等价的,这是本章的核心

研究性的问题难度真的非常高,普通的同学知道一下就可以了.另外我听说,TAOCP第一小节的研究性题目就是费马大定理…

Posted in 数学 | 2 Comments

2012年读书计划

总是去看一些乱七八糟的书,明年少浪费些时间。
如下:

1.code complete
2.concrete mathematics
3.psychology and life
4.the elements of statistical learning
5.多处理器编程的艺术
6.the art of R programming lauguage
7.out of control:the new biology of machines,social systems,and the economic world
8.artificial intelligence:a modern approach
9.the big bang theory script
10.美国纽约摄影学院摄影教材

Posted in 评论 | 1 Comment

精确控制

早上生了一不大不小的事件,缘起是上月交房租,我把整体的钱交给了房东,其他俩人付钱给我.记忆里,我认为有个姑娘没有给我.我没有说,一方面可能有羞于谈钱的意思,另一方面,还有另外一个小原因.也没向她提.今天一个小事情,我突然想起,于是谁也记不得清楚了

姑娘也不是难处之人,当下把钱给我了,少不了一番讨论

我终于明白,什么叫谈钱伤感情.先前我很惊讶于一些朋友理财很仔细,现在明白,其实是很有用的

我从技术角度分析一下这个事情

每个人的记忆都不是那么靠谱,甚至在合适的情况下,即使你非常确信,你的记忆也可能是和事实相悖的.所以这事儿要认真起来,基本也没什么结果

网上的电子消费全部都有详细的记录,所以这部分要兑起来是比较容易的.网下的没有,而且大部分人意识里花掉的钱比真正花掉的都少了很多.为了避免这种傻逼事件再次发生,我觉得有必要取样一下钱包里钱的数目,每隔两三天来一次,基本上想恢复就很容易.要是能详细记录每笔钱的去处那就更好了

以前有个报告说,非现金的消费,比如刷卡之类,会让你更容易地花钱.这事儿也不止这方面,比如情书,如果发的电子邮件,那全选删除就相当容易.还有一个说小额的钱更容易被花,鉴于物价飞涨,这条现在意义已经不是那么大了.所以如果每天晚上都记录一下钱包里钱的数目和卡里的数目,绝对有助于省下不小的一笔钱

Posted in 扯淡 | Leave a comment