问题
概述
很多语言调用 C 语言写的模块来弥补自己某些不足。Rust 当然也可以调用 C 语言开发的模块,不过这是不安全的。
代码
- 在 Cargo.toml 中加入依赖库:
1 | [dependencies] |
- Rust 示例代码:
1 | use libc; |
- macOS 也测试通过。
很多语言调用 C 语言写的模块来弥补自己某些不足。Rust 当然也可以调用 C 语言开发的模块,不过这是不安全的。
1 | [dependencies] |
1 | use libc; |
我房子太大,一个无线路由器覆盖不了怎么办? - 知乎
1000 多平方米的办公室够大吧?一个小米路由器 Pro 放在中间,办公区域覆盖完全,仅厕所信号较弱。
100 平占地面积,三层楼(无电梯、楼梯洞很大),在二楼放一个 79 块的路由器,日常无痛使用 4 年以上。
WiFi 信号是通过漫反射传播的,不是什么“穿墙”!所以重点不是“太大”,而是钢筋混凝土墙的格局。
震惊!WiFi 信号在空旷的地方轻松覆盖你家十栋大别墅的面积!
真正能靠透射、衍射穿透的是玻璃、木头、塑料之类。5.8G 信号是厘米波,能穿透的厚度也不大,稍微厚点的木门都不行,只能从门下的缝钻进去。您可以在房间里做开关门试验,结论是:穿墙太难了,撞墙倒是会反弹……
5G WiFi 就是 5.8GHz,为和 5G 蜂窝网络区分开,特意采用 5.8G。
主路由 + AP 方案!中间当然是千兆网线连接,如果您没有布网,那就跳过,看后面分析为什么其它方案都不靠谱。
本方案需要的硬件是 N 个刷 OpenWRT 的路由器:
主路由器,自然就是放在多媒体箱里,接光猫或入户网线。
AP,其实也是个 OpenWRT 路由器,只是关闭 DHCP 服务,配置和主路由器同网段,然后用 LAN 口接主路由器的 LAN 口。
AP 可以有多个。比如稣家,是长方形结构,距离多媒体箱最远的主卧关上门基本零信号,只能在主卧放一个 AP,然后全家都覆盖完整。
只开 5.8G,尽量不开 2.4G。稣家的“只支持 2.4G 的终端设备”全部集中在大厅区域,所以只有主路由器开启 2.4G。如果开多个 2.4G,注意信道隔离。每个 5.8G 信号都用同样的 SSID,以实现漫游。
AP 的 IP 地址可以使用静态,也可以使用 DHCP client,然后在主路由器上绑定地址。AP 有固定 IP 方便登录管理。
如果 AP 需要 IPv6 地址,再创建一个 lan6 接口,物理 Interface 选择 br-lan(和 lan 接口一样,但不能勾选 Bridge interfaces),协议是 DHCPv6 client。
有人说,这样的方案缺乏 AC 管理,会导致终端设备可能不会自动切换信号。稣特地拿出祖传的 iPad2,从大厅漫步到主卧,神奇的事情发生了——居然可以自动切换 5.8G WiFi 信号!终端能不能自动切换,这显然是驱动程序决定的,虽然 iPad2 已经很老,但系统有更新到 iOS 9.3.5……
实在找不到一个不能自动切换信号的设备!好,测试结束。方案完美上线。
OpenWRT 说它确实可行!
移动中使用设备的机会不高。您不会在家里跑来跑去,同时费劲地使用设备,有可能您根本就不需要自动漫游。
您不会在家里的每个角落使用 WiFi,所以有很多地方并不需要有信号,比如洗手台、走廊、厨房。
买不起!什么?你说某些乐射 AC 很便宜?不好意思,很便宜也不是免费,还耗电!做人,难,做穷人,难上难!
AC+AP 方案的原理:AC 会自动发现并管理 AP,设定 AP 的 RSSI 阈值,将信号不稳定的设备【踢下线】,迫使终端设备重新连接信号最强的 AP,实现 AP 的自动切换。
请注意【踢下线】三个字,用 AC,在终端移动时,一样会断线。既然都会断,那就没有本质的区别,让终端自己选择,体验并没有比较差!
所谓 AC 管理,无非是促使那些不支持 802.11k-2008 的设备重新连接而已。如果您有这样的设备,建议还是换掉他们,或者固定他们,古董啊,可别让它们逃跑了!
贵!Mesh 的主节点就是个 AC,绕回 AC+AP 方案。有网线的话,为什么不用 AP 方案?根本就是一样的嘛!
懒得喷……
不要在 Ubuntu 上运行这条命令!都说 CentOS 比 Ubuntu 稳定,总算见识到具体案例!
1 | $ cat /etc/centos-release |
可见,机智的 CentOS,早就料到这个运维事故!
1 | $ cat /etc/lsb-release |
SSH 到 Ubuntu Server 上,运行 chsh -s zsh,exit 后就再也无法登录……
如果您要远程做这个试验,记得 exit 前 chsh -s /bin/zsh,或者 vi 手动纠正 /etc/passwd。
BC 试用版过期,思考 3 秒钟:稣太穷,买不起!
macOS 和 iOS 一样,App 都是独立存储,找出安装信息保存在哪个文件应该很容易。
确实如此!居然只要两步:
1 | cd ~/Library/Application Support/Beyond Compare |
由于子公司、分公司众多,稣的服务器列表里有好多个项,想备份这个列表,发现还不是很容易!

首先,找到 ~/Library/Application Support/X-NG/-local-config.json,但这个文件里只有当前选择的项。
然后,就看代码吧!Swift 写的,应该还好:
1 | let defaults = UserDefaults.standard |
根据代码线索找到:
1 | defaults read ~/Library/Preferences/com.yuzhou.X-NG.plist |
哇~全部出来了!
《#诗盗#·我类么张》:教主威名顶天扬,挪移失踪烂教纲。殷郎油尽淡淡伤,杨逍无奈朱元璋。
我类么:Whatever。
挪移失踪烂教纲:领导常年消失不见一般会烂掉。
最近 MBP15 的硬盘空间告急,打开“磁盘工具”查看,却发现居然有两个“宗卷”!从没认真研究过 macOS 磁盘管理的稣疑惑了。
“磁盘工具”默认“仅显示宗卷”,“显示所有设备”后是这样的:




肉眼观测 disk1 是放在 disk0 里的……嗯,想起容器!但 GUI 有时候是会骗人的,用 diskutil 来检查一下:
1 | $ diskutil list |
以上可知,只有 disk0 是物理的,disk1 是由 disk0s2 这个分区虚拟出来的。
下面查看两者详细信息对比:
1 | $ diskutil info /dev/disk0 |
两者 Virtual 属性的不同,说明前面的猜测是对的。
搜到如下参考:
推理正确!
Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,具有很好的空间和时间效率,被用来检测一个元素是不是集合的成员。
Bloom filter 采用的是哈希函数的方法,将一个元素映射到一个 m 长度的阵列上的一个点,当这个点是 1 时,那么这个元素可能在集合内,反之则一定不在集合内。
libbloom 是 Bloom filter 的 C 语言实现库,其中哈希函数是 MurmurHash2。
如果检测结果为是,该元素不一定在集合中;但如果检测结果为否,该元素一定不在集合中。
优点:插入和查询时间都是常数。它查询元素却不保存元素本身,节省大量的存储空间。当元素是密码时,不保存元素的特征使其具有良好的安全性。
缺点:存在误报(false positive)。当插入的元素越多,错判“在集合内”的概率就越大。另外 Bloom filter 也不能删除一个元素,因为多个元素哈希的结果可能在 Bloom filter 结构中占用的是同一个位,如果删除了一个比特位,可能会影响多个元素的检测。
以官方 test-basic 为例,简化的代码如下:
1 |
|
输出为:
1 | ->entries = 1002 |
数学原理参考:《Bloom Filter概念和原理》
bytes 是最容易理解的,4802 位需要 601 字节存储。
bits = bits per elem * entries,每个元素需要多少位 * 元素个数。
hash functions = ceil(-ln(error) / ln(2))
bits per elem = -ln(error) / ln(2)^2
Rust 三大设计宗旨:内存安全、零成本抽象、实用。本文从所有权角度来学习师兄妹的爱恨情仇“内存安全”。
值归变量所有。
当变量超出使用范围时,变量值所占用的内存将被释放。这是类似于 C++ 的 RAII 概念。
变量值可以由其他变量使用,但需遵守由编译器强制要求的若干规则。
前两条是其它语言也有的,没啥好说,重点放在第三条。
克隆(clone):此处将值复制到新的变量。新变量拥有新的复制值的所有权,而原始变量保留其原始值的所有权。
你有一本书,稣按照你那本书,买了一样的书。你的书是你的书,稣的书是稣的书。
移动(move):所有权被转移到另一个要使用该值的变量,原始变量不再拥有所有权。
学姐含情脉脉地把她的书送给稣。
不可变借用(immutable borrow):没有发生所有权转移,但是可以通过另一个变量读取该值。当借用变量超出范围,内存不会被回收,因为借用变量没有所有权。
学长不太情愿地把书借给稣,并交代:“书借你,只能看,绝壁不要在上面做笔记,被我发现会砍死你的哦!我偶尔会找你查查。”
可变借用(mutable borrow):可以通过另一个变量对该值进行读取和写入操作。当借用变量超出范围,内存也不会回收,因为借用变量没有所有权。
稣把书借给学妹时说:“这书你随便用,把稣的书当做你自己的书,等到用不上时再还。”
重点在于一个“借”字:书的所有权属于其主人,但主人将书借出之后,自己是无法再在书上做笔记啦!
借出期间,借方不能写:学长说过,在书上乱画,要砍死稣!
借出期间,所有者不能写:这书学长已经学完,偶尔要复习,但已经不需要写笔记,借出去之后就更不会写了。
1 | fn main() { |
不能多次可变借用:只能有一个独占的学妹(active borrow),稣不能同时承诺给多个学妹“随便用”,不然学妹们可能打起来……
所有者不能再读写:书在学妹手里随便蹂躏,稣虽然心疼,但不能说!等她爽(huan)了再说吧。
1 | fn main() { |
《#诗盗#·隐玊》:诗码中年初白头,科技人生稳如狗。神之八哥思千虑,一算钱袋拮九周。
玊:通“士”。
稳如狗:稳妥地像狗,不是稳定。
神之八哥思千虑:要解决的问题是神级的难,脑力消耗很大。
一算钱袋拮九周:收入不行,只能过着拮据的生活。
改编自霹雳角色玉龙隐士诗号:
书剑青眼初白头,
智殊相悬问机难,
波澜困守役千虑,
一算龙隐决九川。
在《优化思维【3】消除没必要步骤》提到一个对象转化的例子:A 对象要转为 B 对象,实现时先把 A 对象转为中间对象 T,再将 T 转为 B 对象,由于两步都很容易实现,一个现有函数即可,所以很多人可能会采用这个思路。
下面要介绍的“合并步骤”,类似于优等生解应用题时“跳步”(一行合并多个步骤),可以作为前文的补充。
以下命令 UMU 经常看到,其实它可以用 grep UMU test 来优化,减少一次管道交互。
1 | cat test | grep UMU |
再看下面例子是从一个命令行里移除 A 和 C 两个选项:
1 | cmd="EXE A=1 B=2 C=3 D=4" |
其中两次 sed 可以合并为一次:
sed -e 's/ A=[^ ]*//;s/ C=[^ ]*//'
或 sed -e 's/ [\(A\)\(C\)]=[^ ]*//g'
或 sed -e 's/ \(A\|C\)=[^ ]*//g',这个 macOS 上不行。
或 sed -E -e 's/ (A|C)=[^ ]*//g',这个适合 macOS。
先查一下 sysctl net.ipv4.tcp_fastopen,一般应该是 1,说明客户端支持 TFO;如果是 2 则说明服务端支持;3 是同时支持。
TFO (TCP Fast Open) 是一种能够在 TCP 连接建立阶段传输数据的机制。使用这种机制可以将数据交互提前,降低应用层事务的延迟。
这其实也是一种合并步骤的思想,把传输数据合并到三次握手期间。
参考: