分类 Tech Notes 下的文章

让服务器响应整个网段中的请求

最近有个需求是让某个服务器能够响应一整个网段的请求,研究了一下,发现比想象的容易。

假设需要的网段是 172.16.0.0/16 (好多IP!) 我们需要让用户能用这个段里面任何一个 IP 访问我的服务器,服务器IP实际是 192.168.1.4 ,那么分这样两步走就行。

1: 在路由上将 172.16.0.0/16 设置一条静态路由,网关是 192.168.1.4
在别的机器上 ping 172.16 段里面任何一个 IP,肯定现在还 ping 不通,但是在 192.168.1.4 上抓包,保证报文已经被路由到了这台服务器
2: 给本机的 lo 上增加一条 local 表里面的路由
ip route add local 172.16.0.0/16 dev lo

然后就一切正常了。

PS: 这个办法 IPV6 一样可以用,例如
ip route add local fc::/64 dev lo
就可以让 Linux 响应 fc::/64 里面所有的 IP

PS1: 除了路由器上设置服务器为网关,其实还有其他办法让请求报文能到达服务器,V4 可以用 tarpd,V6 可以用 ndppd,但是这些方法都会给网关和服务器的 ARP 表和邻居表里面增加非常多的记录,对性能有很大影响,因此不建议使用,还是用静态路由的方式比较好。

PS2: 不要设置在 eth0 上,可能会造成一些其他问题,lo 就挺好的

不要买技嘉 X570 Gaming X 主板

装了这么多年电脑,头一次遇到被电脑主板散味熏的头疼了好几天的情况。。。

之前台式机是 3700X + MSI Mortar B450m, 用的没啥问题就是槽不够用,因为有加设备的需求,打算借机就换个 X570 飞一下,于是选择了一线品牌里面最便宜的这个 GIGABYTE X570 Gaming X,1099 大元入手。

拿到以后一看 PCB 觉得比较一般,看上去不像一线品牌应该有的样子,也没多想就直接上机了。结果开始烤机以后电脑机箱里面温度上升,主板就开始发出比较浓的化学品味道,熏得人坐立不安,大冬天的不得不开窗放气。开始想着这可能是临时现象,没想到过了几天依然如此,而且不开电脑时候依然有味,整个书房里面都充满了化学品的味道,简直要疯掉。

最后忍无可忍,简单做了一下功课以后,直接狗东下单微星 B550 暗黑,虽然是 B550 但是供电比 570 GAMING X 好太多,看在算是相对高端定位的份上,应该不会太差把。拿到以后上机果然没味。

以后买东西还是坚决不能买丐版,钱包不够好的话,还是稍微差一点的品牌的旗舰级别产品会更好一些。宁为鸡首不为牛后。

Golang socket 里面奇怪的 pipe 使用

有个 golang 写的 proxy server, 大概日常 tcp 连接数两万多左右,结果某次在 /proc/pid/fd 下面一看,竟然有五到六万多文件,ls -l 一看,居然 socket 只有两万多,pipe 反而有三万多小四万,这就奇了怪了,哪儿来的这么多 pipe?

读了一阵子源码搞清楚了,golang 在 Linux 下面,对于 fd 对拷这种操作【具体是 net.Conn.readFrom(net.Conn)】,有个用 splice 系统调用的优化,会先试着用 splice 调用在内核里面完成两个 fd 之间的拷贝,这个可以省去将大量数据从 kernel 里面拷贝到 user space 的操作。如果失败才正常拷贝。

然而 splice 这个调用可能是为了内部实现方便,目标一方必须是 pipe 类型的 fd。所以 golang 里面的实现其实比较龌龊,先创建一对 pipe fd,然后从源 fd splice 进 pipe 入端,接下来从 pipe 出端 splice 到目标 fd。 这样下来一个 readFrom 操作,里面要一次 pipe2 调用,2 次 splice 调用,还有 2 次 close 操作关掉 pipe。有趣的是,即使这么龌龊的实现,在数据量大的应用,比如 proxy 上面,依然可以达到比直接拷贝更好的性能,可以参考下面的第一个链接。

唯一感觉比较不爽的也就是每次 readFrom 都要创建 pipe 再销毁了,这个为了不影响 golang 的架构设计,可能也只能这么做。不过一般 proxy 里面最后大多是 io.Copy ,而这个调用一旦调用就直到 tcp 连接断开了,生命周期不会太短,所以完全没有必要再做任何优化了。

参考传送门

https://github.com/golang/go/issues/10948
https://github.com/golang/go/blob/0e85fd7561de869add933801c531bf25dee9561c/src/net/tcpsock_posix.go#L47
https://man7.org/linux/man-pages/man2/splice.2.html

用RenderDoc和安卓模拟器抓帧手游

知乎上有一篇用 Intel GPA 和安卓模拟器抓帧手游的帖子,不过 Intel GPA 配置相对比较繁琐,还有版本问题。还是 RenderDoc 比较习惯。所以研究了一下如何用RenderDoc来抓帧模拟器,倒是蛮简单的。这样手游只要能用模拟器运行,就一定可以被抓帧,什么 ro.debuggable 啊,USB 调试啊都不需要管,root 也不用开,绝无被检测到的可能。

首先要设置 Windows 环境变量 RENDERDOC_HOOK_EGL = 0 ,这个是为了防止 RenderDoc 把模拟器里面实现的 GLES API 给 Hook 了的同时还 Hook 了 DirectX 造成冲突。设置的时候需要右键点击我的电脑(Win10里面叫此电脑),选择属性里面有个修改环境变量的地方。不要试图在命令行上设置,没有用。

其次把模拟器的渲染模式改成 DirectX,原因同上。

在 RenderDoc Tools->Settings->General 里面找到 Allow global process hooking 并勾选

然后找到模拟器的核心文件,一般是一个叫 XXXHeadLess.exe 的文件,也可能是其他的。找到的方法很简单,模拟器里面随便运行一个手游,然后任务管理器里面按照 CPU 使用排序,排在最前面的就是,右键点击之,选择打开文件所在位置。就可以找到核心文件的位置。

在 RenderDoc 的 Launch Application 页面里面。Executable Path 选择刚才找到的模拟器核心。然后在下面 Global Process Hook 里面点 Enable Global Hook,如果提示需要 Administrator 启动就确定以后再点 Enable Global Hook 按钮。

退掉所有模拟器,(注意一定要退干净,有时候模拟器界面关掉了,核心还在后台运行。可以在任务管理器里面查看模拟器的核心是否还在运行,还在运行的话用任务管理器杀掉)然后重新启动模拟器,这时候应该能看到模拟器画面左上角已经显示 RenderDoc 的信息了,如果没有,请检查前面操作是否正确,没有RenderDoc的显示信息说明完全没有加载成功。

RenderDoc File 菜单 Attach to Running Instance , 在 localhost 下面可以看到模拟器核心程序,选中并点击 Connect to app ,之后就正常抓帧即可。

* 如果模拟器里面没有启动手游,而是停在桌面上的话,刚 Connect 上的时候有可能会显示 D3D11 Not Present,没法抓帧,不用担心,这是因为模拟器没有渲染动作。正常启动游戏就可以抓了

* 模拟器毕竟是把安卓的渲染 API 给翻译到 D3D11 API,所以确实有可能和实际渲染操作有些许差别,特别是采用多线程渲染方式的手游,抓帧下来的结果时序很有可能是不对的,这个就没有办法了,就当个补充好了。

* 我测试都是用 64 位模拟器做的,没试验 32 位的行不行

解决 Mac 电脑原生 EFI 安装 Windows 启动很慢的问题

Mac 电脑如果不用 bootcamp,直接用 EFI 方式安装 windows 或者其他操作系统,会发现开机的时候会黑屏或者灰屏停留 30 秒才开始引导。网上搜到的很多帖子都说需要用 recovery 盘启动,用 bless 命令修改 bootloader 参数,实际上这个方法并不适用于原生 EFI 方式,只适用于用 bootcamp 方式安装 bios 启动的操作系统。

真正导致这 30 秒 delay 的原因是 bootloader 找不到原本的 EFI 启动项 MacOSX ,于是它等了 30 秒才去尝试下一个启动项 Windows。于是只要删掉原有的 OSX EFI 启动项就好了。

随便用一个可以在 Windows 下面编辑 UEFI 启动项的软件(我用的是 DiskGenius 免费版本,在工具菜单的最后一项),删掉已经不存在的 OSX 项,一般是 0080,然后保存启动项信息,退出重启就能看到开机立刻出现 Windows logo 了。

最近评论

时光机

其他