Archives for Post

dss 编译问题小结

主要遇到两个问题,比较有通用性,记录一下: 1. -lpthread 修改为 -pthread 2. -ldl 修改为 -Wl,–no-as-needed -ldl 在linux编译遇到 undefined reference to pthread_mutexattr_init undefined reference to dlopen 可能跟这两个问题相关。

EFI/GPT上的Windows – Linux双系统

很长一段时间都没有鼓捣重装系统了。前些日子旧笔记本坏了,买不起MBP的咱只好入手了一台惠普的win8系统的本本。 近来需要一个linux环境进行线下测试,这台本本就成了实验对象。本以为装个linux还不简单么,装个ubuntu分分钟搞定的事情,没想到居然屡遭挫折。最简单的方法就是通过easybcd软件进行硬盘安装了。然后遇到的第一个难题就是怎么重启机器。win8新的电源管理模式,所谓关机其实只是打瞌睡。网上查到在控制面板-电源管理中可以关闭这个功能。OK,重启。进入引导界面却引导失败,提示找不到文件。这个问题纠结了很久,我以为是自己填写的磁盘号错了,通过存储管理可以看到除了系统可见的C盘D盘E盘外,还有好几个分区,此时我还没了解到这是GPT分区表的特征,从(hd0,0)到(hd0,5)试了个遍,通通无效。 经过这么多纠结我终于决定放弃硬盘安装,转而采取刻录光盘安装,还好新本本光驱还没坏(不得不吐槽下本本光驱的脆弱身板。。)。结果再次挫折。。光驱引导界面进去之后无法进入到liveCD的试用模式,也无法直接安装,于是使用检测光盘那个选项吧,统统黑屏,进去光盘也不转。试用模式的最后会输出两行字,说是无法从cd0的某扇区读取数据。莫非是烧CD烧坏了?于是再烧一张,并且烧写结束的检测光盘步骤也检测正确了,ubuntu的iso检测checksum也检测正确了,应该没问题了吧,用新盘重试,还是一样的问题,甚至提示错误的扇区编号都是一样的,我看着状况应该不是烧写的问题。 只好再度重启去BIOS看看了(其实应当是叫做EFI,这个时候我还没意识到这个问题)。发现boot option中有一个选项是开启legacy support模式。注解中说这个模式用于引导win7及以前版本,推荐不要开启可能会导致(win8)系统无法引导。我晕,估计问题就出在这了。首先先不管一层层的警告先把这个选项开了,然后我也注意到这说明这台机器的引导方式已经与以往不同了,以往的引导方式已经是legacy了。。 重启之后还有提示,说有延迟的修改,不顾各种警告允许修改生效,再次通过liveCD引导,终于可以进入熟悉的ubuntu试用界面了。不管那么多进入安装。根据ubuntu以往的尿性,应该是对windows超级友好兼容,不用担心引导项问题的(我还是没意识到EFI这个问题的严重性)。结果装好发现就是败在这个疏忽上了,grub没有正确地安装,还是直接进入到windows引导界面了。 不过这时候已经知道病因了,那么在网上求医问药就比较顺当,找到了许多文章,介绍了许多不同的解决办法。我采取的是这篇文章中介绍的办法,通过liveCD进入ubuntu后,挂载sda2,这是gpt的引导分区。其文件夹结构为 <DIR> Boot <DIR> HP <DIR> Microsoft <DIR> Ubuntu 其中Boot文件夹中有Bootx64.efi文件,Microsoft/Boot文件夹下有Bootmgfw.efi文件,Ubuntu文件夹下有grubx64.efi文件。可以看出Ubuntu安装程序已经安装了Ubuntu的引导文件,可是EFI系统没有识别出新的引导项,依旧直接启动了windows的引导文件。由于对EFI也是昨天折腾这个事才刚从网上了解,我还说不出所以然,为什么Ubuntu的安装程序无法正确替换windows引导文件,并且事实上ubuntu自动生成的windows引导项也是错的无法启动windows。应该说是新设备加上新系统吧,兼容工作不可能那么快跟得上。 网上提供的另一种解决方案是将linux引导信息写到U盘,通过U盘启动linux,这样做就避免修改windows的引导文件,应该说是方便企业级客户吧。这个方案来自linuxsir.org。可是对我来说太麻烦,不想采用。于是还是使用了上面引用的方案,将Ubuntu引导文件强行替换windows的引导文件,并将ubuntu的grub中增加一个项目,指向原来的windows引导文件(备份更名),从而解决问题。不得不佩服下这个方案的作者,这样强行替换引导文件确实是需要足够的知识和勇气的。。。 这里说明一下,我的系统引导文件分区与文章中一样是sda2,但可能不同系统不同,可以分别挂载查看一下目录结构就能确定具体是哪个。 好吧,长篇的唠叨说完,总结一下要点: windows 8 电源管理关闭快速启动策略 EFI(BIOS)设置中启用boot options/legacy support(网上说法还需关闭secure boot,我是后来才看到,没有采用) 完成ubuntu安装后用ubuntu的grubx64.efi文件替换windows的bootmgfw.efi文件(注意备份) 在ubuntu的grub配置中增加指向原bootmgfw.efi的条目 当前版本的easybcd暂不支持efi/gpt引导方式(我使用的是2.0.2,文章中称2.2也不支持) 后记 总结完才意识到可能由于我没有关闭secure boot才导致ubuntu引导项安装失败以及easybcd设置启动项失败。由于昨天经历漫长的战役已经重启笔记本30次以上消耗了一整天的时间,暂时没有心情去继续研究了。附上似乎是比较官方的介绍easybcd双启动linux和win8的文章供参考。 how to dual boot windows 8 and linux 最后是参考来源: 关于Windows Boot Manager、Bootmgfw.efi、Bootx64.efi、bcdboot.exe 的详解 全局唯一标识分区表 UEFI模式+GPT硬盘实现Windows 8与Ubuntu双系统启动 在EFI/GPT硬盘上利用grub2实现Ubuntu/Win7等多重启动 Ubuntu官方文档:UEFIBooting – Booting Linux natively […]

python urllib2 重定向时获取cookie

最近用python写一个简单的爬虫,在模拟网站登录时遇到问题,就是登录后紧跟着302重定向,这时候cookie获取没做好,就会登录失败。 网上找了很多文章,可能是因为python版本不同之类的原因吧,很多方法试了都没用。这里踏破铁鞋找到了可用的方案,记录一下,希望能帮到后来的朋友。 鉴于python的版本浆糊问题,这里声明下,我使用的python版本2.7.3,并且使用的是urllib2库。 解决这个问题,其实说起来很简单,就是要自己定义一个RedirectHandler,在创建opener的时候作为参数放进去。 cj = cookielib.LWPCookieJar() opener = urllib2.build_opener(MyRedirectHandler, urllib2.HTTPCookieProcessor(cj)) 这里我还要记录cookie信息因此还使用了cookiejar。 现在难点就在于这个RedirectHandler如何重写了。 urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers) 通过这样一句调用,默认的redirectHandler已经支持在发现302头部的时候自动跳转到新的location去。但问题是返回的response中缺少了前一个请求返回的cookie信息。因此重点是如何在redirect handle中把前一个请求的cookie设置到新的请求中去。 class MyRedirectHandler(urllib2.HTTPRedirectHandler): def http_error_302(self, req, fp, code, msg, headers): setcookie = str(headers[“Set-Cookie”]) cookieTokens = [“Domain”,”Expires”, “Path”, “Max-Age”] tokens = setcookie.split(“;”) for cookie in tokens: cookie = cookie.strip() if cookie.startswith(“Expires=”): cookies = cookie.split(“,”, 2) if […]

Haskell初心—认识Monad

从三月份开始看Real World Haskell这本书,断断续续看到7月份,总算初步对Haskell有了一些认识。 我想,学习Haskell这门语言,第一个门槛就是Monad这个概念。今天初步来做一点总结。 在读书和试着用haskell做一些习题的时候,就会感觉到,haskell是一门实践性极强的语言。当然,他同时也是一门理论性极强的语言,他允许甚至鼓励你用数学方法去推导函数签名,通过定义一系列公理可以对特定类型的函数式进行数学变形,以达到最短最优美的代码形式。 但对于我而言,那些过分抽象的函数和概念,非常难以理解,并且即使是形式上理解了他的定义,还是无法理解他为何要如此定义,有什么意义。Haskell代码的特点在于极端的精炼,许多函数定义看上去什么都没做,像是在说废话。幸好RWH是一本非常好的教材,他通过许多实例来说明这些抽象定义在实践中的用途,让你看到许许多多在实际代码中经常遇到的痛点,在Haskell中都有解药。如同醍醐灌顶般爽快。(请参见代码交叉拷贝悖论) Monad就是Haskell的一个经典设计。它来源于“范畴论”,可以说是数学中的数学,一坨“抽象废话”。我先不去考虑他的数学含义,单看他在代码中如何化繁为简。这里我抄一段RWH中的代码(略简化)。 data MovieReview = MovieReview { revTitle :: String , revUser :: String , revReview :: String } simpleReview :: [(String, String)] -> Maybe MovieReview simpleReview alist = case lookup “title” alist of Just title@(_:_) -> case lookup “user” alist of Just user@(_:_) -> case lookup “review” alist of […]

windows使用其他版本java

换到自己的笔记本上做安卓开发,出现了一个很烦人的问题,就是一直报 Can’t bind to local 86XX for debugger 这样一个错。网上查了一下,原因是jre7不兼容的问题,需要退回到jre6才行。我安装了jre6,又不想卸载jre7,就想,改了环境变量的PATH应该就好了吧。 JAVA_HOME = “C:\Program Files\Java\jre6” PATH = “…;%JAVA_HOME%\bin” 可是修改之后,进入命令行输入java -version一看,问题没有解决,还是java 1.7的版本。这很奇怪啊。 网上继续查了一下,原来java installer会把java.exe复制一份到windows/system32下面,而PATH的特点是先到先得,在系统目录找到java.exe后,就直接执行了。需要把jre\bin的目录在PATH中设置到系统目录之前,就解决问题了。 JAVA_HOME = “C:\Program Files\Java\jre6” PATH = “%JAVA_HOME%\bin;…” 顺带再骂一句java,每个主要版本升级都闹出一堆不兼容来,不知怎么想的。一处开发到处执行这个口号唉。。。不提。。 又记起那时候在公司配置Jira系统的痛苦了。。 参考 Can’t bind to local 86XX for debugger Windows ignores JAVA_HOME: how to set JDK as default?

emacs + cygwin again

两年前我写了一篇博emacs + cygwin fail,说的是在cygwin中使用emacs的种种不便。这些问题已经得到解决。但如今我的需求又有了转变,想在native emacs on windows上使用cygwin作为shell,于是又产生了新的问题。今天看到ownwaterloo在我博客里的留言,想到应该花点时间把以前遗留下来的问题解决掉,于是有了这篇文章。 在emacs中使用cygwin作为shell,可以使用这个cygwin-shell.el http://lists.gnu.org/archive/html/help-gnu-emacs/2010-02/msg00668.html 然后在.emacs中如此启用之 (load “D:\\programs\\emacs-24.3\\site-lisp\\cygwin-shell.el”) 为了方便可以绑定一个快捷键 (global-set-key (kbd “M-s”) ‘cygwin-shell) 重启emacs试用,发现不工作,原来是bash的路径需要填对: (let* ((shell-file-name “D:\\cygwin\\bin\\bash”) 再进去看,可以用了,但是提示符乱码。根据网上的一些讨论,打开bash.bashrc查看 # Set a default prompt of: user@host and current_directory PS1=’\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ ‘ 由于我用的emacs版本支持分色显示,我删除了前面的\w\a部分,保留了分色显示的\u@\h部分。 # Set a default prompt of: user@host and current_directory if [[ $TERM = “emacs” ]]; then PS1=’\[\e[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ ‘ else […]

承认错误—三门问题强力纠错

中午跟基友讨论的三门问题,我一直坚持“1/2”观点还写了很长的博客去分析。 掷骰子的上帝-冷眼看三门问题 到了傍晚,终于被基友说通了,恍然大悟自己的错误。。立刻补博客谢罪。。 基友是个不擅言辞的人,言语上一直没有说出能说服我的道理。但是他的一句话忽然点醒我,说让我写程序试试。虽然我认为写程序测试没有必要,但尝试从程序的角度思考的话,的确,一开始就选定一扇门,并且无论看到什么都坚持不换,那测试100次,这样选中的概率,跟3选1选中的概率当然是没有区别的。只能是1/3。那么跟这个策略相反的,坚持换选另一扇门的策略,一定能把剩下2/3的情况都吃光。 如果这点不够显然的话,可以假设有兄弟二人一起去参与这个活动,每次都是弟弟坚持不换哥哥坚持换。这俩人一定能包揽所有的汽车,并且弟弟获得汽车的概率肯定是1/3,跟3选1的概率相同。则推出哥哥选到汽车的概率应当是2/3。 我尝试用一个比较显然的方法说服自己,感觉应该是这样。一开始选择了一扇门,这个动作本身将三扇门分为了两份,“我选择了的门”和“我没有选择的门”。主持人在你没有选择的门里面开一扇,说这扇后面是羊。然后问你,你选“我选择了的门”,还是选“我没有选择的门”里面,除了打开不是羊的那扇门之外,剩下的一扇。 如果这样说还不够明白,进一步构造的话。一开始选择了一扇门,这个动作本身将三扇门分为了两份,“我选择了的门”和“我没有选择的门”。主持人不开任何门,直接问你,你选“我选择了的门”还是“我没有选择的门”。一个只有一扇门,一个有两扇门,当然选“我没有选择的门”啦!重新选择了“我没有选择的门”之后,主持人再从那里面找一个是羊的门,打开。这个情况跟先打开再换选,实际是完全等价的。因此换选这个策略能达到2/3的概率,就显而易见了,一个是选了一扇门,一个是选了两扇嘛。 呜,之前的博客中还有对“果壳死理性小组”不屑言论,深表惭愧及歉意。特保持原博客原状,作为对自己错误的惩罚。

掷骰子的上帝 — 冷眼看三门问题

本篇博客观点是错的,我已补新篇谢罪。特保留本篇文章原状作为自我惩罚和警示。 今天基友硬拉着我跟我争论了一个经典的概率问题:三门问题。 问题是说,在机智问答的最后抽奖环节,有三扇门,其中两扇门背后是山羊,一扇门背后是汽车。一旦你选择了一扇,主持人就会选择你没选中的那扇并且打开它。当然这后面一定是山羊啦。这时候你换选另一扇还是保持原来的选择? 这个问题我很早之前就看过,我没多想。再选的概率一定是1/2我认为这没什么可讨论的。但是基友一定要跟我争,而且有一套挺不错的逻辑。我一时说不出他的逻辑有什么错。争论结束我回来还是余兴未央,搜索了一个帖子,是讲这个问题的 换还是不换?争议从未停止过的三门问题~ 我努力抛弃原有的想法,尝试理解这种观点。认为换比不换好的人,思路是这样的: 1) 我选了一扇门,后面是羊还是车我不知道,但是是羊的概率是2/3,是车的概率是1/3。 2) 主持人开了一扇门,门后必然是羊; 3) 如果我选的门后是羊,剩下的一扇门背后必然是车;概率2/3 4) 如果我选的门后是车,剩下的门背后必然是羊;概率1/3 这个思路看似缜密实则混淆了概率的基数。 1)和 2)两点都是无可争议的。 我们看第3)点。如果我选的是羊,换门就是车,这也没问题。但问题是,现在我选的是羊的概率还是2/3吗? 当三扇门都未打开时,我选一扇门,门后是羊的概率是2/3,这是没有问题的。但要仔细考虑,为什么是2/3?这个概率是谁贡献的? 不妨设门后的三个物件为:羊A,羊B,车C。 我选一扇门,门后有这三物件任意一件的概率都是1/3,是羊的概率是2/3其实是羊A的概率 1/3 加上 羊B的概率1/3。 当主持人打开一扇门,露出了一头羊,不妨说是羊B吧。这个时候其实你选择到是羊B的概率就是0了!你不可能选择了羊B。 所以可能性只有你选择了羊A,和你选择了车C。所以你选羊A的概率是1/3,选车C的概率也是1/3。你换门得到车的概率是1/3,不换门得到车的概率也是1/3。是一样的。这样说有点不太对,因为是羊B的那1/3的概率已经不可能存在了。整体系统的概率是1。所以说的概率1/3其实是主持人开门之前的概率了,主持人开门观测一扇门后的物件这个动作,其实影响了整个系统的概率。他开的这扇门确定是羊,就说是羊B好了。那么是羊B的概率就是100%,是羊A的概率就是0,是车C的概率也是0。所以剩下两扇门,无论你选了哪一扇,是车的概率都是1/2,是羊的概率也都是1/2。 观测前 门1(羊A 1/3,羊B 1/3,车C 1/3) 门2(羊A 1/3,羊B 1/3,车C 1/3) 门3(羊A 1/3,羊B 1/3,车C 1/3) 观测后 门1(羊A 1/2,羊B 0, 车C 1/2) 门2(羊A 1/2,羊B 0, 车C 1/2) 门3(羊A 0, 羊B 1, 车C […]

难题:识别独立安卓设备

今天碰巧朋友问到我怎么识别独立的安卓手机,就花了一些时间琢磨了一下。 其实这个问题可以秒答,就是IMEI。 TelephonyManager.getDeviceId(); 这需要一个权限: <uses-permission android:name=”android.permission.READ_PHONE_STATE” /> 问题如果这么简单就好了,问题在于: 平板等其他设备,无SIM卡,因此无Telephony模块。 有些设备恢复出厂设置的操作会清空IMEI (水货硬解通常会导致这个结果) 参考这个硬解技术贴 参考这个恢复出厂设置不慎的操作案例 我国许多山寨手机厂商偷懒,刷机不改IMEI,所以IMEI都是一样的 因此其实问题从这里才开始。网上能够搜索到的解决方案有以下几点: – WIFI MAC 一个方案是优先采用IMEI,当IMEI相同时,再比较WIFI的MAC地址。但如果手机没有WIFI功能或者WIFI功能没有开启(飞行模式),则无法获取到MAC地址。更加让人惆怅的是,我国大山寨厂商实在是懒透了,无线网卡的MAC地址居然也不修改,不少自刷机的也是这病情(例如这个,这个还有这个)。至于说蓝牙MAC地址就更别说了。IMEI重复的病因,与MAC地址相同的其实是一个原因,都是刷机或山寨,所以这个wifi MAC地址的方案其实算不上互补了,必须另谋途径。 – Serial NO 另一个方案是用serial NO。这个值仅在android 2.3版本以上才提供支持。通过adb可以这样查看: adb shell getprop ro.serialno 代码中可使用系统变量android.os.Build.SERIAL访问。如果这个值能够取到这是仅次于IMEI的最好方法了。缺点是这个值在2.2及以下版本的android系统不支持。不过好在如今的安卓世界2.2及以下的占有率已经越来越低了,翻新速度很快,因此这个值很值得一试。 – Android id 其实安卓系统提供了Settings.Secure.ANDROID_ID来获取唯一设备号。 import android.provider.Settings.Secure; private String android_id = Secure.getString( getContext().getContentResolver(), Secure.ANDROID_ID); 但同样2.2以前的系统支持得不好。这个值是系统初次启动后生成的,因此恢复出厂设置后这个值会变,导致观测到的设备数虚高。在手机刷机、重置频繁的环境,这个值是不靠谱的。另外某大厂生产的设备居然有个BUG,这个值是会重复的(DROID2),因此这个值还是别用为好。 – generated UUID 最后还有一个自己生成UUID的办法,保存这个ID,每次访问服务器时上传,自己告诉系统自己是谁。这个方法比所有硬件方法都更不靠谱,因为只需卸载软件和清理数据就会导致这个值被删除,从而产生新的UUID,造成观测到的设备数量虚高。更别说刷机和恢复出厂设置了。这个方法非常适合用来统计软件安装次数,而非独立设备数。 结论 综上所述,目前为止我还没找到非常完美的统计独立设备的方案,尤其是在中国这个水货、硬解、山寨、刷机市场泛滥和不规范的安卓世界,更是难上加难。 但是反过来想,是不是一台完全刷新,安装了全新的ROM的手机,就已经不是原来的那台手机了呢?统计独立设备数的目的究竟是什么?如果要的是独立活跃设备数,其实用自己生成的UUID已经足够,因为原来使用的那个UUID已经失去活性,可以忽略了。对于APP开发者而言这个情况与用户换了一台手机,完全弃用旧手机的情况其实是一样的。假如是采取活跃UUID的方式,则即使是使用ANDROID_ID或者自己生成的UUID都是可取的做法了。 本文参考 [1] identifying-app-installations […]

北京堵车考

荒废好久的博客。。俺回来鸟。 又是出差北京,体验北方冬天的干冷。 在出租车上堵得无聊,就跟师傅闲扯。我很呆地问:“这五环上又没有红绿灯十字路口,所有的车都往前开,照理说车再多也不可能堵车啊。” 师傅回答:“人多事儿多呗。抽口烟,喝口水,旁边撞车了踩脚刹车看看撞得咋样儿。可不就堵了么。” “哦。” 原来高速路上也能堵车,是这么个理儿。 果然磨磨蹭蹭挪了20多分钟,前面有个撞车的。过了那辆车,前面一大段路都是一路畅通了。真的很有意思,因为没有岔路,主干线上仅仅一处事故就能引发整条高速路的拥堵。由于人多车多,这偌大的五环上只要有那么三五处事故,就能全天二十四小时不间断堵车了。 如果真是这么有趣的原因导致堵车,那么解决方案似乎也很简单啊。最极端的方案就是全面实施自动驾驶。上高速路不算,进了路,速度平稳之后,必须切换到自动驾驶。这自动驾驶首先不会出事故,更不会因为旁边有事故现场就减速看热闹。这么一来五环的运力就可以用一个简单公式计算:车速×车道 / 车距。根本不可能堵车嘛。 当然短期内还不可能全面实施自动驾驶,那么稍微简单点的办法就是通过广大司机们的自觉。说劣根性那是没办法,但矫正总还是有机会的。哪个北京司机不骂北京交通的,哪个司机不想早那么一点到目的地的。如果大家都知道,就因为自己多踩一脚刹车,晚起步半秒,导致的蝴蝶效应正好绕五环一周,叠加在自己的堵车时间上,那么为了快每个人在五环上就更冷血点,更严肃点,更快更少小动作点,事情不就解决了嘛。 这跟市内交通还不一样。毕竟在五环上,没有十字路口没有红绿灯,大家都往一个方向走,并且除了特别的时间段,通常来讲上五环和下五环的车数是相等的(除非有车想赖在五环上就不下来了)。所以只要大家都快起来,五环自然就不会再堵了。 另外可以提建议的,就是不如砸点钱搞几架直升飞机支持高速路上的事故处理。你派拖车过去把事故车再运走,一天时间都没了,可能保险公司来调查的人还堵在半路呢。直接直升飞机把该来的各方面人员都带过来,一股脑解决,把事故车吊走,至少吊离现场把,运到附近公路上再慢慢等拖车呗,能解决多少运力问题。那烧在路上的时间,分分钟都是钱啊,光节约的油钱就够多少架直升机了。