使用 Tee 和 Named Pipe, Screen 进行

这两天突然想用journalctl来管理Minecraft日志。

使用Sytemd启动Minecraft服务器,不以Fork的形式,而是直接作为一个Simple的服务进行管理,同时使用journalctl管理 Minecraft 服务器日志。

然而为了能正确关闭服务器,并且进行一些配置,还是需要一个脚本进行管理。这个脚本需要在启动的时候直接吧Minecract Server(也就是Java)的标准输出直接输出出来,同时管理员要能再 attach 到 Minecraft 服务器上

 

大意如下:

Daemon.sh

#!/bin/bash
screen -dmS “test” /bin/bash -c “cd ; ./echh.sh | tee ./test.fifo”
cat ./test.fifo

 

C++ 异常处理机制

一直不知道C++中的异常是如何处理的,为什么通过一个throw语句,语言运行时就知道发生了异常,并且能在catch块中捕捉和处理这个异常。

今天看了Itanium C++ ABI: Exception Handling,大概整理总结了一下思路

 

翻译&参考:https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html

 

Splay Tree 为什么要使用两层倒序翻转?

Splay Tree中

Flatmap, Discontigmap, Sparsemap

最近在研究各种内存问题,没有找到好的介绍三种内容模型的内容,无论是中文还是英文,打算这里自己总结一下。

Flatmap的引入是最早的,也是最简单的。整个Memory中所有 Page内容用一个连续的

Discontigmap是让每个Numa Node能有一个自己的

记一次修复Linux Kernel HyperV Bug的经历

最近在做Linux Kernel Kexec的工作,Windows 10的HyperV VM里装了个Fedora 29,惊讶的发现Kexec竟然不能工作。

调用Kexec会直接蹦出这个Panic:

[   19.966336] kexec_core: Starting new kernel
[   19.994408] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[   19.995152] PGD 8000000057995067 P4D 8000000057995067 PUD 57990067 PMD 0
[   19.995152] Oops: 0002 [#1] SMP PTI
[   19.995152] CPU: 0 PID: 1016 Comm: kexec Not tainted 4.18.16-300.fc29.x86_64 #1
[   19.995152] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v3.0 03/02/2018
[   19.995152] RIP: 0010:0xffffc9000001d000
[   19.995152] Code: Bad RIP value.
[   19.995152] RSP: 0018:ffffc9000495bcf0 EFLAGS: 00010046
[   19.995152] RAX: 0000000000000000 RBX: ffffc9000001d000 RCX: 0000000000020015
[   19.995152] RDX: 000000007f553000 RSI: 0000000000000000 RDI: ffffc9000495bd28
[   19.995152] RBP: 0000000000000002 R08: 0000000000000000 R09: ffffffff8238aaf8
[   19.995152] R10: ffffffff8238aae0 R11: 0000000000000000 R12: ffff88007f553008
[   19.995152] R13: 0000000000000001 R14: ffff8800ff553000 R15: 0000000000000000
[   19.995152] FS:  00007ff5c0e67b80(0000) GS:ffff880078e00000(0000) knlGS:0000000000000000
[   19.995152] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   19.995152] CR2: ffffc9000001cfd6 CR3: 000000004f678006 CR4: 00000000003606f0
[   19.995152] Call Trace:
[   19.995152]  ? __send_ipi_mask+0x1c6/0x2d0
[   19.995152]  ? hv_send_ipi_mask_allbutself+0x6d/0xb0
[   19.995152]  ? mp_save_irq+0x70/0x70
[   19.995152]  ? __ioapic_read_entry+0x32/0x50
[   19.995152]  ? ioapic_read_entry+0x39/0x50
[   19.995152]  ? clear_IO_APIC_pin+0xb8/0x110
[   19.995152]  ? native_stop_other_cpus+0x6e/0x170
[   19.995152]  ? native_machine_shutdown+0x22/0x40
[   19.995152]  ? kernel_kexec+0x136/0x156
[   19.995152]  ? __do_sys_reboot+0x1be/0x210
[   19.995152]  ? kmem_cache_free+0x1b1/0x1e0
[   19.995152]  ? __dentry_kill+0x10b/0x160
[   19.995152]  ? _cond_resched+0x15/0x30
[   19.995152]  ? dentry_kill+0x47/0x170
[   19.995152]  ? dput.part.34+0xc6/0x100
[   19.995152]  ? __fput+0x147/0x220
[   19.995152]  ? _cond_resched+0x15/0x30
[   19.995152]  ? task_work_run+0x38/0xa0
[   19.995152]  ? do_syscall_64+0x5b/0x160
[   19.995152]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   19.995152] Modules linked in: ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack ebtable_nat ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat iptable_mangle iptable_raw iptable_security nf_conntrack ip_set nfnetlink ebtable_filter ebtables ip6table_filter ip6_tables sunrpc vfat fat crct10dif_pclmul crc32_pclmul ghash_clmulni_intel intel_rapl_perf hv_balloon joydev xfs libcrc32c hv_storvsc serio_raw scsi_transport_fc hv_netvsc hyperv_keyboard hyperv_fb hid_hyperv crc32c_intel hv_vmbus

跟着Trackback看了下代码,大概是Kexec尝试关闭其他CPU的时候,Send IPI发生了Panic。

# gdb vmlinux 
(gdb) list *(__send_ipi_mask+0x1c6)
0xffffffff81024166 is in __send_ipi_mask (./arch/x86/include/asm/mshyperv.h:138).
133
134     #ifdef CONFIG_X86_64
135             if (!hv_hypercall_pg)
136                     return U64_MAX;
137
138             __asm__ __volatile__("mov %4, %%r8\n"
139                                  CALL_NOSPEC
140                                  : "=a" (hv_status), ASM_CALL_CONSTRAINT,
141                                    "+c" (control), "+d" (input_address)
142                                  :  "r" (output_address),

Panic就发生在那个Inline ASM里面。这个RIP: 0010:0xffffc9000001d000以及Code: Bad RIP value,又是怎么回事呢?

根据汇编代码分析一下:

        x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));
ffffffff8102413b:       48 c7 c2 00 00 00 80    mov    $0xffffffff80000000,%rdx
ffffffff81024142:       48 2b 15 97 39 16 01    sub    0x1163997(%rip),%rdx        # ffffffff82187ae0 <page_offset_base>
ffffffff81024149:       48 8b 1d a0 62 94 01    mov    0x19462a0(%rip),%rbx        # ffffffff8296a3f0 <hv_hypercall_pg>
ffffffff81024150:       4c 01 f2                add    %r14,%rdx
ffffffff81024153:       48 85 db                test   %rbx,%rbx
ffffffff81024156:       0f 84 59 ff ff ff       je     ffffffff810240b5 <__send_ipi_mask+0x115>
        __asm__ __volatile__("mov %4, %%r8\n"
ffffffff8102415c:       31 c0                   xor    %eax,%eax
ffffffff8102415e:       49 89 c0                mov    %rax,%r8
! ===> ffffffff81024161:       ff d3                   callq  *%rbx  # ! <=== rbx is 0xffffc9000001d000, value of <hv_hypercall_pg>
ffffffff81024163:       90                      nop
ffffffff81024164:       90                      nop
ffffffff81024165:       90                      nop
ffffffff81024166:       48 89 c3                mov    %rax,%rbx
                if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS)
ffffffff81024169:       66 85 c0                test   %ax,%ax
ffffffff8102416c:       75 0a                   jne    ffffffff81024178 <__send_ipi_mask+0x1d8>

注意0xffffffff81024166之前,有一条mov 0x19462a0(%rip),%rbx,此处把hv_hypercall_pg赋值给了rbx。0xffffc9000001d000应该是此时hv_hypercall_pg的值。

可以看出是hv_hypercall_pg被使用的时候发生了Page Fault,初步估计是什么东西错误地提前把它释放了。

先做一个Bisect吧。

经过10多次recompile,发现commit 引入了这个问题,内容很清晰,用Hypercall去做IPI。

之后又仔细梳理了一下Kexec的过程,发现Panic的地方正好对的上,分别是在和APIC通讯和Send REBOOT_VECTOR这个IPI。分别在这两个步骤之前直接返回失败,kexec便会Fail,不会Panic。

发现HyperV重写了

在 Tang Hex 上跑香山 CPU

首先在Xilinx官网下载了Vivado,不清楚License是如何弄得… 但我下载下来安装了就能用…( ´_ゝ` )。

官方的BSP,不知有啥用,先放到Vivado里再说:https://github.com/sipeed/Tang-Hex-BSP。

然后把 Xilinx 的 UG1165 下载下来大概翻了翻。

要结合 SIPEED 官网可以在 HDK 里下载的 Lichee Tang Hex.pdf 来看:https://dl.sipeed.com/shareURL/TANG/Hex/HDK

然后在 https://dl.sipeed.com/shareURL/TANG/Hex/Projects 下载了示范 Project project_zynq_hex.zip,直接解压扔到 Vivado 里,根据提示升级一下 IP 和重新 build 一遍。然后 Export Hardware。

然后在 Vitis 里,用刚刚 Export 的 Hardware 建立一个 Platform Project,再建立一个 Application。

问题一:Pin Number 如何确定:EMIO 对应的就是从54开始往上加,MIO就是对应数字,如果是 AXI GPIO 等扩展出来的,就调用驱动。

还记得我在大学的时候,全宿舍只有我一个是第一志愿报的计算机,全年级估也没几个是感兴趣而去做程序员的。

我是小县城的留守儿童,家庭问题导致家庭环境异常恶劣,比孤儿院都惨,即便现在都隔三岔五梦到小时候而哭醒。而且村一直没通网。大概三两岁还不怎么会说话的时候,有人带过来了一台笔记本。我一下子就被这个铁盒子吸引了,从哪之后就励志要做一个用计算机的人。但当时的我也不知道什么人用计算机,所以就总说是科学家:),现在想想,计算机科学家也算是科学家,也是因为这个影响现在工作之余也在钻研底层,数学,学术之类的内容。

但是生活确实挺打击人的,特别是大学之后。相比我到了高中才接触到手机,网络。大学同级的一大把都是小学就学VB,中学参加OI,这一对比差距有点大。即便如此,我还是成了同学眼中的大佬,基本上全班抄我一个作业,一个人代做10份课设这种事情也经常发生。但是真的去参加一些拿得出手的事情,比如ACM,各种竞赛,都会苦于没有队友,没有队伍,没有老师,也没指导(世界上有ACM和OI这两个玩意也是我大三才知道的…)。有经验的大佬看不上我,我自己本身就是无头苍蝇乱碰,其他同学基本上是完全抱大腿,做过几个项目,最后都变成了一个人做多分工…

可能就是兴趣使然吧,很多沮丧的时候去写一会代码,沉浸在小世界里感觉会好一些。于是业余时间就自己研究一些开源项目,给不少项目做了贡献,也因此在工作上有了很大进展,Linux Kernel,Kubernetes,各种发行版都留下了不少commit。也搞了一些轮子,去各种会议听了或发表了一些演讲。而且时间长了,发现差距在越拉越近,曾经很多仰慕的大神,渐渐发现也不过如此,现在各种领域自己不说是精通也都门清了。

不过,我一直感觉我的生活有一个断层,生活就是计算机了。平时基本没有社交,因为公司远程上班我已经2年没出过门了(如果排除一年出去几次去交费之类的),要么写代码,要么打游戏,听听音乐,这似乎就是我生活的全部了。感觉自己真的喜欢计算机,喜欢代码,不想结婚,但现在却又感觉有点空虚。

奇异的 SSH 连接错误

今天突然不能连接到我的一个树莓派了,SSH连接被拒绝:

# ssh 172.21.2.128 -v

OpenSSH_8.6p1, OpenSSL 1.1.1l  FIPS 24 Aug 2021
... <snip> ...
debug1: Local version string SSH-2.0-OpenSSH_8.6
kex_exchange_identification: read: Connection reset by peer
Connection reset by 172.21.2.128 port 22

所幸还有物理终端,到 Pi 上一看;

# journalctl -e

... <snip> ...
sshd[4984]: debug1: Forked child 5051.
sshd[5051]: debug1: Set /proc/self/oom_score_adj to 0
sshd[5051]: debug1: rexec start in 7 out 7 newsock 7 pipe 9 sock 10
sshd[5051]: debug1: inetd sockets after dupping: 5, 5
sshd[5051]: debug1: getpeername failed: Transport endpoint is not connected
sshd[5051]: debug1: ssh_remote_port failed

看起来十分迷惑… 看了下sshd源代码,这里似乎是网络被断开了,把 sshd 关掉,开 netcat 看看 22 端口有啥问题:

# netcat -l 22

在客户端:

# netcat 172.21.2.128 22

发现握手正常,之后发送任何信息都会被断开,在 Pi 这边开 tcpdump 看看:

# tcpdump -i any 'tcp port 22 and ip' -vvvv

13:08:22.929265 eth0  In  IP 172.21.12.242.34322 > 172.21.4.1.ssh: Flags [S], seq 4077360934, win 64240, options [mss 1460,sackOK,TS val 484745913 ecr 0,nop,wscale 7], length 0
13:08:22.929735 eth0  Out IP 172.21.4.1.ssh > 172.21.12.242.34322: Flags [S.], seq 595516270, ack 4077360935, win 65160, options [mss 1460,sackOK,TS val 923544308 ecr 484745913,nop,wscale 7], length 0
13:08:22.930221 eth0  In  IP 172.21.12.242.34322 > 172.21.4.1.ssh: Flags [.], ack 1, win 502, options [nop,nop,TS val 484745914 ecr 923544308], length 0
13:08:22.931183 eth0  In  IP 172.21.12.242.34322 > 172.21.4.1.ssh: Flags [P.], seq 1:22, ack 1, win 502, options [nop,nop,TS val 484745915 ecr 923544308], length 21: SSH: SSH-2.0-OpenSSH_8.6
13:08:22.931335 eth0  Out IP 172.21.4.1.ssh > 172.21.12.242.34322: Flags [.], ack 22, win 509, options [nop,nop,TS val 923544310 ecr 484745915], length 0
13:08:22.931861 eth0  In  IP 172.21.12.242.34322 > 172.21.4.1.ssh: Flags [R], seq 4077360956, win 0, length 0
13:08:23.135704 eth0  In  IP 172.21.12.242.34322 > 172.21.4.1.ssh: Flags [P.], seq 1:22, ack 1, win 502, options [nop,nop,TS val 484746119 ecr 923544308], length 21: SSH: SSH-2.0-OpenSSH_8.6
13:08:23.135986 eth0  Out IP 172.21.4.1.ssh > 172.21.12.242.34322: Flags [R], seq 595516271, win 0, length 0

Pi 这边看起来是 ssh client 主动发了个 TCP Reset?再看看客户端:

tcpdump -i any ‘tcp port 22 and ip’ -n 655ms  Mon 11 Oct 2021 01:09:42 AM CST

01:09:46.710289 enp0s31f6 Out IP 172.21.12.242.34324 > 172.21.4.1.ssh: Flags [S], seq 3002468069, win 64240, options [mss 1460,sackOK,TS val 484829694 ecr 0,nop,wscale 7], length 0
01:09:46.711225 enp0s31f6 In IP 172.21.4.1.ssh > 172.21.12.242.34324: Flags [S.], seq 742740888, ack 3002468070, win 65160, options [mss 1460,sackOK,TS val 923628089 ecr 484829694,nop,wscale 7], length 0
01:09:46.711267 enp0s31f6 Out IP 172.21.12.242.34324 > 172.21.4.1.ssh: Flags [.], ack 1, win 502, options [nop,nop,TS val 484829695 ecr 923628089], length 0
01:09:46.711628 enp0s31f6 Out IP 172.21.12.242.34324 > 172.21.4.1.ssh: Flags [P.], seq 1:22, ack 1, win 502, options [nop,nop,TS val 484829695 ecr 923628089], length 21: SSH: SSH-2.0-OpenSSH_8.6
01:09:46.712083 enp0s31f6 In IP 172.21.0.1.ssh > 172.21.12.242.34324: Flags [.], ack 3002468091, win 509, options [nop,nop,TS val 923628090 ecr 484829695], length 0
01:09:46.712204 enp0s31f6 Out IP 172.21.12.242.34324 > 172.21.0.1.ssh: Flags [R], seq 3002468091, win 0, length 0
01:09:46.919426 enp0s31f6 Out IP 172.21.12.242.34324 > 172.21.4.1.ssh: Flags [P.], seq 1:22, ack 1, win 502, options [nop,nop,TS val 484829903 ecr 923628089], length 21: SSH: SSH-2.0-OpenSSH_8.6
01:09:46.920232 enp0s31f6 In IP 172.21.4.1.ssh > 172.21.12.242.34324: Flags [R], seq 742740889, win 0, length 0

恩?中间那个 172.21.0.1.ssh > 172.21.12.242.34324: Flags [.] 是什么情况… 难怪会 reset。

看了下 Network Manager 配置,好家伙,Network Mask 忘了设置了… 好一顿折腾,太蠢了…

超计算(Hyper computation)模型

在 Tang Hex 上运行香山 CPU