跳转至

博客

预告 Learn-Project 4.0 版

不知道大家听没听说过 Google Chrome 有个插件,叫做 Learn Project,是一个网络学堂的改良前端。不过,随着网络学堂的不断更(xia)新(gao),它已经不再适用于现在的版本。于是,哈利橙(@Harry-Chen)决定利用寒假时间,在今天(2.17)之前完成 Learn Project 4.0 的开发。为什么叫 4.0 呢,因为哈利橙课程的 GPA 众数是 4.0。这个版本采用先进的 React 框架编写(Vue 塞高),使用了 Material Ui 作为界面框架(这我觉得可以),目前的一个参考图(图源哈利橙):

看那满眼的高分数,希望 Learn Project 4.0 能在 flag 倒下之前完成。

每周分享第 11 期

对不起迟到了(

  1. Google 的 fuzzing 家族又来了个新成员 太喜欢造轮子了 https://github.com/google/clusterfuzz
  2. 有趣的文本生成工具 https://github.com/TheBerkin/rant
  3. 又一个 side channel attack https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2019/february/downgrade-attack-on-tls-1.3-and-vulnerabilities-in-major-tls-libraries/
  4. 来自 Prof Fan 的一个 cf dns 权限限制分发的工具 https://github.com/ProfFan/cloudflare-proxy-rs
  5. 部署到了我的博客的小工具 大家体会到了吗 https://instant.page/
  6. 教育性质的 C on web https://vasyop.github.io/miniC-hosting/
  7. 激活清华教育版 win10? --> dig +short TXT win10.harrychen.xyz
  8. windows95 v2.0 发布(误 https://github.com/felixrieseberg/windows95/releases/tag/v2.0.0
  9. 已经部署到 tuna 的 rustup-mirror crate https://github.com/jiegec/rustup-mirror
  10. Forth 也能有 http 服务端框架 http://www.1-9-9-1.com/
  11. bartender 的开源替代 实测可用 https://github.com/Mortennn/Dozer
  12. 给不支持 pac 的客户端在 http proxy 上套一层 https://github.com/williambailey/pacproxy

近来做 Stanford CS140e 的一些进展和思考(9)

距离上一篇 CS140e 系列文章已经过去了很久,距离第一篇文章过了一年零几天。在后来这一段时间内,CS140e 结束了课程,又开始了新一年的 winter 2019 课程,迎来的却是 C 版本的 CS140e,不禁让人感到失望。还好,Sergio Benitez 放出了原来的 CS140e 的镜像,如果大家仍然想回去查看原版优质的 CS140e,可以点进去参考。

后来因为机缘巧合参与到了清华的 Rust OS 课程,又想到回来把原来的 CS140e 进行更新,于是顺带把跑在 QEMU 下的一些需要的工作给做了,另外把 Rust nightly 版本更新了(一年前的 nightly 还能叫 nightly?),才发现标准库变化还是蛮大的,由于 nightly 版本变了,而且原来是内嵌了一个阉割过的 std,所以主要是从新的 std 里抄代码到内嵌的 std 中。另外,原来的 xargo 也不再维护了,转而使用 rust-xbuild 进行交叉编译。

然后又顺手实现了 backtrace 和从 backtrace 中配合 dward symbols 找函数名的功能,不过实践证明,这些东西还是 addr2line 做得更好,所以也就没有做下去,在 relocation 上也是遇到了各种问题。这个经验也是应用到了 rCore 那边。

再之后也就是寒假写驱动了,见之前的一个博文,我就没有在 CS140e 上去实现它了。有时间有兴趣的时候再考虑做一下 Raspberry Pi 的网卡驱动吧。

写于迪拜雨天。

每周分享第 10 期

新年快乐!

  1. Haskell to WASM compiler https://github.com/tweag/asterius
  2. A ssh tarpit that sends endless banner https://github.com/skeeto/endlessh
  3. Use rust to write UEFI app https://github.com/rust-osdev/uefi-rs
  4. 神奇的小游戏 https://yeahpython.github.io/game/game.html
  5. 又一个后端 rust web 框架 https://github.com/seanmonstar/warp
  6. 挺酷的一个网站 https://github.com/pomber/github-history
  7. ws 调试工具 https://github.com/vi/websocat
  8. React Hooks 进入正式版 https://reactjs.org/blog/2019/02/06/react-v16.8.0.html
  9. 又一个关于硬件的 wiki https://wikidevi.com/wiki/Main_Page
  10. virtio-fs 项目 旨在替代 virtio-9p https://virtio-fs.gitlab.io/
  11. SergioBenitez 镜像了一份去年的 CS140e https://cs140e.sergio.bz/

每周分享第 9 期

  1. IDA Loader plugin for some Nintendo rom https://github.com/w4kfu/IDA_loader
  2. websocket daemon http://websocketd.com/
  3. 实时的游戏开发器 https://script-8.github.io/
  4. 硬核逆向 Leica 相机的固件 https://alexhude.github.io/2019/01/24/hacking-leica-m240.html
  5. 做 CTF 时遇到的整数溢出的 CVE https://www.anquanke.com/post/id/104182
  6. 发现一个 speedtest 的轮子 https://github.com/adolfintel/speedtest
  7. 西数的 RISCV 核实现 https://github.com/westerndigitalcorporation/swerv_eh1
  8. iOS 12.2 会有更多的 PWA 兹瓷 https://twitter.com/mhartington/status/1089292031548145666
  9. 代替死去的 git-up: git config --global alias.up 'pull --rebase --autostash'
  10. 利用已知明文破解旧版加密 zip 的工具 https://github.com/kimci86/bkcrack
  11. 在线看 jwt 内容 https://jwt.io/
  12. JS 的 Lua VM https://github.com/fengari-lua/fengari
  13. 鲁棒但不优雅的前端 KV https://github.com/gruns/ImmortalDB
  14. Emacs Modules doc https://phst.eu/emacs-modules
  15. 用 IPv6 的 Flow Label 实现类似 MPLS 的效果 https://github.com/wenxin-wang/flowlabel-switching
  16. 又一个 JS 实现的表格 https://github.com/myliang/x-spreadsheet 类似以前用过的 handsontable
  17. @shankerwangmiao 推荐的光纤教程 http://www.kepu.net.cn/gb/technology/telecom/fiber/fbr215.html
  18. 用 Rust 写 iOS App https://medium.com/visly/rust-on-ios-39f799b3c1dd
  19. Build Once, Run Anywhere 还行 https://wasmer.io/
  20. 挺科学的 DNS proxy https://github.com/AdguardTeam/dnsproxy

使用 Rust 实现 VirtIO 驱动

背景

最近在给 rCore 添加驱动层的支持。一开始是想做网卡驱动,后来发现, qemu-system-riscv32 只支持如下的驱动:

# qemu-system-riscv32 -device help

Storage devices:
name "scsi-cd", bus SCSI, desc "virtual SCSI CD-ROM"
name "scsi-disk", bus SCSI, desc "virtual SCSI disk or CD-ROM (legacy)"
name "scsi-hd", bus SCSI, desc "virtual SCSI disk"
name "virtio-blk-device", bus virtio-bus
name "virtio-scsi-device", bus virtio-bus

Network devices:
name "virtio-net-device", bus virtio-bus

Input devices:
name "virtconsole", bus virtio-serial-bus
name "virtio-keyboard-device", bus virtio-bus
name "virtio-mouse-device", bus virtio-bus
name "virtio-serial-device", bus virtio-bus
name "virtio-tablet-device", bus virtio-bus
name "virtserialport", bus virtio-serial-bus

Display devices:
name "virtio-gpu-device", bus virtio-bus

Misc devices:
name "loader", desc "Generic Loader"
name "virtio-balloon-device", bus virtio-bus
name "virtio-crypto-device", bus virtio-bus
name "virtio-rng-device", bus virtio-bus

所以要实现网卡的话,只能实现这里的 virtio-net-device ,而 VirtIO 驱动之间有很多共通的地方,于是顺带把 gpu mouseblk 实现了。

第一个驱动 virtio-net 的实现

首先想到并且实现了的是网卡驱动, virtio-net 。最开始的时候,为了简单,只开了一块缓冲区,每次同时只收/发一个包。首先拿了 device_tree-rs 读取 bbl 传过来的 dtb 地址,找到各个 virtio_mmio 总线以后按照设备类型找到对应的设备。然后就是对着 virtio 的标准死磕,同时看 Linux 和 QEMU 的源代码辅助理解,最后终于是成功地把收/发的两个 virtqueue 配置好,并且在中断的时候处理收到的包。这个时候,可以成功地输出收到的包的内容,并且发出指定内容的包了。效果就是看到了这样的图片(图中网站是 Hex Packet Decoder):

基于此,写了一个简单的以太网帧的解析,ARP 的回复和 ping 的回复(直接修改 ECHO_REQUESTECHO_REPLY 然后更新 CHECKSUM),实现了最基本的 ping:

显卡驱动

网卡可以用了,很自然地会想到做一些其他的 virtio 驱动,第一个下手的是显卡。显卡和网卡的主要区别是,网卡是两个 queue 异步作,而在显卡驱动上则是在一个 queue 上每次放一输入一输出的缓冲区来进行交互,具体步骤在 virtio 标准中也写得很清楚。在这个过程中,QEMU 的 Tracing 功能帮了很大的忙,在调试 desc 的结构上提供了很多帮助。

然后就在 framebuffer 上画了一个 mandelbrot:

在 @shankerwangmiao 的建议下,调了一下颜色:

这样就好看多了。

HTTP 服务器

在 @wangrunji0408 的提醒和建议下,我开始把一个 Rust 实现的网络栈 smoltcp 集成到代码中来。这个库中,对底层 Interface 的要求如下:

  1. 当可以发包并且可以收包的时候,返回一收一发两个 Token,并在使用的时候调用指定的函数。
  2. 当可以发包的时候,返回一个发的 Token,含义同上。

这是我第一次看到这种抽象,而且也没有特别明确的文档表示,这个 Token 代表什么,我应该提供什么。我直接按照一些已有的例子,照着实现了一把。过程中遇到了 ownership 的问题,通过 Arc 和 Mutex 解决了,然后又出现了死锁的问题,调了半天才调出来。

接着按照 somltcp 的样例写一个简单的 udp echo server 和(假的)tcp 服务器:

// simple http server
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
if !socket.is_open() {
    socket.listen(80).unwrap();
}

if socket.can_send() {
    write!(socket, "HTTP/1.1 200 OK\r\nServer: rCore\r\nContent-Length: 13\r\nContent-Type: text/html\r\nConnection: Closed\r\n\r\nHello, world!\r\n").unwrap();
    socket.close();
}

虽然很粗暴,但是 work 了:

鼠标驱动和块设备驱动

接着自然是往 QEMU 支持的剩下的 virtio 设备里下手。首先下手的是鼠标驱动。这次遇到了新的问题:

  1. 由于缓冲的存在,每次只有在 EV_SYN 的时候才会一次性把若干个事件放入队列中。
  2. 一个事件就要一个 desc chain,意味着直接串足够大小的 buffer 到同一个 desc chain 中并不能工作。

于是只好痛定思痛照着 Linux 内核的实现把完整的 Virtqueue 的操作实现了,并且顺带把前面的网卡和显卡的驱动也更新了。果然,每次都是三个左右的事件(X,Y,SYN)插入,然后根据这些事件就可以计算出当前的鼠标位置了。

至于块设备,遇到的则是别的坑。看标准的时候,本以为就一个结构体 virtio_blk_req 就搞完了,但仔细读了读,标准似乎没讲清楚,读的时候是怎么传,写的时候又是怎么传。于是在这里卡了很久,从 Tracing 信息可以看出,QEMU 一直认为我提供的 buffer 大小不正确,多次实验之后发现,给 device 写入的 buffer 大小为 block size 的整数倍加一,这个一存放的是状态,其他则是数据,真的太坑了。

有了块设备以后,就可以替换掉原来的内嵌 SFS 的方案,转为直接从块设备读 SFS 文件。这里我没想明白 lazy_static 和 ownership 的一些问题,最后也则是@wangrunji0408 的帮助我解决了。

总结

用 Rust 写出一个可以工作的驱动并不难,只要知道 unsafe 怎么用,但是一旦需要深入思考这里应该用什么安全的方法封装的时候,才发现是个很困难的事情。现在虽然工作了,但是很多地方线程并不安全,代码也不够简洁高效,以后还有很多需要改进的地方。

See also

  1. Virtio Spec

THUWC 2019 小记

前段时间,以工作人员的身份参加了在广州二中举办的 THUWC 2019。作为一只菜鸡 OI 选手,我没想到过我会以另一种身份参与一个我本来没能参与的活动,就好像以暑校辅导员的身份参与清华暑校一样。

提早来到了赛场,布置场地,然后把机考的各个流程都过一遍,记住各个细节,各方面都有条不紊地进行,看着第一场前同学们特别激动地冲入考场,到最后一场同学们考完后的释放,在同学们身上看到了很多不成熟的样子,看到了兴奋想要和同伴分享的喜悦,也看到了不甘的眼泪。

希望各位强大的选手们可以来到九字班、零字班乃至一字班,享受课改的乐趣吧嘿嘿嘿

每周分享第 8 期

这周更加忙了,所以内容不多。

  1. Rust 1.32.0 is out 其中 dbg macro 挺有意思 https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html
  2. 在线的 hex packet decoder https://hpd.gasmi.net/
  3. Rust Cheatsheet https://www.breakdown-notes.com/make/load/rust_cs_canvas/true
  4. Rust tcp/ip stack https://github.com/m-labs/smoltcp
  5. 逆向 CAJ 的转换器 https://github.com/JeziL/caj2pdf

每周分享第 7 期

这周比较忙,所以内容不多。

  1. 在嵌入式系统里跑 Lisp 可以在串口开个 repl 在线调试 http://www.ulisp.com/show?3J
  2. Pattern matching for C++ https://github.com/solodon4/Mach7
  3. 一个商业版的类似 ASan 的产品 不知道效果如何 https://stensal.com/
  4. 用 Python 写 Cocoa 界面还行 https://dawes.wordpress.com/2017/08/17/python-with-a-cocoa-gui-on-macos/
  5. Rust 实现的权威搜索引擎 https://github.com/toshi-search/Toshi
  6. Rust Embedonomicon 讲述 Rust 在 bare metal 下的一些神奇操作 https://docs.rust-embedded.org/embedonomicon/preface.html
  7. 发现另一个基于 Github 的 Disqus 替代品 https://utteranc.es/
  8. 挺好的一部讲 Rust 生命周期的小书 http://cglab.ca/~abeinges/blah/too-many-lists/book/README.html
  9. 跨平台的 Ctrl-C 处理 for Rust https://github.com/Detegr/rust-ctrlc
  10. 用 Rust 写 stm32 上程序所需要的库 https://github.com/stm32-rs/stm32-rs
  11. go 语言编写的基于 fuse 的加密文件系统 https://github.com/rfjakob/gocryptfs
  12. Rust 的图片解析库 https://github.com/PistonDevelopers/image
  13. 用 BPF 做 API 解析和过滤 https://github.com/cilium/cilium
  14. 学到了 x86 又一个指令集 bmi2 https://github.com/jordanbray/chess
  15. FoundationDB 推出 Record Layer 名字十分贴切 https://github.com/foundationdb/fdb-record-layer/
  16. 一个开源的教室电脑监控系统 https://github.com/veyon/veyon
  17. DNS flag day https://dnsflagday.net/
  18. Rust stable 1.32.0 发布 https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html dbg 宏好评
  19. 各 MacBook 的 Linux 支持情况一览 https://github.com/Dunedan/mbp-2016-linux

实现 VSCodeVim 中支持中文分词的单词移动

最近用 VS Code 写中文 LaTeX 比较多,但是编辑起来总是比较麻烦,不能用各种带 w 的 motion,不然整行都没了。于是 @xalanq 提出能不能拿一个 JS 的分词库,魔改一下 VSCode Vim 来得到同样效果?答案是可以的。

最后代码在 jiegec/VSCodeVimChinese 里,还没有合并到上游的打算。不定期根据上游发版本同步更新,在 Github Release 里发布 vsix 文件,目前版本为 v1.0.1。在 VS Code 里 Extensions: Install from VSIX... 即可安装。

经过对代码的研究,发现对 motion w 的处理都是通过 getWordLeft getWordRightgetCurrentWordEnd 完成的。于是我修改了这三个函数,根据原来的返回值把字符串喂给分词器,再返回的新的位置。一开始用的是 nodejieba ,但是因为需要用到 node-gyp 遇到了 Node 版本不兼容的问题,于是换了一个纯 Node 的实现 node-segment ,就完成了这个功能。

Grafana 中可视化 Ping 时把 Timeout 显示为指定值

刚遇到一个需求,就是用 Telegraf 收集 ping 信息,然后在 Grafana 里可视化当前的延迟,如果超时了,就显示一个指定值,如 999,这样就可以放到一个 Gauge 里面可视化了。但是,问题在于,Telegraf 的 ping input 在超时的时候只会在 result_code 里写一个 2 ,其他项都是空的,因而如果直接用 GROUP BY time(interval) fill(999) 会导致最新的一个数据经常得到 999。这意味着需要根据 "result_code" 来进行区分 Timeout 的情况。最后捣腾了很久,得到了这个方案:

 select "average_response_ms" * (2 - "result_code") / 2 + "result_code" / 2 * 999 from (select "average_response_ms", "result_code" from ping where $timeFilter fill(0))

最后的方法很粗糙:当 "result_code" 是 0 也就是成功的时候,得到延迟,而当 "result_code" 是 2 也就是超时的时候,直接得到 999。这样就解决了这个问题。

域名已经迁移到 jiege.ch

从买新域名到迁移大概用了一个多小时,现在已经恢复访问。原有的地址也会直接 301 到新的域名上来。

仍然 Host 在 Github Pages 上。还会继续更新,不会跑路的(逃

每周分享第 6 期

今天刚迁移了域名到 jiege.ch,原来的 jiegec.me 会自动跳转过来,链接什么的都不用变。

  1. Rust 的 cfg! 宏只是返回 bool 而不会影响内部是否被编译 如果需要 if constexpr 的效果需要用 cfg-if
  2. 基于 HTML5 canvas 的图表库 Chart.js
  3. Endianness MATTERS! -- Harry Chen
  4. 各数据库的带补全的 CLI https://www.dbcli.com/
  5. 边开发边测试 k8s 部署 tilt
  6. Github unlimited free private repos 于是称为了 PRO 用户 https://blog.github.com/2019-01-07-new-year-new-github/
  7. Github 美食博主还行 https://github.com/hendricius/pizza-dough
  8. 一个用于本地化的库 https://github.com/dustin/go-humanize
  9. Vim Verilog 补全 https://github.com/vhda/verilog_systemverilog.vim
  10. homebridge 网页前端 https://github.com/oznu/homebridge-config-ui-x
  11. Zigbee 2 MQTT Bridge 需要额外的设备 https://github.com/Koenkk/zigbee2mqtt
  12. gdb 的网页 gui https://github.com/cs01/gdbgui
  13. Rust 一键 par iter https://github.com/rayon-rs/rayon
  14. 挺好看的 hex viewer https://github.com/sharkdp/hexyl 可以配合 bat 滚屏
  15. gitalk 基于 Github issues 的评论系统 类似 Disqus https://github.com/gitalk/gitalk
  16. 根据蓝牙连接键盘与否改变键盘布局 https://github.com/jwilm/alacritty/wiki/Automatic-MacOS-Keyboard-layout-change-for-Bluetooth
  17. 8.8.8.8 加入 DoT 家庭 https://security.googleblog.com/2019/01/google-public-dns-now-supports-dns-over.html
  18. 恢复损坏的 QRCode 工具箱 https://merricx.github.io/qrazybox/
  19. 通过同时修改两个芯片的 PLL 达成了非标准的 Wi-Fi 通信还行 https://hackaday.com/2019/01/04/underclocking-the-esp8266-leads-to-wifi-weirdness/
  20. inline x86 asm in go https://github.com/mmcloughlin/avo#readme

调整 Alacritty 的 Powerline 字体显示偏移

今天体验了一下 Alacritty,以前一直在用 iTerm2,但是它的高级功能我都没用到。于是现在用了下 Alacritty,把 Solarized Dark 配置了,发现 Inconsolata for Powerline 字体显示有点偏差,于是调整了一下:

# Font configuration (changes require restart)
font:
  # Normal (roman) font face
  normal:
    family: Inconsolata for Powerline
    # The `style` can be specified to pick a specific face.
    #style: Regular

  # Bold font face
  bold:
    family: Inconsolata for Powerline
    # The `style` can be specified to pick a specific face.
    #style: Bold

  # Italic font face
  italic:
    family: Inconsolata for Powerline
    # The `style` can be specified to pick a specific face.
    #style: Italic

  # Point size
  size: 18.0

  # Offset is the extra space around each character. `offset.y` can be thought of
  # as modifying the line spacing, and `offset.x` as modifying the letter spacing.
  offset:
    x: 0
    y: 0

  # Glyph offset determines the locations of the glyphs within their cells with
  # the default being at the bottom. Increasing `x` moves the glyph to the right,
  # increasing `y` moves the glyph upwards.
  glyph_offset:
    x: 0
    y: 3

主要是这里的 glyph_offset 设置为 3(2 也可以,我更喜欢 3) ,这样箭头就基本对齐了不会突出来。

然后按照官方 Wiki,配置了 Solarized Dark 配色:

## Colors (Solarized Dark)
colors:
  # Default colors
  primary:
    background: '0x002b36' # base03
    foreground: '0x839496' # base0

  # Normal colors
  normal:
    black:   '0x073642' # base02
    red:     '0xdc322f' # red
    green:   '0x859900' # green
    yellow:  '0xb58900' # yellow
    blue:    '0x268bd2' # blue
    magenta: '0xd33682' # magenta
    cyan:    '0x2aa198' # cyan
    white:   '0xeee8d5' # base2

  # Bright colors
  bright:
    black:   '0x002b36' # base03
    red:     '0xcb4b16' # orange
    green:   '0x586e75' # base01
    yellow:  '0x657b83' # base00
    blue:    '0x839496' # base0
    magenta: '0x6c71c4' # violet
    cyan:    '0x93a1a1' # base1
    white:   '0xfdf6e3' # base3

真香

Grafana Variable 的 regex 过滤方式

用 InfluxDB 收集到 Mountpoint 数据的时候,经常会掺杂一些不关心的,如 TimeMachine,KSInstallAction 和 AppTranslocation 等等。所以,为了在 Variables 里过滤掉他们,需要用 Regex 进行处理。网上有人提供了方案,就是通过 Negative Lookahead 实现:

/^(?!.*TimeMachine)(?!.*KSInstallAction)(?!.*\/private)/

这样就可以把不想看到的这些 mountpoint 隐藏,节省页面空间了。当然了,这里其实也可以用白名单的方法进行处理,直接写 regex 就可以了。

Rust 获取 Linker Script 中的地址

在 Linker Script 中可以记录下一个地址到一个变量中,大概这样:

.text: {
    PROVIDE(__text_start = .);
    *(.text .text.* .gnu.linkonce.t*)
    PROVIDE(__text_end = .);
}

这里的 PROVIDE() 是可选的。这样,代码里就可以获取到 .text 段的地址了。在 C 中,直接 extern 一个同名的变量就可以了,但在 Rust 中,需要这样获取:

extern "C" {
    fn __text_start();
    fn __text_end();
}

// __text_start as usize
// __text_end as usize

这样就可以拿到地址了。

每周分享第 5 期

2019 年第一篇博文,祝大家新年快乐。最近忙于期末,没怎么搞事情,所以暂时没有关于别的内容的博文。

  1. 发现一个很好看的 http web server index 就是不再更新了 h5ai
  2. 录制 DOM 变化并且重放 rrweb
  3. C++ 中的 Lazy Sequence 实现 lazyCode
  4. 来自 Berrysoft 的 Windows UWP 校园网认证解决方案 TsinghuaNetUWP
  5. 中科大老运维的笔记 ITTS
  6. Go 源码研究电子书 目测还在编写,不过读来挺有收获的 go-under-the-hood
  7. 第一次了解到 ELF Aux Vectors auxv
  8. 发现了 C99 的参数列表里 static 数组大小语法 static array indicies
  9. 发现一个有趣的包装了 socket 的消息库 支持一些消息分发方法 nanomsg
  10. 找到一个可视化 YUV 和视频解码的一些内部信息的工具 YUVView
  11. 通过动态 QRCode 传输数据 txqr qr-transfer
  12. 发现一些很好看的 CSS 动画 10-stunning-css-3d-effect-must-see 其中最神奇也最复杂的是 这个
  13. Android runtime 中动态获取权限的库 Dexter
  14. 来自 Berrysoft 的 Stream operators in C++ CppLinq
  15. Squirrel (Rime for macOS) 在两年以后终于出了 0.10.0 新版本 有了好看的新皮肤
  16. 神奇的 v8 漏洞利用 实在是太复杂了 exploting math expm1 in v8
  17. JWT How-to 发现 Koa 和 Flask 的 session 默认实现也是同样的原理 learn-json-web-tokens
  18. 配置 DNS CAA 的在线工具 限制 CA 签证书的方案 sslmate caa
  19. 又一个 Python 的 Parser 库 配合有趣的 decorator 语法 sly
  20. 自动配置 webpack 的库 Jetpack jetpack
  21. eBPF tutorial learn ebpf tracing
  22. 图片 xkcd-ify 太有趣了 xkcd-style plots
  23. 又一个 Vue 的 rich text 控件 tiptap

每周分享第 4 期

咕了更长的时间。

  1. Header only JIT assembler https://github.com/herumi/xbyak 想找个时间玩玩 JIT
  2. Rust 实现的 Babel 转译 https://github.com/swc-project/swc
  3. 又一个瀑布流实现 https://github.com/e-oj/Magic-Grid
  4. 马上可以体验 HTTP/3 的库 https://github.com/djc/quinn
  5. Logitech Spotlight Presentation 挺好用的 配套软件的安装过程和使用都挺好的
  6. Server side canvas https://github.com/Automattic/node-canvas
  7. 边看 youtube tutorial 边写代码 https://yourepl.tumblr.com/post/180936303347/announcing-yourepl
  8. 又一个 PostgreSQL 网页版客户端 https://github.com/sosedoff/pgweb
  9. 有趣的 CSS Layout 学习方法 http://cssgridgarden.com/#en http://flexboxfroggy.com/
  10. pipenv 也有过 easter egg https://github.com/pypa/pipenv/issues/786 不过影比 antd 这个事情好多了
  11. Web 太强了 啥都能做 https://whatwebcando.today/
  12. 来自娄晨耀的清真 DNS 解决方案 https://github.com/Chenyao2333/freedns-go
  13. 快速的 tldr 实现 https://github.com/dbrgn/tealdeer
  14. MongoDB Data Source for Grafana 可以用 就是 aggregation 不大容易写对 https://github.com/JamesOsgood/mongodb-grafana
  15. Fish 3.0 发布“fish now supports && (like and), || (like or), and ! (like not), for better migration from POSIX-compliant shells (#4620).”

《加速奔向 2019》小程序编写和运营回顾

前言

关注清华的同学可能知道,昨天,“清华大学”公众号发了一篇名为《2018,我们共芳华丨@THUers 致相伴一年的你,请查收这份心意》的推送,内容大概就是,有那么 100 个新年台历礼品要送出去,大家如果想要的话,就扫描小程序。小程序模仿了火车抢票的病毒式营销的模式,要求大家分享到群聊或者朋友圈,让别人给自己加速,加速到 2019 的前 100 名即可填写信息领取奖品。

然后大家就在推送里看到了我。就酱。

开始

这件事情据说策划了有一段时间了,只是因为各种原因一直没有做,最后这个锅就路由到了我的头上。一开始说就是个加速小程序,逻辑很简单,但后来逐渐发现需求越来越多,主要是界面上的,动画上的,还有一些非技术因素的功能,嗯。这其实算是一个不大好的软件工程案例。

过程

线上的问题与解决方案

然后就是上线了。大概是昨天(2018-12-27)中午的时候推送发出去,很快流量就开始来了。很快,在朋友圈看到有同学在转发了,也有人反映说,网络有点卡,加载资源有点多。我去机器上用 iftop 看了下,流量大概是 250Mb/s,没打到千兆。我一开始看了下,CPU 和内存占用都良好,以为是网络出口限制的问题,就想着没办法了,就这样吧,扛过去再说。不过,忽然有了转机。

TUNA 技术群里,忽然有人在讨论 SOMAXCONN 的问题,我想到,会不会是有些参数没开够大,导致了性能瓶颈,又受到啊荣的点拨,立马调整了这些变量:

net.core.somaxconn
fs.file-max
net.core.netdev_max_backlog
net.ipv4.tcp_max_syn_backlog
nginx: worker_rlimit_nofile
nginx: event.worker_connections

很快带宽从 200Mb/s 左右打到了 400Mb/s 多,在 iftop 中看到的峰值接近 600Mb/s,见下图:

事后回来看,发现配置一套科学的监控系统真的很有用,如 TCP 连接的状态图:

这里最高的黄线代表的是 TIME_WAIT,意味着很多的 TCP 连接都卡在了等待资源上,而一当我修改参数以后,立刻就降了下来,ESTBALISHED 的连接有了显著的提升。这个问题从另一个图也可以明地看出:

这个图是 TCP Handshake Issues,可以看到无论是 activeopen 还是 passiveopen,都很高,意味着这里无论是发还是收都遇到了问题。而修改参数以后,这些问题立马得到了很好的改善。

其实这些本应该在上线前做好的,但我低估了清华大学的影响力,没有做好相应的准备,还是在优秀的运维人员的指点下得到了较好的效果。

用户数据分析

当然了,除了 Grafana+InfluxDB+Telegraf 这一套监控系统,我们也部署了 ElasticSearch+Logstash+Kibana,只不过我们还是用 Grafana 做了 ElasticSearch 的前端了。通过对 Nginx 日志的分析,我们得到了这些关键的数据(从 12-26 12:00 到 12-27 12:00 一天时间):

除了这些,还有很多有趣的数据,例如用户里北京的最多,也可以大致地看出各个地方网络和手机的普及程度;用户使用的手机的机型里前几名都是苹果的,从单项占领了排名的前很多位,之后则是华为小米 OPPO 等,但总体上反而是安卓用户更多。

微信小程序官方也提供了一些数据统计可供参考。例如页面的访问次数信息,一共大约有二十多万次,打开小程序有十三万多次,访问人数是五万多,还有女性用户比男性用户多等等。这个时代,有数据确实能够得到许多有价值的判断。

反思

这次学到了很多东西,验证了监控系统的必要性,它能够实时看到服务的运行状态并进行调优,事后也可以回过头来进行进一步的分析和总结。不足的是,遇到大客户量的时候,静态资源就应该用 CDN 服务而不应该自己搭建,成本不高而且用户体验会很好。这次后端在数据库操作都用了原子操作,没有出现大的问题,但如果以后遇到更复杂的需求的时候就没有这么容易了。

每周分享第 3 期

因为 DDL,咕了一小会。

  1. 被 Windows 保存为 Unicode 文件坑了 BOM 配上 UTF-16 太难受了
  2. Github 最近添加了很多 Issue 方面的更新,如 Pin 和 Delete
  3. Grafana 真的很好看很好用 推荐大家自己配一套监控系统
  4. Microsoft Remote Desktop Beta 新增了 AVC Codec 有意思 不知道啥时候上 HEVC
  5. 发现一个很好玩的用 Rust 写的网页游戏 https://sandspiel.club/#
  6. Python Pattern Matching https://github.com/santinic/pampy
  7. 大新闻:MIPS Open Source 了 https://www.eetimes.com/document.asp?doc_id=1334087
  8. GRPC 调试的 GUI https://github.com/uw-labs/bloomrpc 对标 Postman
  9. 酷炫的屏幕保护 for Mac https://github.com/JohnCoates/Aerial
  10. WPF 开源了 不知道啥时候支持 *nix https://github.com/dotnet/wpf
  11. 分享欢乐 https://github.com/dotnet/wpf
  12. 分享欢乐 x2 https://lore.kernel.org/patchwork/patch/628142/
  13. 谷歌近日到处上线了 Material Design 2.0 感觉风格不大习惯
  14. veonim/veonim 的 Tag 里有 #meme-driven-development 太好笑了
  15. 巨硬开源了自己的 UEFI 和 TianoCore EDK 竞争 https://blogs.windows.com/buildingapps/2018/12/19/%e2%80%afintroducing-project-mu/
  16. Github 的 GDPR 完全体上线 https://blog.github.com/2018-12-19-download-your-data/
  17. ZFSonLinux 要统治 ZFS 世界的节奏 https://lists.freebsd.org/pipermail/freebsd-current/2018-December/072422.html
  18. VBScript 真的是太多漏洞了 满目疮痍 https://googleprojectzero.blogspot.com/2018/12/on-vbscript.html
  19. 原来取名真的这么草率的吗 我也想买一个了 https://www.solidot.org/story?sid=59028

每周分享第 2 期

继续,继续。

  1. 用代码呈现硬件实现对性能的影响,值得一读 链接
  2. 发现了一个蛮少见的编码标准 AVS2,才发现是中国主导的 编码器
  3. linux.org 的 DNS 被篡改了,认准 kernel.org 即可
  4. 一个处理器的电路的在线可视化 ARM1 visualized
  5. WASM 家庭现已加入 Nginx 链接
  6. 用 .bat 编写汇编语言 mnnip/BOOTSTRA
  7. Gitlab 挺香的,兹瓷 git-lfs,还可以自己给自己的项目配一个 ci runner
  8. LaTeX 的 subfigure 之间如果有空行,就真的换了一行,所以同一行的 subfigure 不要换行
  9. Rocket 4.0 出了,看起来不错,要是作者更新一下 CS140e 就好了 链接
  10. 装机必备,查询 Arch Wiki arch-wiki-man
  11. LaTeX 里 \newcommand 时,如果文件名有多个 '.' ,要特殊处理 链接
  12. RunAsDate for *nix wolfcw/libfaketime
  13. 用数据库做数据分析似乎是个不错的选择
  14. Canvas 配合 globalCompositionOperation 能做到不少东西
  15. 才知道有 Time Machine over SMB 这种操作 链接
  16. mDNS repeater 把两个子网的 mDNS 打通 kennylevinsen/mdns-repeater
  17. Office 2019 for Mac 的 December 2018 release 添加了 Dark Mode,并且也支持了 Continuity Camera,直接从手机拍照导入
  18. Gitlab serverless 发布,期待 链接
  19. 用 NAS 作为 Time Machine 备份盘的方法 链接
  20. 研究了一下,Time Machine over SMB 在 macOS 里的表现形式是 apfs 里写了一个 sparse bundle,bundle 里面是 HFS+ 。

配置 homebridge-mi-aqara 并添加为 telegraf 的数据源

最近有了设备,想把设备拿到的数据都导一份存到 influxdb 里,但是目前找到的只有 homebridge-mi-aqara 可以访问并拿到数据,然后它又提供了 mqtt 的数据获取方案,于是自己写了个脚本去读取这些数据。

首先当然是配置一下 homebridge-mi-aqara,按照网上的教程来,这个不难。然后本地开一个 MQTT Broker(如 mosquitto),配置为本地监听,然后我编写了脚本 telegraf-mi-aqara.py ,使用前需要 pip install paho-mqtt,并且按照实际路径修改一下内容。验证能够跑起来后,写一个 telegraf 配置:

[[inputs.exec]]
        commands = ["/usr/bin/python3 /path/to/telegraf-mi-aqara.py"]
        timeout = "5s"
        data_format = "influx"

现在就可以读取到各项信息,如温度,湿度,是否开门,开关用电情况等等。

2018-12-16 更新:

研究了一下绿米网关局域网通信协议,得到了第二个版本 telegraf-mi-aqara-v2.py,它与第一版的区别是,第一版是主动向网关读取信息,而这一版则是监听组播包,等待网关发消息。这个脚本负责把读取到的组播信息发送到 MQTT,再让 telegraf 从 MQTT 里解析 JSON 消息,写入数据库。Telegraf 配置如下:

[[inputs.mqtt_consumer]]
        servers = ["tcp://127.0.0.1:1883"]
        qos = 0
        connection_timeout = "30s"
        topics = [
                "/telegraf-mi-aqara"
        ]
        persistent_session = true
        client_id = "Telegraf"
        data_format = "json"
        json_string_fields = ["model", "sid", "status"]
        tag_keys = ["model", "sid", "short_id"]

由于设备不全,有些字段可能不完整。如果大家自己要用的话,可能需要自行修改一下。

每周分享第 1 期

向阮一峰学习,把自己在一周里看到的有趣的事情分享一下。不过形式就比较随意了。

  1. 最近写 MongoDB + NodeJS 学到的新操作:$addToSet $nin $ne Mongoose 的 setDefaultsOnInsert
  2. Promise 真香,真好用
  3. 几天前惠老师还在说 "IE, The best Chrome Downloader Downloader, ever" 今天 EdgeHTML 就宣告死亡了
  4. WPF, Windows Forms 和 WinUI 开源了,mono 这是要凉? 链接
  5. 有人逆向了 FPGA 的 bitstream 格式,希望 FPGA 有朝一日可以进入 开源时代? 链接
  6. 造机的 baseline 就决定是
  7. 根据 AST 炼丹判相似度还行,好奇它跨语言的预测水准 链接
  8. 可视化 h264 nalu 的软件 H264Naked (做的好糙啊,想交 pr)
  9. ffprobe -show_packets 和 ffprobe -show_frame 真好用
  10. 发现一个解决 ArchLinux 滚内核后无法 modprobe 的方案
  11. 010 Editor 和 Hex Fiend 是二进制分析的神器啊... Kaitai 还有待加油
  12. CSS-in-JS for ClojureScript 真香 有空可以试试用 ClojureScript 写前端
  13. Safari Technology Preview 71 加入了 Web Authentication 这是要支持 U2F 的节奏?
  14. Grafana+InfluxDB+Telegraf 真科学,随手写了一些简单的 Telegraf 的 input plugin
  15. 给 010 Editor 写了俩 .bt 文件,见我上一篇博客
  16. 海思 cc 居然支持 ASan : /opt/hisi-linux/x86-arm/arm-hisiv600-linux/arm-hisiv600-linux-gnueabi/lib/a7/libasan.so
  17. 遇到了 设备名有空格导致 telegraf 读取 S.M.A.R.T. 信息失败 的锅,不过似乎没人修
  18. 看到了一个很有意思的 Interview Pass Rate 关于使用的编辑器的调查,很有意思 链接
  19. 发现一个 JSX 的替代品,用了 Template literal syntax,挺好的 链接

也不知道能不能坚持下来,就这样了,发布(逃

Grafana 可视化实践:清华大学 2018 年度人物评选

最近这段时间,清华内部正在投票选出今年的年度人物,想到最近刚好在学习使用 Grafana+InfluxDB+Telegraf 全家桶,于是想着能不能写个爬虫把数据都拿下来,然后用 Grafana 画出来,就可以得到一个投票随时间变化的趋势。爬虫很简单,就是登录,获取页面信息,然后按照 InfluxDB 的输入格式进行输出即可。代码放在了 jiegec/student-tsinghua-vote18 下。

接着就是用 Grafana 进行可视化,大概得到了这样一个曲线:

为保护隐私,把名字隐去了。实际上的投票时间是从 12-3 号开始到 12-7 号结束,但由于宿舍停电的原因所以采样的点在半夜的时候都没有,所以看起来有点奇怪,但还是能够反应总体的趋势的。比如可以看到前两名很早就一马当先,而后一直遥遥领先,下面的选手则排名变动很大,特别是截止前最后一段时间,大家都在拼命拉票,可见大家都是 DDL 选手啊。如果对上面这个图求个导,看看变化率的话:

这显现出了很有意思的一个趋势,就是每天十二点左右都有一个高峰期,然后在零点前大概熄灯附近的时间也是一个高峰期,另外就是截止前最后的抢票阶段,大家都在疯狂拉票,从中午拉到最后时刻。由于停电的原因,在零点附近的数据都比较的鬼畜,不过影响不大,趋势一目了然。

Grafana 真香!期望可以学到更多高端的查询语法和可视化的骚操作,现在有很多东西不知道该怎么可视化,比较苦恼,不知道大家有没有什么经验可以分享。

编写 010 Editor 的 FLV Template

最近在做 FLV 和 H264 方面的研究,研究了很多标准和文档,然后用 010 Editor 对着文件进行分析。这个软件真的很好用,对研究二进制结构用处特别大。不过它自带的 FLV.bt 功能不是很好,我对它加上了 H264(AVC) 的部分支持,放在了 myFLV.bt 里。我也写了 H264 的解析,不过效率不高,大文件要卡好一会。

除此之外,很多格式,010 editor 都有支持,特别好用,它的解析器语法也很好写。