shell中通过set builtin操作positional parameter

最近在调试ubuntu 14.04上的openvswitch服务时,发现openvswitch在upstart里的脚本实现频繁用到了set这样一个shell builtin,代码写的不是很好理解,后来经过查询shell相关文档,终于理解了通过set这个builtin来操作位置变量确实是一个很不错的办法。 bash的info文档中专门有一章节来介绍The Set Builtin,并且由于builtin is so complicated that it deserves its own section,但从本文的角度来看,我们认为set就是用来操作位置变量的,以下用一个简单的示例,就可以很容易的给出set的妙用了。 set -- # --这个特殊的用法来清空位置变量,即用$@来访问位置变量将得到空,除了--,set还有其他很多用法,具体可以查看shell的info文档 set "$@" ls # 用ls来初始化位置变量,ls将被赋值给$1 set "$@" -l # 将$@展开后,与-l一起重新赋值给位置变量,使得ls被赋值给$1,-l给赋值给$@ $@ # 展开位置变量,并执行,等同于执行ls -l命令 从上面的代码示例可以看出,set可以将其后的一串参数赋值给位置变量,从而方便对命令行扩充,支持更好的扩展性,并且由于@这个位置变量全集的通用性,使得在脚本嵌套时,可以方便在被执行的脚本中,对原调用脚本传过来的参数进行进一步的编辑,从而实现更为复杂的应用,比如上述openvswitch的upstart脚本,就在这点上大做了文章。 从这点感觉,bash设计的还是很精妙的,工作中大多数采用C编程,对于shell脚本的编程实践较少,后续需要继续掌握这些细节和强大之处:)

August 27, 2015 · 1 min · fortitude.zhang

Linux普通时钟与高精度时钟

对于X86 PC来说,主板上会有一个用电池驱动的里存在的以较小hz(如200)这样的interrupt(即tick interrupt),形成以1/hz为单位的jiffes,精度约在ms上的时钟,无法满足高精度计时(ns级)的需要(计时、ntp同步)等 。 于是,通过其他芯片来触发高精度中断,成为linux os提供高精度时间源的一个可能的选择。 对于linux系统,可能过如下命令查看可用的时间源以及当前活跃的时间源: cat /sys/devices/system/clocksource/clocksource0/available_clocksource cat /sys/devices/system/clocksource/clocksource0/current_clocksource 目前在x86架构上使用较多的为tsc这个由x86 cpu内部以cycle计算提供的一个计数器( TSC)来实现的由中断触发的时间源,可以以clock_event_device的行式来触发linux中断执行,从而驱动linux的高精度计时功能。

June 27, 2015 · 1 min · fortitude.zhang

谈谈Linux下的时间机制

最近同事在解决一个时区问题时花费了较多时间,但仍是一头雾水,通过查询Linux相关的文档,我给出了他一些修改建议,经过验证后问题得以修复,事后我总结来看,主要是该同事对于Linux下的时间机制的理解不够深入,因此这里我将相关的知识给记录下来,以解释相关的疑惑。 Linux下目前有三种主要的时钟,其名称及作用如下: 硬件时钟 此时钟一般由主板上的单独电子器件提供,它与CPU核心是独立的运行的,往往在电脑关机时仍能继续运行(想想我们的PC在装机重启后,时间仍然还保持着正确性就是因为这么个东西存在)。 此时钟还有一些其他名称,如RTC(实时时钟)、BIOS时钟或CMOS时钟,此时钟可以通过hwclock这样的小工具来设置。 需要注意的是,硬件时钟中是不感知时区的,其硬件实现记录了个初始值(如我司设备经常采用的1970.1.1等),然后用户可以通过hwclock写入一个时间来更新它,我们可以认为它是一个有初始值的计数器,用户可以更新当前的值,之后它将按照其计时精度来更新其值,供系统通过硬件接口读取。 系统时钟 此时钟是由Linux内核所维护的一个软件时钟,由时钟中断触发更新,其时间是相对于1970.1.1-00:00:00 UTC这个时间的秒数(UTC与GMT即格林威治时间意义相同,为世界标准时间),为方便这里的讲述,我们可以假定我们在格林威治这个地方讨论时间,这样我们可以先把时区放到一边不管了。 在Linux启动后,系统启动脚本(不管是sysvinit还是systemd都将有这样的处理)将通过hwclock读取硬件时钟,并将时间设置到内核中,此后用户获取时间均通过内核获取。 单调时钟 在Linux系统上,用户可以通过date命令更新系统时间,从而导致系统时钟出现跳变,这对于一些涉及到对调度单元(如协程)运行时间来记时以便切出去让其他进程执行的程序来说则会产生计时不准的问题,为此,Linux上支持了一个所谓的单调时钟的接口,此接口除支持单调时钟外,还支持对于系统时钟的获取,此接口属于较新的POSIX标准,如果Linux版本较老的话,可能将无法支持 此接口的定义如下: int clock_gettime(clockid_t clk_id, struct timespec *tp); // 采用CLOCK_MONOTONIC这个clk id可以获取到单调时钟 上面讨论时,我刻意互略了关于时区的处理,为简单起见,我们这里可以认为Linux内核是不感知时区的(实际上由于种种原因比如VFAT文件系统的时间戳处理就需要内核需要感知到时区)。 在Linux下,由于大量程序均需要依赖于glibc,因此glibc会读取TZ这个环境变量来设置时区,下面是一些C库函数的简单介绍: struct tm *gmtime(const time_t *timep); // 获取UTC时间,也就是说怎么改TZ变量或者通过tzset更改时区都不会影响此值 struct tm *localtime(const time_t *timep); // 获取本地时间,更改TZ变量或者通过tzset更改时区都会影响此值 当然当于时区还需要补充一点的是,环境变量这个东西只影响所属的进程,在子进程中修改并不会影响父进程,libc.so甚至提供了一个全局变量用来保存当前进程的时区设置(注意,虽然libc.so为动态库,但其在mmap映射是private的,所以会导致其中定义的全局变量每个进程都复制了一份),如果修改的话,需要通过signal类似的IPC机制通知相关进程予以刷新,这也是我同事改时区反复出问题的一个原因。 从一个编程者的角度来看,如果是涉及到对调度单元(如协程)运行时间记时的话,要尽可能采用单调时钟,下面是syslog-ng项目所采用的异步io库ivykis关于时间处理的代码片段,可以看出,它将尽可能去使用单调时钟或者clock_gettime接口,在最后才尝试使用gettimeofday来获取时间。 #ifdef HAVE_CLOCK_GETTIME static int clock_source; #endif void iv_time_get(struct timespec *time) { struct timeval tv; #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC_FAST) if (clock_source < 1) { if (clock_gettime(CLOCK_MONOTONIC_FAST, time) >= 0) return; clock_source = 1; } #endif #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC) if (clock_source < 2) { if (clock_gettime(CLOCK_MONOTONIC, time) >= 0) return; clock_source = 2; } #endif #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_REALTIME) if (clock_source < 3) { if (clock_gettime(CLOCK_REALTIME, time) >= 0) return; clock_source = 3; } #endif gettimeofday(&tv, NULL); time->tv_sec = tv.tv_sec; time->tv_nsec = 1000L * tv.tv_usec; }

January 31, 2015 · 1 min · fortitude.zhang

精神自由

昨晚晚饭时喝了一杯咖啡,于是在夜半时一如往常一样的失眠了,而关于自己此生到底要追求什么这样一个问题,其实在我心里已经盘旋了很久,于是借着昨晚的时间,我好好思考了这个问题,而结果既出于意料之外,又在意料之中,仔细推敲来,我其实一直所追求的是一种自由,但这种自由并非是消费的自由,也并非旅行的自由,虽然这种自由也建构在金钱的基础之上,但这种自由则是思考的自由,工作方式的自由,睡眠的自由,读书的自由,写作的自由等等,而如果要从这些这些自由中抽象出共性出来,那就是精神的自由,或者说是精神层面的自由。 今年是二零一五年,也是我进入三十岁奔向四十岁的关键一年,对我来说,工作、结婚、生子、逐渐年迈的父母、偿还房贷等等事务,都会成为我要面对的现实问题,而我能拿出来安慰自己的,则是我相信自己还能够抽出额外的时间,进行思考、阅读甚至这里的写作这样片刻属于我的时间,而我相信我所追求的,就是我能够在这些事务与自己的内心世界之间寻找到一种平衡,我能够坚守这这块属于我的土地,但却又能维持好前述种种。 从目前来看,实现这种自由的前提很世俗,就是资金,但相比财务自由来说,我的要求却低的很,或许是因为成长于农村的原因,我生活并不奢华,也不想追求奢华,于我而言,我只需要简单而基本的生活,于是我有理由相信自己实现这个过程较为简单,它应该是两部分,首先我可以拥有一个覆盖日常生活开支的固定收入来源,比方说一套用于出租的房产或者其他较为稳健的理财产品,之后是我将从事相对灵活自由的工作,像我这样的职业,在互联网这样的时代,想做自由职业者应该容易的多;通过这两部分的结合,我希望再经过十年,也即我四十岁的时候,我能够实现自己这里所谈到的精神自由的资金基础。 想清楚自己追求之后,对于我而言,最大的作用是能够理性正视生活中所遇到的事情,哪些事情我需要隐忍,哪些事情我需要放手一博,哪些事情我可以做,哪些事情我不可以做,也有助于我更好的做好人生规划,不偏离人生方向的持续前行。 我很开心在自己即将在而立之年能想通这样一件事,于是就记录在网络上的这片属于自己的地方,期待将来我回过头来再来看看。 附: 当我发布这篇文章到网站上后,才发现原来我网站的标题就是通往成熟与自由的旅程,看来这并不是巧合,而是我潜意识中故有的所在了。

January 30, 2015 · 1 min · fortitude.zhang

Midonet聪明的Tunnel Key分配策略

拥抱开源如今成了一种潮流,既Juniper家的OpenContrail成为开源一揽子(之所以称为一揽子是用于区别现有OpenStack中由社区所维护的基于分散组件的松耦合方式)OpenStack网络虚拟化方案的首发明星后,Midukura这家公司也将自家的OpenStack网络虚拟化方案以开源方式来运作了,相比于OpenContrail的工程师的设备商研发背景,Midukura更具有IT运维背景(这点可以从其技术堆栈如scala编程语言、zookeeper/cassandra数据库、分布式架构推测出来,关于更细节的内容,后面我会陆续补充相关的分析),因此我个人还是更看好Midokura的方案,而从自己实际部署及验证的情况来看,Midokura要靠谱的多一点,当然这只是一家之言,也并非本文的重点,就不再展开。 在本文中我想谈的是,Midonet Tunnel Key的使用策略,与我们通常在基于OVS的方案中看到Tunnel Key(不论是NVGRE还是VXLAN)一般用做租户标识(即Virtual Network Identifier)不同,Midonet Tunnel Key则可以理解为按VIF分配的(实际上是基于Midonet的外部虚拟端口分配的,这里为了简化理解,可以简单认为就是按VIF分配的),而前者其实也是IETF相关标准文档所描述的用法。 Midonet之所以这样做的原因,与其架构实现有较大的关系,Midonet的架构总结起来,有如下的这几种特色: 全分布式架构,每个节点上运行一个Midolman进程(跑在JVM上),用于负责从分布式数据库(zookeeper)同步并发布虚拟网络配置信息,因此实现了去中心化,每个节点可以独立计算出转发结果 虚拟拓朴仿真机制,Midolman从VIF上收到报文后,通过拓朴转发仿真(与我们常规的Bridge->Router->Router->Bridge转发类似),就可以计算出目的VIF,从而得知目的虚拟机所在的主机,并在通过Underlay网络的IP以NVGRE/VXLAN的方式将报文Overlay传送给目的主机前就将报文编辑好 内核转发采用OVS datapath,即采用exact match的flow转发(megaflow暂不支持),以实现次包(即首包之后的包)的内核转发,提高转发性能 结合上面的介绍,Midonet采用基于VIF分配的原因就比较清楚的: 即然源端可以直接仿真出目的VIF且完成报文编辑,因此到对端唯一需要做的就是知道对端的VIF对应的OVS datapath接口是什么,NVGRE/VXLAN封装中的Tunnel Key则提供了一个简单方便的编码点,于是midonet就这么用了,另外一个Host上通过Zookeeper分配的Tunnel Key空间有10位数(非标准限制,而是Zookeeper的限制),对于一个cpu有限、memory有限的主机来说,10位数的VM已经远超能力极限的(咱们又不是天河一号,天河一号估计也不行),已经足足够用了 Midonet采用与OVS相似的机制,转件层面采用wildcard match流表,内核采用exact match流表,因此在主机上的Midolman扫描到VIF对应的TAP接口时,Midolman就可以为这个VIF生成一条匹配域为该VIF在该主机上所申请到的Tunnel Key为匹配项的wildcard match流表,其出接口即为该VIF所对应的OVS datapath接口,当收到含有该Tunnel Key的报文时,可以直接命中该wildcard match流表,提取报文字段生成exact match流表出接口继承该wildcard流表向OVS datapath下发即可,Wildcard match流表查询及exact match流表下发会非常迅速,也弥补了Java/Scala代码在未被JIT编译器优化时的性能损失,是一个非常优雅的方案 以上便是我个人对于Midonet Tunnel Key分配的理解,在软件定义网络这股风潮日近的今天,来自于互联网IT企业所带来的新思维,新用法,也许会继续改变设备商的开发模式,设备商要想办法适应并拥抱这种变化了。

January 11, 2015 · 1 min · fortitude.zhang

黄金时代

国庆期间和老婆在看完了稍煽情的“亲爱的”以及速食搞笑式的“心花路放”这两部热门电影后,补了团购的差价冲着文艺片的口号去看了电影“黄金时代”,看了一会儿才发现这原来是讲述作家萧红的传记式电影,我并不熟悉萧红的作品,尽管剧中大部分的作家我都有过耳闻,所以这篇并不是观后感,而是借题发挥,因为如果从黄金宝贵的含义来说,我即将步向三十岁,并同我的爱人结了婚,我生命中最为珍贵而且无忧无虑的生活也即属于我们的“黄金时代”已经划上了句号,因此即便看完电影已经过了三天,我都难以不想起我的黄金时代已经结束这样的一个现实,于是只好在这深夜里,随笔用我刚清理过的机械键盘打下下面这些文字吧。 看电影的过程中听着画外音所转述出的萧红那强烈画面感(或者我应该用即视感这样更为时髦的话语吧,但去他娘的,我就是这么的固执)的文字,我突然意识到,在我黄金时代的前二十几年,我也曾经对文字有过一种说不出的迷恋,而如今近十年过去,我却很少再能够静下心来,读篇散文或者长篇小说,心中柔软的地方已经变的坚硬,少有被触动了,这并不我所期望的一种状态,无论如何,在我未来的生命中,我都想再次疾呼并提醒自己,无论信息多么的碎片,我都应该试着再次软化心中的某块地方,毕竟,人并非机器,尽管人已经逐渐被机器所束缚,我们总需要情感来支撑自己活过。 假期陪老婆看装修材料,体验了老婆平日里跑装饰城的艰辛,看着老婆稍显稀疏的头发,心里涌起一阵阵的伤感,尽管老婆高中毕业,我曾经想去证明既便我们这样的搭配依然能过的很好,如今看来却有些荒唐与可笑了,我谁不需要去证明,也无需给自己证明,老婆同我度过的六年,同样也是她的黄金时代,我们一起笑过、哭过、闹过、打过,如今仍然相依为命在一起,生活也逐渐的稳定起来,我们都彼此都真心的付出过,就不再愧对于自己过往的时代了。 我并不是一个安份的人,既使如今定居在苏州三年,我心里仍一直有些躁动,渴望继续能够在不同的城市生活,老婆也很支持我这样的想法,我很期望这就是我们将来的时代所最明显的印记,时而漂迫,时而安定,永远生活在别处。

October 7, 2014 · 1 min · fortitude.zhang

使用ghostscript合并多个pdf文件

最近用chrome从网上打印了一系列文章,于是弄出来了一堆pdf,很想把这些pdf合并成一个pdf,再编辑下书签水印的,很容易弄的有点像个书的样子。 搜索来发现还是ghostscript这个工具比较适合,gentoo上直接emerge即可,其他发行版应该比gentoo更为简单。 从ghostscript的官方网站的这句介绍的话: Welcome to the Home Page for Ghostscript, an interpreter for the PostScript language and for PDF, and related software and documentation. 可以很容易看出,ghostscript做为PDF解释器,是能够理解PDF的内部构造的,那么合并PDF这样的事情,应该会做的不错。 闲话不多说,安装完ghostscript后,可以用如下命令行来合并一系列的pdf。 gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=finished.pdf file1.pdf file2.pdf 简单解释一下上面的选项: -dBATCH 批量处理,做完就乖乖退出 -dNOPAUSE 每页PDF都给我处理好,不要等我再下指令 -q 不必要告诉我你在正确处理 -sDEVICE=pdfwrite 使用内置pdfwrite设备来写文章 -sOutputFile=finished.pdf 合并后的文件名 怎么样,还是比较简单吧? 附: [1] ghostscript官方主页

July 21, 2014 · 1 min · fortitude.zhang

关于产品的思考(一)

最近百度一位30岁的副总引起了关注,在c114上甚至看到了有人发了将其与李一男对比谁更厉害的帖子,然而我对论坛口水战没有兴趣,我更关注是他们均随着成就产品的同时而成就了自己,前者搞火了百度贴吧、百度百科,使百度在移动互联网时代取得了不错的份额,后者则是用CC08程控交换机帮老任打了如今华为的坚实基础,人们需要好的产品。 上次我在京东购买了一条3.5mm的耳机插口延长线,其接口应该采用铜金属制成,直径约一厘米,长约三厘米,直到最近我才注意这样设计的好处,原来在桌子上,由于这么多的铜,使得这个东西对桌子的吸附力要比一般的普通延长线要好的多,也就不容易在听歌时掉到地上去,这款产品于我而言,就是很不错的产品,我如果再有类似的需求,也同样会优先考虑这样的产品。 以往在华为工作时,做为大公司里的一名螺丝钉,如果非要套上一个产品的话,我所负责的模块或者项目,可以称得上产品,交付一个少bug稳定的特性,或许就可以称得上交付了一个产品,然而正如那句经典的交换机上80%的特性都是无用特性的话所说,我不知道我所交付的这个所谓的产品,是否能让用户在用到时,有如同我上面的那样的感觉,而在敏感且对可靠性要求严格的路由器产品上,软件的稳定性尤其重要,这样的特性,即使用户不会使用,也将自此融入产品,再不敢轻易删除,从此软件越来越膨胀。 从华为辞职后,在新公司,因为公司规模的缘故,我与之前相比,更容易接近客户了,那么到底怎么样去衡量客户的需求是否合理,我们做出来的东西是否能让客户产生眼前一亮的感觉,惊叹一声这恰好就是我所期望的东西,如何避免上面软件膨胀的问题,对我而言都是具有挑战性的工作,使我越来越觉得如何评估如何做出好的产品,满足客户需要的产品的重要性了。 对于这样的问题,显然是不会现成的答案的,甚至我觉得,不同的领域,不同的客户,对于好的产品的定义,也自然是不同的,比如对于不爱听歌的人,显然无法给出什么样的随身播放器是一款好的产品。 如果要弄清楚这样的问题,首先就要对目标市场有深入的理解,甚至需要对目标市场的主要玩家的产品有深入的理解,真正了解客户目前在怎么用,是否遇到了什么问题,如果有机会的话,需要和客户做更多的交流,甚至在现场去了解,去分析。 其次,要多增加碰撞的机会,真理越辩越明,在相关人之间要着力创建思辩的氛围,在东西未经讨论之前,尽量要避免做老好人的角色,不能唯唯诺诺。 再次,在客户给予条件的时候,要尽早获得客户的反馈,这与敏捷开发的原理相似,借此可以快速迭代,快速优化,尽快让产品接近客户需求本质,避免走弯路。 如今我比以往更渴望,能够做出一款真正有人广泛应用的产品来,让人们的生活更美好,岂不是一件很有成就感的事情么?

July 14, 2014 · 1 min · fortitude.zhang

AOSA之ZeroMQ阅读笔记

AOSA即《The Architecture of Open Source Application》是本不错的书,这本书的写成本本身也采源了开源社区的协作方式,目前已经出了两部,最新的版本为POSA即《The Performance of Open Source Application》,专注于开源软件的性能。 最近抽时间看了AOSA中关于ZeroMQ的章节,自己先前由于工作需求,简单了解到过ZeroMQ,这次可以借机会读读ZeroMQ创始人亲自写的章节,确实有不少的收获,记录在这里,在后续的项目实践中可以予以参考使用。 Library设计 The lesson here is pretty obvious: Don’t use global state in libraries. If you do, the library is likely to break when it happens to be instantiated twice in the same process. ZeroMQ设计时经过分析和对比,最终采用了Library而非单一的消息服务器的方案,在设计Library时,得出了上述结论。 也即对于Library而言,最好避免全局状态,采用Context的方式较好,特别是存在library被额外的library依赖在同一程序中存在多份library实例时可以避免带来的竞争性问题。 了解真正的问题 There are many more pitfalls in benchmarking the messaging systems that we won’t go further into. The stress should rather be placed on the lesson learned: Make sure you understand the problem you are solving. Even a problem as simple as “make it fast” can take lot of work to understand properly. What’s more, if you don’t understand the problem, you are likely to build implicit assumptions and popular myths into your code, making the solution either flawed or at least much more complex or much less useful than it could possibly be. ...

July 8, 2014 · 3 min · fortitude.zhang

自已动手打造wifi路由器

由于家里那台华为的HG8245越来越不给力,虽然是自己的前东家出品,这产品也真不耐用,用后门上去可以发现经常性出现kernel分配skb不到导致上网时断时连,妈的内存只有一M空余了,当然,也许他们也知道这东西电信是不给开路由的,既然咱自己动手hack开了路由,就别怪这种后果。 于是最近花了一周晚上的时间,买了个PCDuino板,自己搭建了一个家用wifi路由器,由于我家基本不存在WLAN间互访的问题,少了个LANSWITCH影响不大,做个NAT Router,PCDuino跑的比较Happy,网速快的很开心;至于HG8245,俺将之改回了bridge模式,给俺透传个报文,目前跑的很欢。 废话少说,以下拉个清单,供有需要打造wifi router的朋友参考交流。 原材料汇总 PCDuino v1,v2集成wifi实则非常鸡肋,不必花冤枉钱 802.11n USB WIFI无卡 (需支持AP模式),京东上购得EDUPEP-MS15002一款,只需39元,采用RTL8192CU芯片,支持2T2R实现300Mbps数据传递,对于我那只有12Mbps上的光纤,已是足足有余 HDMI to DVI转接线 (如显式器支持HDMI则直接买HDMI线即可) 5V/2A DC电源 (本人拿IPAD充电器替代) 旧笔记本上拆下来的320G硬盘,用来做下载机硬盘 4G左右的SDCARD,虽然PCDuino自带4G NAND flash,但这玩意显得得保护得当,启动盘与系统盘还是复制到SDCARD上比较好 背景知识 以下是我总结下来的需要了解的一些背景知识,似乎有点多,但科班出身的咱们码农们,不少是熟之又熟啦。 基础Linux操作系统知识 基础网络知识(交换与路由) 交叉编译 内核编译、内核模块编译 iptables使用 routing/bridging PPPoE HostAP配置(实现wifi认证接入) 打造过程 复制系统到SDCARD双系统设计算是全志A10这款SoC的亮点,默认的Linaro系统接电启动可以通过Ctrl-Alt-F1进入文本模式,启动板子配置工具,此时可选择将NAND Flash上的系统拷贝到SDCARD上,A10在下次启动就可以根据SDCARD上是否存在启动文件而从SDCARD启动,从而避免对Nand Flash的寿命产生影响。此后除非把SDCARD上的内核弄坏,一般情况下就无需Nand Flash启动了。(二般情况下,我就犯了错,替换SDCARD启动分区上的内核文件时,没注意到大小不对,使得还需要用Nand Flash启动,手工挂载SDCARD启动分区,拷贝可用的内核予以修复,其实也并不难办,只是稍显麻烦)。 升级SDCARD上的系统玩过Debian系OS的话,对apt-get比较熟悉了,轻车熟悉升级一把即可,Linaro源里的包还算丰富,由于A10主频有1GHZ,并且自带1G内存,所以系统默认就带了编译工具,对于像我这里用到的RTL8192CU驱动编译的话,在PCDuino上直接就可以编译完成了,无需进行交叉编译。 Wifi AP设置wifi AP配置的一切麻烦都来自于8192CU这看似性价比高的芯片,A10所用3.4.29+内核里的驱动虽能用,但用起来还是不够好,所以RealTek官方还是给出了自己的源码,虽然会增加麻烦,但所幸官方提供了包括修改过的HostAPD源码,编译下内核再编译个HostAPD,就可以搞定了。官方给出的驱动包里的东西已经比较清除了,Linksprite上的链接提供了板子上直接编译该驱动的方法,以下附上链接: PCDuino编译 8192CU驱动 IPtables规则设置IPtables依赖的netfilter功能在PCDuino默认内核上是没有开启的,因此需要重新编译内核和内核模块,理论上可以直接在PCDuino上完成,但内核编译显得耗时过长,生命有限,能少折腾还是少折腾了。Linksprite上的链接提供了在X86_64 Linux上交叉编译内核的方法,从文章的链接中也可以找到如何替换SDCARD上内核的办法,以下附上链接: PCDuino交叉编译内核 需要注意的是,因为8192CU驱动为我们自己编译,建议下完内核代码后,把这款驱动的编译修改到内核编译过程里,避免每次需要手工复制,并且如果是在板子上编译的内核模块,与新交叉编译的内核文件并不配套,导致不能顺利加载,影响wifi接入功能的顺利调试。因为家里有多台设备需要通过此wifi router上网,IP tables的作就就是在ppp虚拟口(在未完成PPPoE拨号时,这里可以用内置接口eth0替换,相当于在HG8245下面又做了一级NAT)和WIFI接口间进行NAT,目前只用到一条MASQUERADE规则即可: :::console iptables -A POSTROUTING -t nat -o ppp0 -j MASQUERADE PPPoE拨号在之前的步骤中,我一直还是通过HG8245 DHCP接入上网的,当上述设置完成后,就可以恢复HG8245为桥接模式了,在PCDuino上通过内置的RJ45 100M端口,通过HG8245光猫PPPoE拨号出去,自此但可享受远离HG8245频繁掉线的困扰了。Debian/Ubuntu系统上PPPoe拨号相对比较简单,网上有大把流程,这里就不再赘述了。 陷阱(坑啊坑) PPPoE与TCP MSS问题由于PPPoE这样Overlay在Ethernet(最近研究了太多的overlay技术了)上,显然是有额外的封装代价的(需要在正常的以太报文上再额外消耗8个字节),这样就会与TCP协商时的MSS产生冲突,TCP采取本地网卡的MTU来填写TCP报文的MSS,而大部分终端默认网卡MTU都是1500,这样就会有可能在PPPoE封包过程(设想终端发过来的报文刚好1500,再加8字节的封装就大于1500了)中产生大于运营商链路MTU的报文,从而使和报文被丢弃,直接症状就是视频或图片加较缓慢或不能加载,影响家庭用户心情。以下链接提供了较为详细的介绍,可供参考: MTU and PPPoE详解 对此问题,Linux Iptables提供了TCP Clamping的功能,直白点就是动态干预调整TCP MSS字段的设置(另外一种方法基于path mtu discovery,但容易受现网环境影响,不必折腾),具体命令如下: :::console iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1460 后记 PCDuino用着让人不爽的几个地方: ...

June 26, 2014 · 1 min · fortitude.zhang