自制 Profiler 第二部分——调用栈回溯

书接上篇,我们现在已经能在其他程序中执行我们自己的代码,并且也做到了以固定的频率去执行采样代码(我们的printf),但是如何采样还是一个问题,这篇文章会就这这个问题继续探讨接下去我们面临的挑战——调用栈回溯。 为什么要获取函数调用栈?一方面是因为profiler除了要分析程序存在的性能问题,即函数执行热点以外,还需要帮助我们可怜的程序员找到问题的原因,这时候能提供问题函数的堆栈信息就非常必要了;另一方面,我们上一篇文章其实说了,是为了通过堆栈信息尽量还原程序的执行过程:试想一个程序执行的过程是 main->funca->funcb->funcc,我们第一次采样 main->funca,第二次采样 main->funca->funcb->funcc,假如我们没有堆栈信息,我们只会统计一次 funca 和一次funcc,但是这并不能反应事实,相反,我们有堆栈信息的话,就会把 funca 、funcb 和 funcc 各计数一次,更能反应实际的执行过程。 概念 函数调用栈(Call Stack)和相应的栈帧(Stack Frame)我们其实都不陌生:在使用 gdb 调试程序的时候,bt(backtrace)命令打印出来的就是函数调用栈;而函数调用栈列表中的每一项则代表一个栈帧,我们执行 frame 命令跳转到某一个栈帧,其实就是一次回溯的过程。 想要在内存中解析出我们想要的函数调用栈,首先我们需要知道的就是一个程序的stack 段里面各个栈帧是如何布局的,要搞清楚这个,我们还需要了解一个概念叫:调用约定(Calling Convention),调用约定主要约定了(好绕): 函数的参数是如何传递的,是全都放到寄存器,还是全都放在 stack 段,还是混用两者(好像gcc之前是使全用寄存器,后来换成了全用stack); 函数的参数是按什么顺序放置到内存中的; 函数中的本地变量是如何分配的; 子函数调用是如何返回的; 子函数的栈帧是如何清理的; 等等 所以,调用约定基本上决定了函数调用中每个栈帧的产生、压栈、出栈对内存布局的影响,而这个约定是因架构和平台而异的。我们这里只关注x86_64 平台下的 cdecl 约定。 在这个约定下,假如我们有一个函数 DrawSqure 调用了 DrawLine (例子来自Wikipedia),那么程序内存布局中的 stack 段就应该是类似下图所示: 每个函数调用即创建一个栈帧,每个栈帧一次压入 stack 中。 其中,Stack Pointer(esp) 永远指向栈顶, Frame Pointer(ebp) 指向当前栈帧的中一个固定的地方(基地址);函数参数以从右往左的顺序依次压栈,然后是压入Return Address ,它是当前函数(或者栈帧)执行完成后,程序要继续执行的指令地址, 同时压入父函数的栈帧基地址(Saved EBP),它是当前函数执行完成以后,Stack Pointer 和 Frame Pointer 将会指向的地方,基于这个地址,程序指令可以方便地访问函数本地变量(ebp负向偏移)和函数参数(ebp正向偏移)。 结合上面两张图,其实可以看出,每个栈帧其实都保存了上一个栈帧的基地址,因此所有的栈帧最终组成了一个链表,这也就是我们能拿到函数堆栈的理论基础了。 (注:上面只是粗略的讲解,参考链接 [1] 非常详细的描述了函数调用的过程中栈帧、stack 段和esp、ebp寄存器的变化,如果感兴趣,可以详细了解一下。) 参考方案 看完上面一大串概念以后,我们发现如果我们要按照函数约定的方式去获取函数调用堆栈,可以,但是太过蛋疼,而且不跨平台,很难受。 所以秉承不要重复造轮子的优良传统,我们发现有几个方式可以简单地获取到函数调用栈: Read On →

自制 Profiler 第一部分

​ 最近对性能剖析的技术颇感兴趣。好不容易来了三分钟热度,自然不能浪费,因此在余热消失之前研究并实践了其中一部分细节,对于其中一些知识点,个人感觉对于自身编程能力提升还是比较有益的,因此在这里写出来,抛砖引玉。 Linux profiler简介 ​ 性能剖析的工具,其实在Linux平台还是挺多的,比如小巧实用的strace、ltrace、latrace,大名鼎鼎的google-perftools、gprof、valgrind,以及瑞士军刀型的linux-perf等等,它们主要分为三个阵营,一个是针对程序执行的性能进行剖析,对程序执行的热点进行分析,如*trace、gprof这些工具;另一个是针对程序运行过程中内存的使用进行剖析,方便针对性地做内存优化,如valgrind;最后一部分就是“脚踏两条船”的,两个我都做,比如google-perftools、linux-perf这些,我们这个系列主要集中在“针对程序执行的性能进行剖析”方面。 Profiler的本质 ​ 要自制Profiler,首先要知道Profiler的本质是什么。简单来说,Profiler的本质其实就是在程序执行的过程中对程序正在“做什么”进行搜集和统计,如何搜集呢?无非两种: Instrumentaion - 程序主动Profiler告诉它在做什么; Sampling - Profiler自己间断性地去看程序在做什么; 前者的实现主要依靠程序运行时提供的某些钩子机制、代码插桩等方式,例如gprof主要是依靠 gcc 在编译程序的时候”夹带私货“来达到程序运行的时候主动提供给gprof采样样本,来达到事后分析的目的[1]。这种方式相对来说虽然比较可靠、准确,但是对于无法控制编译条件的程序就比较无可奈何了。 后者的实现则主要是定期对程序当前执行的指令和对程序执行的函数堆栈进行回溯(unwind)来尽量还原程序执行的过程,例如google-perftools就是采用这种方式,这种情况下,采样的周期就显得尤为重要。 ​ 对比以上两种方式,我们果断采用第二种。 ​ PS: 这里需要说明一下的是,利用ptrace系统调用完成工作的strace和ltrace,虽然不依赖编译器夹带私货,但是相当于依赖了内核的“钩子”,不属于sampling的范围;同样,latrace则是依赖了ld的LD_AUDIT“钩子”,也不属于sampling的范围。 Profiler启动 ​ 那么问题又来了,ptrace没得用,我们怎么去获取被剖析程序的执行状态呢?总不至于profiler要搞成root权限的吧?答案是:不,内核管天管地,总管不到程序自己偷看自己的数据吧?我们想办法把我们的代码塞到被剖析程序中去就可以了! ​ 刚才提到了ld的LD_AUDIT,这次就轮到它的兄弟——大名鼎鼎的LD_PRELOAD——登场了。想法是这样的,我们的profiler其实只需要在程序开始的时候执行一个定时器,以后每次定时器执行的时候去抓取我们的样本就OK了,所以我们完全可以把自己伪装成一个人畜无害的动态库,等到别个程序有意无意加载到我们,哼哼……事实上,很多profiler都是采取类似的策略,比如google-perftools,再比如heaptrack等等。 编码实战 ​ 废话少说,放码过来! ​ 我们在QtCreator中创建一个动态库项目 simple-profiler,主类 SimpleProfiler。首先,我们需要设置好我们的定时器: void SimpleProfiler::enableProfile() { int ret = setitimer(ITIMER_PROF, &m_tick, nullptr); if ( ret != 0) { fprintf(stderr, "failed to enable profiler: %s", strerror(errno)); } } 根据 setitimer 的man文档,计时器主要有三种类型: ITIMER_REAL 这个计时器是根据墙上时间进行倒计时,最终触发 SIGALRM 信号; ITIMER_VIRTUAL 这个计时器是根据进程花费在用户空间的 CPU 时间进行倒计时的,最终触发 SIGVTALRM 信号; ITIMER_PROF 这个计时器是根据进程话费在用户空间和内核空间的 CPU 时间进行倒计时的,最终触发 SIGPROF 信号; 个人认为,假如都是用在 profiler 上的话,第一种计时器用来查找程序执行慢(某个函数有IO等情况)的瓶颈比较有效果;后两种计时器用来查找程序 CPU 占用瓶颈比较有效果。不过使用第一种计时器的话,对被追踪程序的执行影响相较于后两者就比较大了,所以这里采用第三种计时器。 Read On →

初探Linux内核态——通过proc文件系统作快速问题定位

文章翻译自 Peeking into Linux kernel-land using /proc filesystem for quick’n’dirty troubleshooting 这篇博客的内容完全是关于现代Linux内核的。换句话说,指的是与RHEL6一样使用的2.6.3x系列内核,而不是古老的RHEL5所使用的2.6.18内核(都什么鬼了?!),虽然大部分企业都还在使用RHEL5。另外,这篇文章也不会涉及内核调试器或者SystemTap脚本之类的东西,完全是最最简单地在有用的proc文件系统节点上执行“cat /proc/PID/xyz”这样的命令。 定位一个程序“运行缓慢”的问题 下面要举的这个例子是这样的:一个DBA反映说他们的find命令一直运行缓慢,半天都没有什么输出,他们想知道这是为什么。听到这个问题的时候我就大概有直觉造成这个问题的原因,但是他们还是想知道怎么系统地追踪这类问题,并找到解决方案。刚好出问题的现场还在…… 还好,系统是运行在OEL6上的,内核比较新,确切地说是2.6.39 UEK2。 首先,让我们看看find进程是否还在: [root@oel6 ~]# ps -ef | grep find root 27288 27245 4 11:57 pts/0 00:00:01 find . -type f root 27334 27315 0 11:57 pts/1 00:00:00 grep find 跑的好好的,PID是27288(请记好这个将会伴随整篇博客的数字)。 那么,我们就从最基础的开始分析它的瓶颈:如果它不是被什么操作卡住了(例如从cache中加载它所需要的内容),它应该是100%的CPU占用率;如果它的瓶颈在IO或者资源竞争,那么它应该是很低的CPU占用率,或者是%0。 我们先看下top: [root@oel6 ~]# top -cbp 27288 top - 11:58:15 up 7 days, 3:38, 2 users, load average: 1.21, 0.65, 0.47 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie Cpu(s): 0. Read On →

15.5研发心得

迟到的经典 2017年11月29日,农历十月十二,经过一番挣扎,deepin 15.5的ISO终于安静地躺在了内网服务器上,静待着属于它的时刻的到来。 是的,deepin在重新定义了十月一日为农历十月初一以后,甚至连“保证月底发布”的底线也没有守住,妥妥地把发布时间拖到了十一月(阳历)中旬。即便如此,我也觉得这次“迟到”是值得的,在“手机不赚钱,交个朋友”的时代,PC操作系统的研发需要特别用心,才能留住那些对我们期待了那么久的用户朋友。我想,在未来可以预见的时间内,所有deepin的用户都会记住这个特殊的版本号:15.5。这个能让我们在视觉体验上有质的飞跃,在应用包格式上走在世界前面,自带修复工具箱——live修复系统,并且在稳定性和易用性上大幅提升的版本。 deepin15.5注定成为经典。 故事 按照传统,一年中各大版本的主要功能都是预先定义好的,搭配一点重要的bug修复和用户体验改进,基本上就妥妥的了。但是15.5是个奇葩。在七八月份定义15.5详细需求的时候,我们梳理github上的issue,发现一条一岁半“高龄”的主题,大意是“跪求高分屏支持”;同样早在16年初,公司成立了一个神秘的组织叫“Alpha Team”,这个小组的第一个任务就是“独立包格式”;在记忆都稍微有点模糊的14年,就有用户想要在deepin下创建热点……这几个严重拖延的任务让人汗颜,所以我们当时就任性地决定15.5主要来解决这些问题。虽说是决定,但是并没有人特别自信,“毕竟是拖了这么长时间都没有解决的问题”,再加上高分屏涉及面太广,深度全家桶都要“挨刀子”;独立包格式本身社区也不统一;WiFi热点挑硬件,Linux下的网卡驱动又不都是那么好……越想越恐怖。 “要不再加点其他任务?”,我提议。 众人惊恐状。 “这样万一前面几个任务完成不了,做点其他任务应付一下老王嘛”。 逆向思维有时候还是挺管用的。 就这样,像是一锅羊肉火锅一样,15.5的配菜变成了主菜,也就是前面提到的三个点;又加入了新的配菜,VPN导入导出、应用代理、触摸板手势、色温调节、bug修复和其他一大波新应用等。 当所有人都以为15.5就这样的时候,一个不识趣的朋友跟老王说我们系统的恢复模式进不了root,所以系统一旦出了问题就只能靠重装大法解决。我闻风一边心想绝对不可能,一边赶紧试了下,结果是果然不好用。 还没等我返回神儿来,老王已经在Tower上建好了“live系统支持”的任务。 高分屏 高分屏支持的话题由来已久,大概是在我刚进入deepin(14年)的时候就有人在“布局”:图片资源一定要用svg、尺寸不能写死等等,然而坚持了一段时间以后,大家发现这种坚持似乎毫无意义,因为没有人用高分屏,自然发现不了高分屏那种细腻到看不到“痘痘”的美,于是乎慢慢地各种png、死尺寸就满天飞了。 俗话说“出来混总要还的”,因为以前的任性,在适配高分屏的过程中,deepin团队可谓吃尽了苦头。不仅几乎所有程序中用到的图片资源都要重新绘制(还好图标主题一直坚持svg),还差点在x2.png的道路上栽了个跟头,还好悬崖勒马,及时止损。 普通应用适配高分屏在如今的环境下,Qt和GTK等界面库的高分屏支持已经比较成熟,还算是比较简单的。但是桌面环境和一些特殊应用,如启动器、截图、录屏等,就需要些功夫了,在适配的时候还要考虑缩放前后的窗口大小、窗口位置等等,恰巧这些地方Qt的处理又比较坑,有时候实在受不了了,只能patch Qt来处理。 看图的适配也比较麻烦,很多地方都用到了缩略图。缩略图也要支持高分屏!听起来有点好笑,但事实是不仅是缩略图,很多情况下一条线、一个圆角的瑕疵,在高分屏下都可能被放大,变得非常恼人。 15.5的细腻就是在这种情况下“磨”出来的。 Flatpak Flatpak其实原名叫“xdg-app”,可能后来觉得不够高端大气,配不上“The future of application distribution”的名头,遂改名Flatpak。 按照官网的说法: Flatpak is the next-generation technology for building and installing desktop applications. It has the power to revolutionize the Linux desktop ecosystem. Flatpak将会改变Linux世界的生态。 不谋而合,同样这样想的还有snap技术。 snap是Ubuntu为了布局服务器和容器市场推出的一套解决方案,与Flatpak类似,它也是利用Linux内核提供的沙盒机制和方案,再加上一套包分发、安装、更新和卸载的辅助系统,来实现应用与系统隔离的想法,以解决目前Linux世界包分发过程中经常让人头疼不已的依赖问题和系统安全问题。 在两者之中,deepin毅然选择了Flatpak,为什么?因为从Mir vs Walyland的例子中,我们发现一个非常真实地存在于开源世界的“潜规则”:“政治不正确”的项目,在开源世界中一般是无法长久的,其中所谓的“政治不正确”其实就是“g家族”已经有同样的项目存在,又有人造了“轮子”。所以,与其寄希望于一个可能不能长久的项目,还是在Flatpak上孤注一掷来得靠谱一点。 想法虽然显得投机了点,但是像往常一样,deepin团队做起实事来一点也不含糊。深度全家桶中的成员,非系统级的应用,全数被打成了Flatpak包。重要的是,这些Flatpak包已经在15.5的ISO中替换了原来的deb包,也就是说deepin 15.5可能是全球第一个预置了Flatpak和自家应用的Flatpak包的发行版了。 “少数人活在未来,人们中的大多数则是静待着未来的降临,这是整个人类文明的演进方式”,最近耳朵里总是充斥着这样的声音。我想deepin团队在推动Flatpak上是走在世界前列的,为身处这样的团队感到骄傲。 live修复系统 对于喜欢折腾系统的用户来说,这次可能最期待的就属live修复系统了,它是个什么东西呢?可以这样简单理解,live修复系统就是一个超级mini版的deepin系统:除了量身裁剪过的DDE外,只预装几款必要的系统工具。最重要的一点是,live修复系统独立于你所安装的deepin系统,完全运行于内存中,这样,你就不会遇到在你修复系统到一半的时候系统弹出警告框,告诉你需要卸载某个磁盘之类的尴尬情况了。 在live修复系统中,预置有深度全家桶的一位新成员“深度备份还原工具”。这个工具具有化腐朽为神奇的超级牛力,它可以助你轻轻松松地把老系统上的数据迁移到你的新硬件上:全新的机器内部,还是熟悉的老伙计——deepin。 live修复系统为了保持简单、简洁,目前除了必要的浏览器、备份还原工具和终端外,并没有预置更多的工具和应用,毕竟要完全跑在内存里嘛。在系统中安装上live修复系统,打开启动器,你甚至感受不到它的存在!因为它的入口确实不在启动器里面,而是在grub菜单。好的功能/用户体验就是这样,需要它的人一定知道它在哪,不需要它的人完全没必要因为每天都能看到它而感到不自然。 在可预计的将来,应该会有更多实用工具登陆live修复系统,让你进入live修复系统,就感觉到自己像是被武装到了牙齿。 其他 每次介绍新功能,都不得不辟一个“其他”的栏目,因为新的变动实在太多,其中有些像网易云音乐新版一样,内部真刀实枪地大改造(用qcef替换原来的webkit),但是用户可能不会有太多直接感知的;还有一些“彩蛋”类的像是本次的“自动色温调节”,有些用户发现这个功能后溢于言表,幸福感可能都超过了使用这个功能本身的;另外的一些工具类,如Wi-Fi热点、VPN导入导出的工具类功能,天生就是理科男的命——绿叶。 在deepin系统的完整度方面,指纹识别算是这次的另外一个亮点了,如果你的电脑配备了指纹识别器,那么升级到15.5,你将从输入密码这项繁琐的工作中解放出来,一切都是那么顺滑。 Read On →

给小崔的基础管理课

最近小崔的日子好像不太好过,负责一个项目的同事发了farewell letter,于是她被莫名其妙地选中来担任整个项目的负责人。 这突如其来的变动,打了小崔一个措手不及:因为给同事分配任务不顺利气哭、因为担心第二天的工作是否能很好完成而失眠……就跟我刚开始担任深度桌面组组长的时候一摸一样。看着实在心疼啊,于是趁着今天天气好出去晃悠的时候顺便跟她传授了一点小小的经验,这里顺便记录一下,希望对有需要的朋友有所帮助。 在说初级管理的经验之前,我想强调一下“自信”,因为这是我觉得一个人能做成一件事情最基础的基础。如果连自信都做不到,那就不要妄谈管理了,你甚至连自己都做不好。小时候我妈一直说谦虚使人进步、骄傲使人落后,让我平时谦虚一点。我当时想不通,现在依然想不通,我甚至觉得自负要比自卑强得多,这是因为自信心实在是太难培养了。比如我虽然一直对自己的学习能力和技术比较(盲目)自信,但是我刚做管理的时候,其实也不自信能把所有人捏到一起、团结起来,但是因为心里面有执念觉得不能把做不到跟自己扯上关系,所以还是努力地去尝试,很清楚地记得有一次我当着所有人的面把自己的完整解决方案说出来那一刻,我的自信心才完全建立起来,之后的管理就相对容易了很多。说到小崔,我大概是不担心的,她只要把自己在镜子前臭美的状态转化一下,自信心应当是爆棚的 😄 自信做好了,用来做什么呢?这就是管理的内容了,管理不再是扎头自己的事情,而是掌握大局,在掌握大局以后在处理非自己处理不可的事情。什么是掌控大局?我觉得分两个部分:承上和启下,承上就是了解清楚上级的需求和工作内容;启下就是把需要做的事情分配给自己的组员,让他们清楚自己工作的内容,这个部分其实是管理的核心,后面会提到我的秘诀!什么又是非自己处理不可的事情?这绝不是自己什么都不做,所有事情一股脑塞给下属同事,而是在了解清楚工作内容以后,把那些能提升团队工作效率的事情或者实在是只有自己才能做的事做了,自身做则才能做到服人。 因为初级管理承上启下的特点,所以这种工作其实有时候特别难做。我从朋友那里学到了十个字,感觉对我的管理工作有着非常关键的指导作用:对上要有胆,对下要有心。仔细揣摩一下,其实不难发现这其实是在约束一个管理者的行为:面对上级领导的时候,不要老感觉自己是个小兵,要大胆跟对方进行沟通,因为你代表的不仅仅是你自己,还有自己的下属同事;面对下属同事的时候,不要感觉自己官大一级压死他们,其实你跟他们是与荣俱荣与损具损的共生体;这对初级管理尤其重要,因为初级管理更像是战场前线的班长,你连面对自己上级的胆量都没有,何谈面对敌人的炮火?你不把自己的班子成员当兄弟,谁会给你当炮灰? 当然,就算你做好这些了,做得非常好了,也不一定能让团队里面所有的人都服你,你一样会遭受挫折、遇到不顺利;这里首先要想到的就是:“如果这件事情简单,哪还需要老子上?” 在这种心态/格局下,再去看待问题可能会更容易接受一些;做管理,容忍度一定是要有的,因为林子大了什么样的鸟都有,在一时半会改变不了别人的情况下,只能让自己学会接受现实,伺机而动。情绪控制也是要有的,下属情商不够,也不能让自己失控,有情绪很正常,不然变成一个冷血的混蛋,没有人会跟你真诚,这样的管理就像是古代的暴政,总会被推翻的。有情绪代表你是一个有血有肉的人,但是也不要让情绪化过多干扰自己的理智,最最基础的也是要做到不要让情绪影响到工作。 这看起来很难,但是只要转换心态就可以让自己好过很多,比如你给对方分配任务,对方无理由拒绝或者态度恶劣,你可以想:“对方拒绝做或者做不好的事公司的事情,又不是自己的事情,犯不着跟对方闹情绪”。对,管理就是要这么灵活,该把公司的事当成自己的事的时候,拼死了干;该把不相干的事情甩出去的事情,就要爽快的甩出去。至少这个时候你无能为力了,这样安慰安慰自己,让自己平复情绪还是很有用的。不要怕沟通,尤其是跟刺头的沟通!那天做到了“今天就算是吵翻了天,明天还是要像一个没事人一样去跟对方相处”,基本上在这方面算是合格了。 还有一部分没有跟小崔聊的,大概涉及到项目管理的事情,还比较重要,所以提一下。分出去的任务,要定期做检查,毕竟公司有管理是为了管人,但是最终的目的是把事情做好。分出去的任务,反馈回来的至少需要有完成的时间和安排,拿到安排后按照自己的经验核算一下是否合理,如果不合理就需要跟对方再进行沟通,合理的话还要提前检查,不检查的时间相当于没有定!其实项目管理的精髓就是这个:计划、检查和沟通,其他的方法论都是技巧性的表皮罢了。 根据我这几年的工作和生活经验,说一下我的“困难观”。面对困难一般有两条路可选,第一是消极面对,相信这个事情总会能熬过去的,等熬过去了,又是春光明媚。这种一般在面对自己完全非自愿但又不得不去抗的事情时用来安慰自己,让自己不至于分裂、崩溃;另一个是积极面对,相信自己的聪明,找到问题的关键,搞定它,解决这个困难,你自己也会有所提升;这种情况我一般都把困难拆分成一个一个的难题(拆解问题的能力也很关键,因为暂时不需要,等以后再聊),像福尔摩斯一样运用自己的智慧去解开每个难题的答案,这样的面对困难重重的生活才不会觉得枯燥无味。 最后,不管使用哪种方式处理现在项目上的问题,我觉得都是对自己的一种磨砺吧,希望小崔可以顺利度过难关 :3

神奇的isatty

前些日子才从apt-get命令系列换成更为时尚的apt系列,作为一个debian系发行版——deepin的开发者,我表示很汗颜……新的apt命令除了在功能上将apt-get、apt-cache等几个命令统一到了一个命令上外,更是有了不错的TUI,如文档所说: The `apt` command is meant to be pleasant for end users and does not need to be backward compatible like apt-get(8). 毕竟,还多了进度条呢…… 😂 不过这不是今天要说的重点,换到apt以后,把apt操作的一些结果跟管道结合一起用,经常会收到警告,例如: (ssh) hualet@hualet-PC : ~ [0] % apt search deepin | grep -i superstar WARNING: apt does not have a stable CLI interface. Use with caution in scripts. CLI的输出也算是API要保持stable么?汗颜again……dtk作为一个系统级的开发库都还没有到stable的状态、某in公司的CTO写得命令行工具,第二天接口就全变了😂……敬畏之余,困惑我的倒不是这个警告的内容,毕竟新的东西都不保证稳定么,但是apt是怎么知道它的输出被连到管道了呢? 一直没空处理,直到昨天,又一次遇到了,遂记下,晚上思来想去没什么想法,遂请教前文提到的不靠谱CTO,丫直接甩过来一句: “istty检测output啊,很多命令行程序都会根据这个做不同的反应” 我:“man istty没有结果啊“ 他:”你man page没装全吧?“ 我默默敲下sudo apt install manpages-dev,显示已经安装了…… 我:“装全了啊,我Google一下吧” 他:“肯定没装全,应该是在libbsd或者termios里的吧……“ 信誓旦旦。 我默默Google了一圈,发现那个函数其实叫isatty,在unistd.h里面定义 我:“你是不是记错了,有isatty,unistd.h里面的……” Read On →

输入法消失之谜

最近不少用户在deepin论坛上报告说搜狗输入法的图标不见了,收到反馈我就心想坏了,我的输入法图标很早前就消失不见了,之前发现这个问题但是没有去跟踪是因为没有看到其他同事出现类似情况,我的电脑平常为了调试用户反馈的bug又经常XJB装软件,觉得是个例。现在收到多人反馈,大概又是什么“更新事故”? 带着沉重的心情,首先要确定的是这个问题影响的范围: 15.4.1的ISO是不存在这个问题的; 不用输入法的老外是没有受到影响的; 只有少量论坛用户报告了这个问题,大部分人表示更新到最新也没有这个问题; 还好影响范围还比较小,那么下一步就是找解决办法了: 想办法绕过?对于这个问题来说好像不太好使; debug找到问题的根本原因; (注:其实用户反馈是集中在这两周的时间甚至更短,如果是其他人的话可能会去排查最近更新了什么包,但是我刚好很早以前遇到了这个问题,受其干扰,所以走了一条冤枉路……) 下面进入本文主题,怎么去debug?以前压根儿没有调过输入法的问题啊,遂去请教公司大神,大神表示:”我也不知道啊 (无奈脸 ”~ 那么我们只能瞎猜了: 第一步:卸载掉搜狗,排除是否是搜狗输入法(问题多多,值得怀疑)导致的。 结果显示卸载掉搜狗输入法以后,小企鹅的图标可以正常显示,看来果然是搜狗输入法导致的? 第二步:下载官方搜狗搜狗输入法,重新安装,排除搜狗输入法版本的问题。 重新安装后没卵用。但是突然想起来搜狗在家目录下的.config/sogou-qimpanel/skin 里面有皮肤缓存,据Google说是皮肤有可能导致输入法图标不见的问题……我们在做2D极速版适配的时候,玩了点黑魔法,替换了一些资源文件,可能是改坏了什么东西? 第三步:删除皮肤缓存,排除修改皮肤的问题。 没卵用…… 陷入僵局,但是发现如果将sogou-qimpanel这个进程杀掉,输入法的图标就会显示出来了……那么估计是这个进程负责读取sogou的皮肤文件然后更改输入法图标,中间可能出现了什么岔子? 第四步:使用strace跟踪sogou-qimpanel,感觉胜利在望。 $ killall sogou-qimpanel && strace -e open sogou-qimpanel 打印着打印着,吭哧,sogou-qimpanel尼玛居然退出了……什么鬼,再次尝试,还是退出了。看来是daemonize了?那么strace attach到子进程呢?貌似关键的信息已经丢了……陷入僵局…… 如何在系统级别追踪呢??? 第五步: 看来要祭出大杀器systemtap了,随手写(抄)了一个stp: probe syscall.open.return { printf("%s %s", filename, execname()) } 运行失败…… WARNING: never-assigned local variable 'filename' (similar: name, __nr, retstr): identifier 'filename' at sogou_qimpanel_open.stp:2:20 source: printf("%s, %s", filename, execname()) 请教公司另外一大神,大神表示“你装一下kernel的debug包就行了……” 结果,还是不行……坑…… Read On →

2016年终总结

自从开始上班,每年年终总结都少不了,因为都是给老板看的,内容无非是今年我做了什么事情、多牛逼、对公司贡献多大云云,万一老板看到一件他不记得但是你写下来的工作贡献一高兴,说不定给你升职加薪,一年也就不算白干了。但是,写给自己的年终总结哪能这么应付,梳理整理自己一年的得失,做好权衡,最重要的是吸取经验做来年的规划。 2016关键词:累、读书和成长 2016年是挺累的一年,不知道是不是整个前半年和2015年的后半年都在加班的缘故还是什么,即便是后半年没怎么加班的时候,也没感觉怎么轻松。其间必然有些成绩,但也带来了很多严重的问题,例如我长期状态不佳、思维不清楚等,总是感觉有点得不偿失。最后的两个来月,我都在认真思考这些现象产生的原因,总结下来问题可能出在两个地方: 一、工作方式不佳,最主要的问题是贪多和多任务并行; 从年初接下来整个社区版的发布和维护工作以后,整个人进入了一种所有事情都想帮着处理的状态,写代码、管理、调试问题、支持售前、支持工程、社区反馈等等,一天到晚地干,似乎没有什么尽头;以至后面养成了多任务并行的坏习惯,做什么事情都集中不了精神,长此以往,不要说提高工作效率了,整个人都快废了。 二、生活方式不佳,最主要的问题是不够自律; 深度一天的工作时间如果不算加班其实到不了8小时,但是这个不到8个小时中我几乎有7.5个小时都在写代码(大部分工作日,有些需要讨论产品需求、开会等略去),中间几乎没有任何break,这几乎回到了14年中的工作生活状态——我几乎丧失了良好的口头交流的能力;这样的一天下来,晚上能干嘛呢?吃饭、游戏和睡觉呗……但是,问题是有些时候还要加班,加班完了回到住的地方连玩儿会儿电脑都不能就睡觉也太“亏”了吧?于是控制不住自己的玩儿过了睡觉时间,长期睡眠不够,这也直接导致了我思维变得特别慢。 确定了问题根源,肯定要治病根儿啊,针对工作方式的问题,我开始强制自己使用番茄钟,并尽量将自己的任务分摊开来;针对生活方式的问题,除了尝试早睡早起外,我也开始尝试跟别人闲聊(主要在微信上),让自己的大脑变得活跃;顺便逼迫自己抽出时间来读书,读书这件事情既能涨知识,还能磨练耐性、让自己的注意力集中起来。 说起读书,16年后半年读的一本非常火的书《软技能——代码之外的生存技能》,它之所以火,我想主要是因为它似乎给程序员打开了一扇门,这些平常只会钻研技术、敲代码的人突然发现,卧槽原来这不是生活啊!一直觉得程序员们是一群很神奇的物种,他们自认为是世界的主宰,但是真相是他们简直是生活不能自理……同时,这群脑子很聪明的人,比其他人更容易接受改变和思想上的冲击。至少这本书让我开始反思自己对待生活的态度、对待薪资的态度、对待投资理财以及社交的态度;书与其说始给程序员写的,到不如说始给所有人写的人生规划课程:学习新技能、找到新工作、营销自己、自由职业、理财和投资等等,我觉得工作的人都应该看一下。 另一本值得一提的书《梁启超教子家书》,这本书我觉得我要么评0分,要么评100分,它好是好在书里面梁启超的家书原文,至于作者整理的一些结论,个人觉得没什么可以吸收的东西。从那么多的家书中,除了可以窥探一番我比较神往的民国生活,从中理解出来的梁启超让我对这个历史人物有了翻天覆地般的认知改变。梁的爱子、博学、社交和投资,这跟前面的《软技能——代码之外的生存技能》这本书似乎遥相呼应,就是在告诉我,你需要改变了! 当作故事读的书例如《红顶商人胡雪岩》和《老残游记》等,其实给我的启发也是蛮大的,胡雪岩的冷静、睿智和大方,老残的淡泊、生活观和使命感(包括作者刘鹗的经历),都让我在生活中处理一些事情的时候有了些个参考;带着功力目的去读的《旅行与读书》、《逻辑思维——成大事者不纠结》等,也能按照预期给我涨涨见识;不期而遇的《解忧杂货铺》,读起来酣畅淋漓,故事也够精彩;2016年(后半年),在微信读书上花费时间116个小时,完整读完的有8本书,还有些零散着读一些丢一些的,这一年也算是个好的收场了。 说起成长,首当其冲的就是经历了一次分手和复合,其中酸甜苦辣,旁人绝不能理解,对我也是一次比较大的考验,让我对待生活、对待另一半有了跟之前完全不一样的转变,我很庆幸这些事的发生在25岁,而不是更晚;2016年我也开始感受到了生活的压力、结婚买房的压力,这些压力促使我去做一些改变,去践行我在书中、在生活中学到的一些生活方式,去担负起责任;这一年通过工作,我更加了解自己的成熟范围和做事风格,我愈加能够掌握做事的分寸。 2016,这是非常精彩的一年。 2017目标关键词:高效、读书、旅行 高效分两个,一个是专注于一两件关键的事情,做好;一个是调整自己的工作状态;读书不消说,这是个会上瘾的东西,好书推荐好书,好书推荐好人,好人又推荐好书,无穷尽也;旅行业分两块儿说,一是出去走走,二是组织一些线下聚会;做到这些2017年也将是非常精彩的一年! 另外,2017年准备把份子钱都收回来,哈哈哈!

12月10日回洛阳记

2016年12月10日,我们宿舍老五结婚的答谢宴,刚好又在我们大学所在的城市洛阳举行,哥们儿几个商量着都回去一趟,互相见见自己几位久未蒙面的兄弟,到场的有深圳来的老大、洛阳本地的老三、新乡来的老四、东道主老五、上海来的老六、北京来的老七和武汉来的我。能够成行着实不易,简单记录一下,留作纪念。 9号晚上从武汉出发,卧铺10号早上到的洛阳。下车发了一个朋友圈: “毕业后就没有来过的城市 洛阳,你有点冷啊😢” 相比江城武汉,洛阳显得要冷得多,去的时候觉得“绝对没问题”的羽绒服已经显得不太够用了。火车站旁边的公交车站,虽然大早上已经开始忙碌起来,但还是那么井然有序;又冷又困,我给五哥打了个电话,问清楚酒店地点,上了熟悉而又陌生的68路。 时间过得总是飞快,上面一幕幕清晰的画面,在现在我码字的时刻,已经是两三天前的场景。这次回洛阳,除了兄弟们一块儿给老五庆祝了婚礼,一块儿吃吃喝喝,还顺带逛了我们的新、老校区,觥筹交错的瞬间,总是感觉回忆满满: 想起了新生报道,先来的瓜分五个下铺;想起了新生拍照,霸气的女生周培一怒之下甩了照相老师一脸;想起了第一次在大学过自己的生日,整个宿舍一块儿出去吃饭,喝了四年最多的一次啤酒(12箱?);想起了用别人的mp4,每天窝在宿舍,一年看了比前18年看得电影总数还多的电影;想起了因为被班长逼着去参加脑残活动,甩了班长一脸;想起了跟宿舍人一块儿打篮球,80后vs90后,打中锋,单手抓篮球;想起了09年大雪,排长队走雪中的一条小径去食堂吃饭,重庆来的老八因为没见过下大雪,翘课出去看雪;想起了唯一一次看世界杯,跟着球迷舍友在4号教学楼一块儿嘶吼;想起了第一次参加文艺晚会比赛,唱王力宏的《龙的传人》;想起了用老九的手机,看电视直播《武林风》;想起了从老大哪里看到的《藏地密码》,他没有看,反而一口气被我看完;想起了一个夏天晚上跟着看了《午夜凶铃》,一个星期没有睡好觉;想起了那个夏天睡宿舍楼顶,早上的大太阳晒的皮肤瘙痒…… 想起了联盟公寓,我买了不到一周的自行车丢了;想起了联盟食堂的面条;想起了洛阳公交车,能随时为了老弱病残停车;想起了人生中第一次去电影院看电影《加勒比海盗4》,也是我看的第一部3D电影;想起了小崔来洛阳找我,跟做梦一样;想起了跟舍友一块儿去做兼职,促销九阳豆浆机,一连站了七天;想起了有虫子的宿舍,宿舍的人不得不三番两次把床板拿到下面用热水烫;想起了我独自上自习,陪过看了所有计算机专业课本的自习室;想起了同样的自习室,小崔因为放了个响屁,非要让我去领她;想起了差点挂掉的机械设计和机械原理,那课压根儿没人愿意上;想起了偶然发现的一个评四大名著的选修课,晚上冒雨也要去听;想起了龙潭峡、天池山,那些洛阳周边的风景区和无忧无虑的大二时光;想起了大家一起看《那些年我们一起追的女孩》,一起听《让青春继续》…… 那天晚上一直玩儿到2点,在KTV唱歌从流行歌曲一直唱到《猴哥》、《葫芦娃》……回酒店又聊天到四点,好像恨不得以后的话就在那天晚上能说完;但是该来的还是回来,老七要去郑州买房子、老大要赶飞机,天下没有不散的筵席,喝碗牛肉汤,各自上路。

楼兰餐厅

这个星期有点浪过头了,周六出去打了羽毛球,周日又出去觅食,文章呢?代码呢?sigh……不过周日的觅食还颇为成功,倒是可以叙叙,补补文章的缺。 楼兰餐厅,一个以新疆地域美食为主题的餐厅,是一个大口吃肉大口吃馕的地方,第一次听说还是上周偶然看到表姐的朋友圈,配图中的烤羊排看着烤得焦黄,卖相相当好,仅这一点便深深地吸引了我,遂决定这周即使浪过头也要去尝一尝。中午十二点到世界城五楼,果然要排长队等候,越加坚定了我这个餐厅不错的信念。 半小时后,终于可以进店享用美食,我俩食量不大,所以只点了四份菜(好像也不完全叫菜,不好称呼), 因为是第一次来,所以菜都是根据感觉来点的,但是我感觉确实刚好凑出了一个比较好的搭配: 第一个上来的是酸奶哈密瓜: 可能是因为用餐环境比较热或者其他的缘故,酸爽的酸奶搭配香甜的哈密瓜,让人的味觉神经突然就活跃起来,人也精神多了;喝了两口小崔急忙制止:“烤羊排肥,吃了肉再喝酸奶,就不会觉得腻”。果然美食家呀,我心悦诚服,放下勺子。 很快,便等到今天的主角大漠烤羊排: 名字听了只让人联想到楼兰古国覆灭后的一片大漠,自古多少英雄战死的地方,想着略悲情,只能吃口烤羊排排解。话说这羊排真不错,外焦里嫩,不管是配酱汁还是佐料,都能让人食欲大开(跟着小崔吃了不少韩国烤肉,完全是两种风格)。吃了两块,大呼过瘾但是也略觉肥腻,这时候吃两口酸奶……写得我现在口水直流…… 楼兰肉囊和牛肉汤揪面差不多是同时上的: 可能是本能上觉得饼和汤搭配吧,就像羊肉泡馍的汤和饼搭配一样,我们点这两样的时候相当默契。事实证明,小崔非常具有美食家的风范,饼是牛肉馅的,配有洋葱,虽然一点都不腻,但是搭配酸爽的牛肉汤,有更上一层楼的美感,肉馕和汤在嘴里相遇的那一刻,真有一种一辈子就这样罢的感觉。实话说,汤的配图有点失败,其实里面有面片一样的面和牛肉片,配有各种蔬菜丁,如果单卖的话我估计可以喝两碗 。 中间小崔也是乐的不得了,原来除了韩国烤肉,还有这么好吃的东西叻,我就顺势盗了她的一张“全餐图”: 食毕,买单走人!