Test Doc
<h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p><img data-src="/../../../images/elogs/b921c8dd42bc1bcccf1a4d99d08f79e1
<h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p><img data-src="/../../../images/elogs/b921c8dd42bc1bcccf1a4d99d08f79e1
<h1 id="intro"><a href="#intro" class="headerlink" title="intro"></a>intro</h1><p>在抬笔之前,纠结许久,过去的这一年,真的有这么多要记录的东西么,有必要花几个小时的时间去写么?我不知道。但同时,我的鼠标已点开了之前的博客,开始翻看前些年写的文字。看着看着,我找到了许多自己已经不怎么记得,但想起却感到十分温暖的那些瞬间和回忆。虽说都不是什么大事儿,但是如果不记录,它们可能真的就会遗失在记忆的荒野里了。</p> <p>所以,我还是要写些文字,来记录我这平凡,也小有起伏的一年时间。</p>
<p>在挺久之前,可能是刚读大学的时候,就隐约听说这本《禅与摩托车维修艺术》的大名,也得到了几位朋友推荐,但在当时,翻过几页后发现根本看不下去,就束之高阁了。这次终于在好奇心的不断怂恿之下花费了一些意志力重新拾起,终于随着情节的展开,同作者一起踏上了骑着摩托车横穿整个美国的长途旅行。</p> <p>在最开始的认知中,我认为这场摩托车旅行一定是一个非常酷的故事,但后面发现虽然故事的确很酷,却非第一印象中的那种酷。</p> <p>在这场旅行中,我在了解美国地理的同时,也被作者和“斐德洛”的暗中较量所吸引,对父亲与克里斯的矛盾所疑惑,更为寻找“良质”同作者(或者说是“斐德洛”)一起陷入了对当下的反思。</p>
<p>时间很快,如今已经是2021年伊始了。虽然已经很久没有写过文章,但是,面对2020年,我总还纠结着要说些什么。</p> <p>2020最大的主题就是变化。不仅有意料之中的变化,更多是意料之外的变化。</p> <h1 id="疫情"><a href="#疫情" class="headerlink" title="疫情"></a>疫情</h1><p>说到变化,总也绕不过的就是疫情。</p> <p>我的2020年是以一次滑雪作为开始,在那场滑雪之后,我还在畅想在结束毕业论文写作之后,毕业前的时间我应该怎样度过,是要趁着有闲逛上大半个中国,还是省一些钱躲在实验室里啃啃买来一直没读的大黑书。</p>
<p>在上一篇博客<a href="/debug-linux-kernel-with-vscode">使用Qemu和GDB对Linux内核进行调试</a>中已经介绍了使用Qemu和GDB对Linux内核进行调试的方法,但是GDB调试对于用惯了GUI工具的人(比如我)来说并不是很直观,所以就希望尝试使用比较熟悉的GUI编辑器,如VSCode,对内核进行调试。</p> <p>由于VSCode的调试方式同样基于GDB,所以需要先在GDB中测试没有问题。</p> <h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><p>需要在VSCode的插件市场中安装微软官方的C/C++插件,该插件可用于IntellSence和GDB调试。</p> <h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>为了使VSCode支持内核的调试,需要配置launch.json,特备注意需要配置<code>setupCommands</code>属性,以便在GDB启动后对其进行设置,大致的配置文件如下:</p>
<p>使用Qemu对Linux内核进行调试是一种较为便捷的方式,近日进行了一番实践,并将大致步骤与其中一些小坑记录了下来。</p> <h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><p>由于放长假赋闲在家,所以手头只有一台装有MacOS的MBP可用,而Linux内核的开发与调试使用Linux环境下会比较方便,所以就使用VMware Fusion创建了一台安装有Ubuntu 18.04系统的虚拟机。由于编译Linux内核及相关软件需要的资源较多,所以为虚拟机配置了双核CPU、2GB内存和20GB磁盘空间(笔记本本身资源有限),但实际使用(特别是物理内存和硬盘)捉襟见肘,于是又在系统中添加了3GB的SWAP内存并扩容了20GB的磁盘空间(其实还是不太够)才解决问题。</p> <h1 id="编译Linux内核"><a href="#编译Linux内核" class="headerlink" title="编译Linux内核"></a>编译Linux内核</h1><p>首先,尝试对内核进行编译,在编译前需要使用通过KConfig启动内核的调试配置。</p> <h2 id="下载内核源码"><a href="#下载内核源码" class="headerlink" title="下载内核源码"></a>下载内核源码</h2><p>由于Linux内核代码量非常大,且由于国内网络大家都懂的原因,所以的下载内核源码是一项较为复杂的体力活动。</p>
<p>最近在项目中遇到需要在 NodeJS 中调用 C++代码的问题,在此略作总结。</p> <h1 id="主要方案"><a href="#主要方案" class="headerlink" title="主要方案"></a>主要方案</h1><p>在 NodeJS 中,和其他语言编写的代码通信主要有两种方案:</p> <ul> <li>使用 AddOn 技术,使用 C++为 NodeJS 编写一个拓展,然后在代码中调用其他语言所编写的源码 or 动态库</li> <li>使用 FFI(Foreign Function Interface)技术,直接在 Node 中引入其他语言所编写的动态链接库</li> </ul> <p>在对这两种方式进行比较后,发现这两种方式各有优劣。</p> <p>首先,AddOn 技术比较通用,它可以使用 C++代码来拓展 Node 的行为,很多库都是使用这种方式来完成一些比较底层操作(比如和操作系统的一些通信)的。但是它写起来比较麻烦,要编写一个 C++项目,还要按照 NodeJS 的规范 export 相应的函数,而且每次安装的时候都需要进行编译(以适应本地 Node 的版本)。如果只是调用一个 DLL,那就还需要在项目里重新包装一遍 DLL 的接口。</p> <p>如果使用 FFI 技术,限制就会比较多,首先,它只能调用其他动态库,如果你想使用 C/C++完成更多功能的话,还需要再封装一层 DLL,另外,它只支持<code>_cdecl</code>调用约定(也就是 DLL 在导出的时候一定要标记用<code>_cdecl</code>编译命令),不支持<code>_stdcall</code>或者<code>_fastcall</code>调用。但是调用起来就会很方便,可以直接在 JS 代码中声明 DLL 的接口就可以了。</p> <p>综上比较,如果只调用第三方 DLL(而且恰好是<code>_cdecl</code>导出),使用 FFI 就再合适不过了(虽然性能可能会有一定的损失,而且调试起来会有困难)。</p> <p>其实,从理论上来讲,FFI 也是基于 AddOn 技术的,只是它可以帮你把在 JS 中定义的接口直接转换成 C 语言的接口,并利用 NodeJS 的 Buffer 内存,将其同载入的 DLL 共享。当然由于 FFI 的这种通用性,也导致了一定的性能损失。</p> <p>下面就以在 Windows 平台上使用 FFI 为例,简单聊一下如何使用 NodeJS 和 C++编译而成的 DLL 通信吧。</p>
<p>引用是C++相对于C而引入的一个重要特性,它使得许多地方的语法变得更加简洁,但是它们的底层究竟是怎么实现的呢?</p> <p>在Wikipedia中,对指针有如下介绍:</p> <blockquote> <p>In computer science, a pointer is a programming language object that stores the memory address of another value located in computer memory. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer.</p> </blockquote> <p>从定义可以看出,指针从本质上来讲就是一个变量,其中所存储的就是其他变量的地址。 而C语言中的指针非常灵活,它可以任意指向某一个地址,不论这个地址究竟是否存在,或它究竟存储的是否为指针所代表类型的数据。</p> <p>那么也不难想到,指针在实现的时候也是内存里的一个变量,它存有其他变量的地址。</p> <p>在Wikipedia中,对引用有如下介绍:</p> <blockquote> <p>In computer science, a reference is a value that enables a program to indirectly access a particular datum, such as a variable’s value or a record, in the computer’s memory or in some other storage device. The reference is said to refer to the datum, and accessing the datum is called dereferencing the reference.</p> <p>In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The definition of a reference in C++ is such that it does not need to exist. It can be implemented as a new name for an existing object (similar to rename keyword in Ada). </p> </blockquote> <p>从上面的定义可以看出,在C++中,引用可以狭义地认为是某一个变量的别名,它本身是并不存在的。</p>
<p>自昨天下午看完《流浪地球》以后,内心久久难以平静。闭上眼睛后,大脑中出现的是流浪地球的主题曲《带着地球去流浪》和地球飞临木星时候大气交汇时那种磅礴而又难以用语言形容的场景。</p> <p>这首歌里,一面是曹操的《观沧海》,描述了人类面对这个世界所发出的赞叹,描述出了大好河山的雄伟壮丽。而另一方面,又进行了古今对比,更体现出这场星际旅行的悲凉与无奈。伴着这首歌,我就知道必须要写些什么了。</p>
<h1 id="Intro"><a href="#Intro" class="headerlink" title="Intro"></a>Intro</h1><p>倏忽之间,又过去了一年。是时候向 2018 说一声再见了。</p> <p>今年,我只在写 <a href="/feelings_around_new_year">年关随笔</a> 时立了一个 Flag,要练习深度写作,至少每个月输出一篇文章。可惜因为暑假时候偷懒,这个 Flag 也并没有达成。不过,我还是要在 2019 重新立起这样一个 Flag —— 2019 年每个月至少输出一篇文章,可以是技术,可以是随笔,也可以是观点。希望明年这个时候再回来看,不要像今年一样打脸。</p> <p>再说回 2018。这一年相比前些年,在我的努力下,节奏逐渐慢了下来,让我有了许多时间静下心来思考、做事,也有时间和爱人相处、与朋友侃大山(至少在十一月之前是这样的)。同时,这一年又并不像以往那么顺遂,让我明白了人力有限,世间有太多力所不能及之事。</p> <h1 id="时光·记忆"><a href="#时光·记忆" class="headerlink" title="时光·记忆"></a>时光·记忆</h1><p>在大自然面前,没有什么是能够永恒的。人不能够,事不能够,城也不能够,甚至文明也不能够。</p>
<h1 id="问题-1-键盘弹起后会遮挡键盘上方的内容"><a href="#问题-1-键盘弹起后会遮挡键盘上方的内容" class="headerlink" title="问题 1 键盘弹起后会遮挡键盘上方的内容"></a>问题 1 键盘弹起后会遮挡键盘上方的内容</h1><p>在微信浏览器中,如果需要模拟一个类似微信聊天的窗口,那么一般情况下需要将输入框使用 fixed 定位放置在页面最下方。就像这样:</p> <p><a href="/images/posts/the_solution_of_bugs_on_wechat_in_ios/wechat-ios-bug1.png"><img src="/images/posts/the_solution_of_bugs_on_wechat_in_ios/wechat-ios-bug1.png"></a></p> <p>但是,在 IOS 中的虚拟键盘和 Android 里是不同的。在 IOS 中,虚拟键盘弹出以后,键盘上面的输入提示会比键盘弹出慢半拍,所以就会导致输入法的提示框将正常页面挡住的情况。</p>
<p>现在,Docker 已经成为了一个非常主流的虚拟化技术,它集合了 Linux 中的许多虚拟化技术,如 Namespace、cgroup 和 AUFS 等等,所以我们可以使用 Docker 搭建一个开箱即用的虚拟化容器。但是,Docker 网路在很多时候依旧不能满足应用场景中的需求,这就需要我们对 Docker 中的网络进行自定义了。</p> <p>这篇博客就是关于位于不同虚拟机中的两个容器实现 vxlan 通信的实验。</p> <h1 id="拓扑和环境"><a href="#拓扑和环境" class="headerlink" title="拓扑和环境"></a>拓扑和环境</h1><p>首先讲一下实验拓扑吧,它大概长下面这个样子。</p> <p><a href="/images/posts/vxlan_tunnel_with_container/docker-vxlan-topo.png"><img src="/images/posts/vxlan_tunnel_with_container/docker-vxlan-topo.png"></a></p> <p>一共两台虚拟机,在两台虚拟机之间使用交换机连接。在虚拟机内部各有一个容器,容器和主机通过 bridge 连接,而这两个虚拟机之间需要通过 vxlan 进行连接。</p>
<h1 id="intro"><a href="#intro" class="headerlink" title="intro"></a>intro</h1><p>上学期同<a href="http://www.cyprestar.com/">Thesharing</a>以及 Stone 去北大旁听了将近一学期的《科技创新与创业》(课程网站:<a href="http://net.pku.edu.cn/dlib/pkuxstart/">http://net.pku.edu.cn/dlib/pkuxstart/</a>)。 这个课程由百度七剑客之一的雷鸣主持,邀请了很多行业内有名的企业家来讲课,几乎都是北大校友(感慨一下北大校友文化真的很棒)。 我想在这篇文章中总结一下他们所讲的一些能引起我思考的观点和内容,以及经过我提炼加工所得到的结论。</p> <h1 id="三角关系"><a href="#三角关系" class="headerlink" title="三角关系"></a>三角关系</h1><p>这里的三角关系并不是指恋爱中的那种复杂关系,而是指一个行业中相互制约的几个要素之间的复杂关系。其中一种要素发生大的变化(一般是非连续性的),这个产业整体以及几个要素之间的相互关系也会随之发生变化,这往往预示着新机会的到来。</p> <p>微博 CEO 来去之间举了一个例子——移动互联网中存在的三角关系:运营商、手机制造商和互联网公司。 这个三角关系中某个要素发生变革就会导致移动互联网行业的巨变,会有一波新的公司起来。比如运营商 4G 网络的普及,使得网速变得越来越快,流量变得越来越便宜,这就催生了短视频行业的兴起,这也催生了一系列的公司和产品,比如快手和抖音。</p>
<p>最近得知《青年马克思》上映,觉得有必要一看。于是上网搜了一下院线的排片,不出所料,排片量几乎是最近热映的《复联 3》的五分之一,甚至周末都少有商业影院有排期。于是只能等到周一约上阿文,去附近的影院一睹青年时期马克思的“芳容”。</p> <p>刚入座,还在和朋友聊最近的中兴联想发生的一系列事件,电影就毫无防备地开始了。此时一个大概容纳五六十人的小影厅里只稀疏地坐着六七个人,多数还是学生(祖国未来还是很有希望的嘛)。</p> <p>电影里的场景暂且不表,先来说说我对电影整体的感受吧。 首先,作为一部传记电影,而且讲述的是一位思想家的成长历程,如果没有一些对马克思生平以及思想的了解,可能就会在电影院呼呼大睡了。这可能会是观影的一个门槛。</p> <p>其次,电影内容很丰富。短短不到两个小时,电影讲述了马克思从莱茵报编辑,到论战蒲鲁东,最后是完成《共产党宣言》这三个时期,同时又穿插了马克思与燕妮之间深沉的爱,马克思同恩格斯之间深切的友谊以及恩格斯同玛丽之间跨越阶级的感情。</p>
<p>在前端调试的时候,跨域一直都是一个比较麻烦的问题,这个在之前的文章<a href="https://blog.zhengzi.me/deal_with_cors">关于跨域问题的一个解决方法</a>中其实已经讨论了一些可以使用的方法。</p> <p>如果要使用 JSONP,第一是需要修改的地方比较多,而且也不太符合前端发展的大趋势,如果使用 CORS 的话并没有 application/json 类型。而且更重要的是这只是在前端调试时候的需求,并不是在上线以后的需求,所以对后端有太多的入侵也不好。</p> <p>所以就有一个念想突然在大脑中闪过——加入有一个代理不就可以解决这个问题了?但是又想了一下写起来还挺麻烦,于是就被搁置了。 直到前几天 Stone 提到其实 webpack-dev-server 早就想到并且已经帮我们实现了。</p> <p>于是,我就在一个 Vue 项目中进行测试,发现真的很赞,既可以本地 Server 热加载,还可以直接跨域调用远程 API,完美解决了之前遇到的所有问题。</p> <p>接下来我简要介绍一下步骤(以一个 Vue 脚手架建立的 webpack 项目为例):首先检查<code>build/webpack.dev.conf.js</code>中是否有</p> <figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">proxy: config<span class="selector-class">.dev</span><span class="selector-class">.proxyTable</span>,</span><br></pre></td></tr></table></figure>
<p>偶然读到王德峰老师的一本已经绝版的小册子,叫《寻觅意义》。心想这个题目起的甚是有趣——其一我在想他会怎么写,结果读下去发现是他在各个大学讲座的讲稿的一个小集;其二说来也很巧,我最近也一直在反思意义究竟是什么,我做什么才有意义,我追求的意义是什么,有没有属于这个时代的意义,而真正的大义又是何物呢?</p> <p>关于时代的意义,和妈妈聊天的时候,她关于她的意义是什么给了我如下的解答:“除了想让你过的开心快乐,剩下的意义就是多赚钱了,钱赚得多,我就感觉很踏实。”我想,前半句是家庭,是我和母亲很真挚的亲情;后半句是时代,是我和母亲以及所有存活于现代社会的人共同处于的环境。</p> <p>我们所处的是这样一个被资本与技术所主导的时代。所以我理解大家的理想多是要去赚钱。不论男女老少,不论贫穷富贵,每个人的欲望也总和钱脱不开关系。而钱这个东西,究其根本,不过是一个几乎是全人类共同参与的一个游戏,同我们的能生存与否没有什么直接的依赖关系,只是在这个时代里,我们需要用钱去获得各种生存资源和对他人支配的权力。</p>
<h1 id="深度写作"><a href="#深度写作" class="headerlink" title="深度写作"></a>深度写作</h1><p>最近看见沈向洋发表了一篇文章(地址:<a href="https://zhuanlan.zhihu.com/p/33771188">https://zhuanlan.zhihu.com/p/33771188</a>),大意是说在这个 AI 的时代,虽然每天我们产生和接受的的零碎的信息量都非常巨大,但真正有意义的思考还是需要通过长篇写作来完成。写作可以帮我们理清思绪,可以清晰地表达观点和逻辑。</p> <p>这也是我最近所担心的事情——我也已经很久没有进行过深度的写作了。</p> <p>上次系统地写作还是中外文学名著鉴赏的期末作业,文章虽然可以大致表达我想说的表面意思,但是短短八百字的表达却支离破碎,根本无法把我更深成次的想法完整表述出来。在刚写完的时候没感觉到还沾沾自喜,觉得一下午写出来的文章应该还能看,之后读起来却就像是读一篇小学生记的流水账一般,像是喝了一大杯白开水还泛着水垢一般,毫无深度,甚至还难以读完。</p> <p>感触更深的一次是上个月我想抽空写一下去年的年终总结,但刚提笔就不知道该从何说起,所以又去翻前几年的文章,发现当时的文风根本现在几乎无法模仿。我十分懊恼,故总结也一直搁置下去。</p> <p>直到今天,我才有勇气重新打开编辑器开始写这篇文章。今天没有给文章定下主题,想到哪里就写哪里,但愿思路会更顺一些吧。</p>
<h1 id="Windows-桌面程序开发一些方案"><a href="#Windows-桌面程序开发一些方案" class="headerlink" title="Windows 桌面程序开发一些方案"></a>Windows 桌面程序开发一些方案</h1><p>开发 Windows GUI 程序的方案有很多,接触过比较流行的大概有三种,一种是 C++和 Qt,一种是 HTML5+浏览器内核,最后一种是 C#+WPF。另外古老的 WinForms 和更古老的 MFC 也不多说了。</p> <p>Qt 的跨平台特性得以开发的项目可以跨平台,而且各种 C++的组件非常丰富。但是但是 Qt 本身库的并不小,我也不是很喜欢 QML 那种 JSON 的书写方式,而且 Qt Creator 用起来也不太顺手,所以一般没怎么用过这种开发模式进行桌面应用的开发。</p> <p>H5 和浏览器内核是一个不错的方式,可以轻松跨平台,而且 H5+JS 可以有很快的开发速度。主流的方案有 Electron、nwjs、cef 和 wke(其中<a href="http://www.danmakupie.com/">弹幕派</a>所用的方案就是 wke),但是 Electron 同样体积巨大,不利于应用的分发。wke 虽小但也很久没有更新,内核很老,bug 比较多。最近志鹏同学正在研究之前 wke 开发者新开发的 miniblink 内核,相信这个方案会比较优秀。</p> <p>WPF 必须依赖于.NetFramework,所以无法跨平台,而且 XP 也不自带.Net,需要用户安装。另外,XAML 虽然写起来麻烦一些,但是开发漂亮的 GUI 还是比较方便。而最新的 UWP 技术也利用了 WPF 的 XAML 进行 UI 的设计,转型起来并不困难。</p>
<p>时日已至伏末,先别问秋老虎可不可怕,仅是鼻炎已经足以让我怀疑有一个连的人在想我。</p> <p>话归正题,兰州在我心中的形象由两部分,一半像兰州烟上(我最喜欢吉祥兰州硬盒上的那个红色镶金的图案)那样:悠悠兰州,九天揽秀,另一半是爽朗直接,像兰州公交车司机一样,可以跳下车跟出租车对骂。总体来讲,用人来形容就是一个很飘渺但又古朴纯净的三四十岁胡子邋遢瘦削的硬汉。总之,矛盾满满。不过这一点不想展开去说,说说最近在兰州的见闻吧。</p> <p>按照惯例,每次回家都要去张掖路逛逛,每次去逛也都盼着能有点什么不一样,但又担心不一样的地方多了我会忘记之前是什么样子。不过到目前为止,我的担心都是多余的。对我来讲,上半年改变最大的大概就是共享单车了。张掖路也是如此,但不是漫山遍野的自行车。为了不让单车进入,步行街的路障间隙更小了——将将够钻进去一条腿——进去以后擦一把汗,开始感慨前些日子的减肥真他丫有效,不然老夫就要卡死在这里了。</p>
<p>好电影是值得多看几遍的。</p> <p>说实话,这几个月我都没有进电影院,更没有看过最近有争论所谓的这些国产烂片或者说是美国大片。对这部电影,虽然没有对比,但不能阻碍我认为它是一部好片。</p> <p>虽然两次看的是同一部电影,但我每次的关注点一定是完全不同的。第一遍是随着影片的进程,不去思考过多,而是把自己融入电影之中,心情和大脑都去主动跟随剧情的发展,完全按照导演和编剧的思路欣赏。如果这是一部好片,那么心情一定会起起伏伏,倘若恰巧情节还比较紧凑,那么一场电影看下来必定是淋漓大汗。第二遍呢,我会选择从片中走出来,在看的时候去思考人物的性格、导演对情节的安排以及场内观众们的表现,看完后必定会有许多新的发现,有时候或许还能看出哪里是被引入的时候经过剪裁的,人物应该在哪里可以更活。</p> <p>首刷的时候,我大概和其他观众一样,随着两个小姑娘的视角,内心跟随她们一起成长,一起对父亲肃然起敬,甚至国歌响的那一刹那,我也跟随她们一起感动。</p> <p>二刷的时候,我注意到了几个有趣的细节。</p> <p>第一个是父亲不顾村里人的笑话,不顾官员的嘲讽,更不顾录像厅老板的眼神,每一次出场的眼神都温和却坚定;但却因自己特殊照顾女儿却导致女儿差点被体育学校开出流泪,这是多坚强的泪水!</p> <p>第二个是父亲不论是在女儿消极怠练还是她们跑去参加别人的婚礼惹他生气甚至是女儿在教练那边学到了新的技巧而趾高气昂地嫌弃他的办法老旧的时候,他都没有打过一次女儿(每次都是她们的哥哥背锅)。父亲虽然严厉,但绝不毒辣,他对女儿的爱不亚于天下任何的父亲。</p>