八哥之神【番外篇9】

听说鲁豫要来采访稣
请戴口罩采访

1. 疫情已经好转很多,终于又可以采访稣!最近在忙什么呢?

忙跳槽。最近两次采访之间,稣一共任职三个公司。

稣现在从事什么行业?

“AIoT 是我的爱,绵绵的金山脚下花正开”难道这歌,稣会唱给你听?

唱的还行,您随意。

“什么样的加班是最呀最摇摆,什么样的养生才是最开怀……”

2. 近期剧情似乎给配角更多笔墨?

是的。这是为了让主角晚点死,是拖剧的惯用套路。

樱国是映射日本吗?

如果您认真阅读,就会发现一个细节:《八哥之神前传【9】》里都是说“樱国”,而《八哥之神前传【10】》中施付说的是“日本”。

是哦,这是不小心写错吗?

不是。这是有区别的。《八哥之神前传【9】》里的故事发生在识界,而《八哥之神前传【10】》的故事则发现在咱们这个世界。

3. 上次您告诉我会出现“李心觎”,但《八哥之神前传【10】》出现的却是“李星觎”,这次是写错了吧?

当然不是。这是剧情需要,后面会解释清楚的,先不剧透。

4. 出现“狐狸精”这种神话色彩的人物,是不是违反您之前说的“无神论”?

这个问题稍微复杂点。这故事发生于 1994 年秋天,圣小开才 12 周岁不到。

他只是个孩子呀!!!

被一系列恐怖的景象吓坏,产生幻觉您可以理解吧!

而且后来开讲给陈因提听时,她并未相信。说明这也可能只是开一脸正经讲的鬼故事而已,作为最了解开的陈因提都如此认为,读者有啥理由拿它当神话看?

原来如此,这可以理解为主角的性格塑造吧!

没错!您想,大部分男人要三四十岁才会遇到狐狸精,而开十岁出头就遇到,而且免疫,这难道不够装逼?

5. 稣,您又赢了!另外,“纯狐连玉”和之前出现的“胡小玉”是同一只吗?

显然不是呀!您看,演员都不是同一个!胡小玉是白色的,长相冷艳,气质是性感魅惑型。纯狐连玉,光看姓,就知道是上古神话风,走的是庄严又有点幽默的大姐路线。

胡小玉只存在于圣小开梦中,是圣小开见过的某类美女的凝神具体。名字很像,主要原因是胡小玉的最初形象是按照纯狐连玉梦见的,后来再也没见过纯狐连玉,形象不断模糊,又不断得到其她美女形象加强就进化出胡小玉。

纯狐连玉是真的狐狸精,而胡小玉更像人。

6. 稣的梦究竟是什么奇妙的世界?能用最贴切的语言描述分享吗?

  • 脑的触感比人体表面最敏感的皮肤还敏感。

  • 爱情里只有鲸神链那部分才是最深刻的。

7. 陈博士的干儿子长生和古思是怎么回事?

孟长生是早期基因编辑婴儿里比较成功的一个,性别染色体来自圣小开,其它基因都来自陈博士,以此为模板优化而成。所以被陈博士收为干儿子,并安排在贾总公司担任一个小领导。

古思是完全基因编辑人造人,只有卵巢是根据陈博士的基因设计,专门用于代孕。这在未来很流行哦!现在大家可能还难以接受。

没关系,等大家有钱再说。

8. 还是有很多读者表示看不懂,您能再提示一下吗?

一部剧能不能看,首先选角很重要,然后靠演员、导演、剧组的努力配合,后期制作、宣传也很重要。

稣只是一个编剧啊!看不懂绝壁不是编剧的问题,您下次采访一下各位演员吧!

八哥之神前传【11】

2042 年

陈博士:长生最近怎么样?

贾力劣:工作尽心尽职无可挑剔,就是好多女员工都打他的主意。

陈博士:难道身份泄露了?

贾力劣:不会!这事严格保密,连他自己都不知道。

陈博士:那就好。

贾力劣:不过您的干儿子年纪也不小,女朋友经常换,坚持不结婚,难免被人说三道四。

陈博士:嗨,这就是基因的力量,思想都差不多。

贾力劣:嗯,他的基因几乎和您一样。

陈博士:他比我还过分,我只是不想生孩子,找个丁克结婚还是可以的。

贾力劣:女朋友换得勤,恐被称渣男呢。

陈博士:他只是个孩子呀!

贾力劣:哦!em……呃!那个,按您基因设计出来的代孕女孩已经送给开哥。

陈博士:很好。这才是正事!管我干儿子的私生活,活腻了?

贾力劣:是是是。她的卵细胞 100% 和您一样。您放一百个心。

陈博士:贾总办事就是靠谱,尤其是保密工作。

贾力劣:懂!相关资料已经销毁。

1994 年

黄金灯已经是著名脑外科专家。他回到虎纠小县城度假的一个夜晚,遇到几个流氓为难大排档卖唱的小妹。

黄金灯:年轻人,文明点!

流氓头:摸个奶,我给钱就是,要你管啊!

黄金灯:小姑娘,你愿意吗?

小姑娘:不!不愿意。

黄金灯:听到没?这位姑娘不卖身。

流氓头:你谁啊?大叔!

黄金灯:我是一名脑外科医生。知道小李飞刀吗?

流氓头:哦?李医生?还飞刀!哈哈哈……

黄金灯亮刀:我这几把叫小灯飞刀,比小李飞刀厉害。

流氓头:大叔,你是不是脑子有问题啊?兄弟们,教训一下他!

黄金灯一出手,飞刀准确插在后面两个流氓鞋头,避开脚趾,将鞋钉在地上,刀拔都拔不动。

流氓发现往前走脚就会被刀切,知道遇到高手,吓得不敢动。

黄金灯:来。我不用飞刀,截拳道对付你。

流氓头跪倒:大叔!小的不识抬举,跟您道歉了。

黄金灯:转过去,跟小姑娘道歉。

小姑娘:大叔怎么称呼?

黄金灯:道释·圣小开。

2003 年

陈因提:死开,你家的牌坊为什么写的是龙田氏?

圣小开:上面写的是:龙田圣心,无尽乾坤。

陈因提:瞎说,上面只有三个字!

圣小开:em?我怎么记得是八个字!

陈因提:又发神经?

圣小开:有可能……晚上安定后告诉你。

1994 年

圣小开出生在道州德国鹰熊岛乾坤村,从小就很好奇村外面是什么。

累积无数次冲动,开终于打算勇敢地往西走,穿过盐田,去看看树木后面是什么!

虽然不远,却感觉走了很久。终于走到树木后面,是一条公路,横穿公路后是一片海沙田,听大人说这田盛产地瓜和花生。

强行穿过海沙田,是小土坡,再翻过去是一些河和另一些盐田,再过去就是海。

开明白,一路向西是无法走到远处的高山。心想:“试试向北,看那片树林后面是不是还是海?”

向右转!走着走着就是一个庙,再过去是灵堂。开想了三秒钟,可怕……还是绕过去吧!

但是开太天真了,虽然绕过灵堂,但它附近有一大堆土坟!于是为了避开它们,居然绕迷路!

平时当开要遇到危险时,都会有路人甲乙冒出来提醒,这次居然没有?

咦?那块石头上面好像有字!走进一看,不禁念出上面的字:“龙田圣心,无尽乾坤”。好酷的感觉!

纯狐连玉:这界碑下面是仙山公。

开转身一看,是个黄色衣装的漂亮的姐姐,便问:仙山公是谁?

纯狐连玉:你干妈的父亲。

圣小开:哦?可是我拜了两位干妈,您说的是哪位?

纯狐连玉:是姑婆祖。

圣小开:哦!原来是族谱第一人。

纯狐连玉:赶紧拜一拜。

圣小开双手合十俯身朝拜:好的。敢问姐姐又是谁?

纯狐连玉:我是仙山公陵墓的守护兽,纯狐连玉。

圣小开:什么?胡连玉?

纯狐连玉:纯狐,连玉。

圣小开:好的,小玉姐姐。

纯狐连玉:死囡仔,按辈分我和你姑婆祖同辈。

圣小开:婆婆好!

纯狐连玉:我是狐狸精。你不害怕?

圣小开:狐狸精?我还是孙悟空转世呢!

纯狐连玉:不怕也好。你跪下,给仙山公磕三个头,我可以实现你一个愿望。

圣小开:这么好康?我要长生不老。

纯狐连玉:死囡仔,活那么久干嘛?三千年就不错啦!

圣小开:成交!我磕。

磕完头,纯狐连玉已经不见。

2003 年

陈因提:狐狸精都出来了!你真能做白日梦!

圣小开:我很严肃好不好!后来我还梦见过它,问它为什么选择我。

陈因提:它怎么说?

圣小开:说我是世间少有的能做很真实的连戏剧梦的人。

陈因提:好像很厉害的样子哦。但是这种能力有什么用?

圣小开:这种能力可以让我从梦中进入全人类,乃至全宇宙所有智慧生命的集体意识中。

陈因提:噗!然后呢?

圣小开:神不会救助任何个体,你懂吧?

陈因提:是啊,要不然神应该来治治你这惊人的幻想能力……

圣小开:不开玩笑,人类社会有很多问题不是在明面可以解决的,或者说这些问题也不需要从明面去解决,而应该通过观测集体意识从而影响它。

陈因提:好吧,你赢了,但是能具体点吗?

圣小开:很多问题的根本都是心灵问题。比如说,残疾人很敏感地发现别人看待他异样的眼光,这可能加强他对自己的嫌弃和遗憾。当你看到别人的问题,一个惊讶、困惑的眼神,对方可能解读成你看到他们差劲的一面,自觉得你会嫌弃他们,于是就烙下一个芥蒂。

陈因提:那你到底能做什么?

圣小开:我可以在睡着的时候进入集体意识去观测大家,让大家的意识明白不管好坏,神都不会遗弃他们。当我醒来世界就会更美好。

陈因提:那你好忙哦,赶紧睡……晚上来观测一下我的意识,看我的意识会不会打你。

圣小开:还好,像我这样的,地球上有 23 人。

CComPtr 和 CComQIPtr

问题

CComPtr 和 CComQIPtr 长得这么像,有啥关系和区别?

分析

  1. 看代码 CComQIPtr 继承自 CComPtr,CComPtr<IUnknown> 没问题,但 CComQIPtr<IUnknown> 报错,应该使用 CComQIPtr<IUnknown, &IID_IUnknown>。

  2. 不同类型 CComPtr<> 不能直接互相构造;CComQIPtr<> 则可以,因为 CComQIPtr 会进行目标类型的 QueryInterface。

1
2
3
4
5
CComPtr<IUnknown> u;
// ...
CComPtr<IDispatch> d(u); // error

CComQIPtr<IDispatch> d(u); // right, will call QueryInterface
  1. 两者构造/赋值时,都会进行 AddRef,如果不想 AddRef,可以使用裸指针(必须十分清楚自己在干嘛!)。
1
2
3
4
5
6
7
CComPtr<IUnknown> u;
// ...
CComPtr<IUnknown> u1(u); // will call AddRef

CComQIPtr<IDispatch> d(u); // will call QueryInterface(call AddRef impliedly)

auto raw = static_cast<IDispatch*>(u.p); // won't call AddRef
  1. 两者赋值时,小部分行为不同。以下模板使得,当等号两边类型不同时,CComPtr 为左值和 CComQIPtr 为左值,表现不同。
1
2
3
4
5
6
7
8
9
10
// CComPtr
template <typename Q>
T* operator=(_Inout_ const CComPtr<Q>& lp) throw()
{
if(!this->IsEqualObject(lp) )
{
AtlComQIPtrAssign2((IUnknown**)&this->p, lp, __uuidof(T));
}
return *this;
}

总结

  • 您可以忘记 CComPtr,只使用 CComQIPtr;

  • 或者,尽量使用 CComPtr,只在必要时使用 CComQIPtr。

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#include <iostream>

#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>

MIDL_INTERFACE("00554d55-0000-0000-C000-000000000041")
IA : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE FuncA() = 0;
};

MIDL_INTERFACE("00554d55-0000-0000-C000-000000000042")
IB : public IA {
public:
virtual HRESULT STDMETHODCALLTYPE FuncB() = 0;
};

class A : public IA {
public:
~A() { std::cout << __FUNCTION__ << "\n"; }

HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) {
if (__uuidof(IA) == riid || __uuidof(IUnknown) == riid) {
*ppvObject = this;
std::cout << __FUNCTION__ << "\n";
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE AddRef(void) {
++ref_;
std::cout << __FUNCTION__ << ": " << ref_ << "\n";
return ref_;
}

ULONG STDMETHODCALLTYPE Release(void) {
--ref_;
std::cout << __FUNCTION__ << ": " << ref_ << "\n";
if (0 == ref_) {
delete this;
}
return ref_;
}

HRESULT STDMETHODCALLTYPE FuncA() {
std::cout << __FUNCTION__ << "\n";
return S_OK;
}

private:
int ref_ = 0;
};

class B : public IB {
public:
~B() { std::cout << __FUNCTION__ << "\n"; }

HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) {
if (__uuidof(IB) == riid || __uuidof(IUnknown) == riid) {
*ppvObject = this;
std::cout << __FUNCTION__ << "\n";
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE AddRef(void) {
++ref_;
std::cout << __FUNCTION__ << ": " << ref_ << "\n";
return ref_;
}

ULONG STDMETHODCALLTYPE Release(void) {
--ref_;
std::cout << __FUNCTION__ << ": " << ref_ << "\n";
if (0 == ref_) {
delete this;
}
return ref_;
}

HRESULT STDMETHODCALLTYPE FuncA() {
std::cout << __FUNCTION__ << "\n";
return S_OK;
}

HRESULT STDMETHODCALLTYPE FuncB() {
std::cout << __FUNCTION__ << "\n";
return S_OK;
}

private:
int ref_ = 0;
};

HRESULT CreateObject(REFIID riid,
_COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) {
if (__uuidof(IA) == riid || __uuidof(IUnknown) == riid) {
auto p = new A;
p->QueryInterface(riid, ppvObject);
return S_OK;
} else if (__uuidof(IB) == riid) {
auto p = new B;
p->QueryInterface(riid, ppvObject);
return S_OK;
}
return E_NOINTERFACE;
}

int main() {
std::cout << "---- Raw pointer:\n";
{
IUnknown* u;
HRESULT hr = CreateObject(__uuidof(IA), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
auto a = static_cast<IA*>(u);
a->FuncA();
a->Release();
}
std::cout << "---- ctor\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IUnknown), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComPtr<IUnknown> u2(u); // will call AddRef
CComQIPtr<IA> a(u); // will call QueryInterface(call AddRef impliedly)
CComQIPtr<IB> b(a); // will call QueryInterface(call AddRef impliedly)
a->FuncA();
}
std::cout << "---- CComPtr A=B:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IB), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComPtr<IA> a;
a = u; // will call QueryInterface(call AddRef impliedly)
if (a) {
a->FuncA();
}

CComPtr<IB> b;
b = u;
if (b) {
b->FuncA();
b->FuncB();
}

// template<T, Q>
a = b; // failed
if (a) {
std::cout << "failed!\n";
a->FuncA();
}
}
std::cout << "---- CComQIPtr A=CComPtr<B>:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IB), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComQIPtr<IA> a;
a = u; // will call QueryInterface(call AddRef impliedly)
if (a) {
a->FuncA();
}

CComPtr<IB> b;
b = u; // will call QueryInterface(call AddRef impliedly)
if (b) {
b->FuncA();
b->FuncB();
}

a = b; // will call AddRef
if (a) {
std::cout << "OK! B is-a A\n";
a->FuncA();
}
}
std::cout << "---- CComQIPtr A=CComQIPtr<B>:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IB), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComQIPtr<IA> a;
a = u; // will call QueryInterface(call AddRef impliedly)
if (a) {
a->FuncA();
}

CComQIPtr<IB> b;
b = u; // will call QueryInterface(call AddRef impliedly)
if (b) {
b->FuncA();
b->FuncB();
}

a = b; // will call AddRef
if (a) {
std::cout << "OK! B is-a A\n";
a->FuncA();
}
}
std::cout << "---- CComPtr B=A:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IUnknown), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComPtr<IA> a;
a = u; // will call QueryInterface(call AddRef impliedly)
if (a) {
a->FuncA();
}

CComPtr<IB> b;
b = u; // failed
if (b) {
b->FuncA();
b->FuncB();
}
}
std::cout << "---- CComQIPtr B=A:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IUnknown), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
CComQIPtr<IA> a;
a = u; // will call QueryInterface(call AddRef impliedly)
if (a) {
a->FuncA();
}

CComQIPtr<IB> b;
b = u; // failed
if (b) {
b->FuncA();
b->FuncB();
}
}
std::cout << "---- CComQIPtr<IB>:\n";
{
CComQIPtr<IB> b;
HRESULT hr = CreateObject(__uuidof(IB), reinterpret_cast<void**>(&b));
std::cout << hr << ", " << b << "\n";
b->FuncA();
b->FuncB();
}
std::cout << "---- CComPtr<IA>:\n";
{
CComPtr<IA> a;
HRESULT hr = CreateObject(__uuidof(IB), reinterpret_cast<void**>(&a));
std::cout << hr << ", " << a << "\n";
a->FuncA();
}
std::cout << "---- CComPtr<IUnknown>:\n";
{
CComPtr<IUnknown> u;
HRESULT hr = CreateObject(__uuidof(IA), reinterpret_cast<void**>(&u));
std::cout << hr << ", " << u << "\n";
auto a = static_cast<IA*>(u.p);
a->FuncA();
}

return 0;
}

用 VS2019 应该尽量链接带有 Spectre 缓解措施的库

问题

愉快地装完 VS2019,编译一个使用 ATL 的工程,结果失败。

LINK : fatal error LNK1104: cannot open file ‘atls.lib’

分析

看 VC++ Directories 里的 Library Directories,有一个 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\atlmfc\lib\spectre\x64,但这个目录并没有 atls.lib

反而 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\atlmfc\lib\x64 目录下有 atls.lib

解决

安装 VS 时,应该选择“带有 Spectre 缓解措施、适用于最新 v142 生成工具的 C++ ATL (x86 和 x64)”。

八哥之神前传【10】

1998 年,周易和萧竫告别

周易:我准备去南洋研究电子现金。

萧竫:老师,您不是一直专研人工智能吗?为啥突然改变方向?

周易:老师对人工智能的现状太失望了,即使再过十年、二十年也没有一种力量能够将人工智能真正落地。

萧竫:三十年、四十年呢?

周易:老师并没有放弃!必须有人做长远打算,做好未来的铺垫。

萧竫:您是说电子现金……就是人工智能未来的希望?

周易:没错!人工智能最终要依靠“钱”来作为连结,把世界上大量机器连接起来,才可能产生机器意识。而这个“钱”,不能是现在的纸币,应该是电子现金。南洋有些国家需要匿名电子货币溪黑签,有实施的土壤。

萧竫:我可以和您一起去吗?

周易:别。你还年轻,有大好前途。好好学习,找个同龄人。

2003 年,周易和施付同居

一天晚上,周易和施付正要休息,门外来了一个女子按门铃。

施付:聪哥,这么晚了,还有人找你?

周易:奇怪呀!外面还下着雨呢!

周易:萧竫!你这么跑来菲律宾了?

周易对房内的施付说:是我的学生。

萧竫:老师,您成家了?

周易:是啊,你呢?

萧竫:没,还没……国内发生了很严重的疫情,现在很多人失业,我研究的人工智能领域一直没什么突破,考虑和老师一样,改研究电子现金,您能帮帮我吗?

周易:你需要什么?

萧竫:您有没有还没发布的电子现金方面的论文?

周易:这……有是有,不过我才开始构思,打算过几年匿名发表的。

萧竫脸色一变:匿名发表?

周易:老师现在很低调,在菲律宾名字都改了,你是怎么找到这儿的?

萧竫:我可找得辛苦了。

施付:要不要进来?

萧竫:不用,不用。我该走了。再见老师。

施付:她是中国人?

周易:是啊,她是我在中国时的女朋友。

施付:哦,我记得你提过她。怎么找到这里来的?

周易:不对劲。我怀疑她被不明势力控制,可能是来套我的研究成果的,看来我的身份已经不安全。

施付:跟我回日本?

周易:好。

2042 年

古思:这个时间点?莫非周老师就是……

圣小开:嗯!后来世界出现区块链,每一个链是一个机器神经元,无数机器神经元通过跨链技术组成一个机器脑,这就是真·人工智能的雏形,最后在量子计算机里发展成现在的样子。

古思:没想到是这样。更没想到周老师居然还谈过两次恋爱!

圣小开:谁都年轻过!

古思:也是。爷年轻时,也是艳福不浅吧?

圣小开:年轻时……em,很年轻,四五岁时,就有两个女孩子说长大以后要嫁给爷。

古思:哦?这么早的事情,爷还记得住?

圣小开:也不是记得特别清楚,因为后来那两个小女孩,就再也找不到了,直到大学毕业后,在母校莫名其妙地认识一个和那两个小女孩里的妹妹同名同姓的学妹。

1987 年夏天

开被父母送到姥姥家,李家村寄养。村口有一个池塘,一片榕树林,据说那是一棵榕树,四百年才长成一片。

池塘的台阶常有人洗衣服,面对池塘,左手边有一个牛棚。

背向池塘,往村里走,会过一条小沟,然后左边有一棵柚子树。

大树下面好乘凉,夏天小伙伴们都在榕树下玩。慢慢地认识笑李子和一对双胞胎。

笑李子本名李小谢,他说叫他谢小李也行,因为他爸姓李,他妈姓谢,但开习惯叫他笑李子,因为他很爱笑,每天拼命要把脸笑到瘫。

双胞胎姐姐叫李星觎,妹妹叫李冰月,她们都很喜欢开。有一次冰月为了单独和开玩耍,把星觎骗到牛棚里,关起来,星觎从小就很淡定,居然就在里面站着,独自玩了很久才被回来的养牛人解救出来。

后来冰月觉得很对不起姐姐,就把开让给姐姐了。

李冰月:姐姐以后嫁给开当大老婆,我当小老婆。

2042 年

古思:好可爱啊,嘻嘻。

圣小开:不不不,这个故事不可爱,还十分恐怖。

古思:哦?后来怎么了?

圣小开:后来爷长大了,去调查这对双胞胎,李家村的大人们都说没有这么一对和爷同龄的双胞胎,甚至村里已经几十年没有女双胞胎!但笑李子是存在的,他比爷小几个月。

古思:那位叫李冰月的学妹呢?

圣小开:肯定不是,学妹是 1997 年的。据说村里的女双胞胎要追溯到 1955 年,她们在 1959 年 1 月 3 日就死于战火……

古思:这不科学啊!

圣小开:是很不科学,爷长大后还梦见过她们一次。

梦境

李冰月:开。

圣小开:冰月?你都长这么大了?

李冰月:哈哈,你也是呀。

圣小开:星觎呢?

李冰月:被我关在牛棚呢!嘻嘻。

圣小开:什么?!关这么多年,不会饿死了吧!

李冰月:呀!是哦,咱们快去救她。

圣小开脑补一副骷髅,心惊肉跳来到牛棚,开门瞬间惊呆了。

李星觎:妹妹,你怎么长这么大了?

李冰月:姐姐,你怎么保持 4 岁的?

圣小开:这个地方是时间隧道吗?咱们赶紧离开。

李星觎:不行,我好饿,没力气离开。

李冰月:我去给姐姐拿吃的。

李星觎:别把我一个人留在这里。

圣小开:你这么小,我抱你出去就好。

走出牛棚,星觎也变成一个大姑娘。圣小开带她们回一栋三层楼。

圣小开:你们俩是 1959 年 1 月 3 日就死于战火的那对双胞胎吗?

李星觎:不是呀。我们是池塘里的美人鱼,我们不能离开水太久。

后来三层楼都被水注满,她们在楼内快乐地游玩。圣小开无法呼吸,赶紧找出口,所有窗们都堵死,最后找到二楼楼梯的小天窗逃出来。但二楼外面没有水,摔下来吓醒。

2042 年

古思:鬼魂和美人鱼都不可能,她们也许也是被父母临时寄养在李家村的吧,就和爷一样。

圣小开:希望是,如果真是这样,那爷还有希望找到她们。

八哥之神前传【9】

自从过去、现在、未来佛都圆寂后,世界进入七鹰劫,人间爱欲繁华,天堂地狱皆被同化。

1976 年,黄金灯在樱国谈恋爱,顺便读研。他本科是读计算机的,理想是实现脑机合一式的意识永生,但由于时代落后,他慢慢意识到,这个技术在他的时代是无法实现的,于是决定改读脑科医学,打算通过克隆加换脑手术让生命延长。

然而现实总是背离理想,这是一个血腥的世界,满地人体器官,即使在大街上散步,他的眼里也都是血红色一片,随时要小心踩到血肉。

血,一片一片一片,拼出你我的缘分。我的爱因你而专生,你的手摸出我的心疼。

由于场面过度血腥,稣吓醒了!

2042 年,床上

圣小开:“你怎么没睡?”

古思:“才几分钟,还没入睡呢?”

圣小开:“什么?爷都已经做了一个梦,吓醒了!”

古思:“什么梦?给我讲讲?”

圣小开:“虽然是梦,但却是真实故事,只不过主角是黄金灯大师。”

1976 年

东湖有个湖心岛叫樱花岛,是谈恋爱的好地方。

黄金灯心想:“去樱花岛吸吸天地灵气,也许我还有救。”

旅游船荷载 26 人,他认真地数了一遍救生衣,确实有 26 个。习惯性地环扫一番,透视人头,都是妖魔鬼怪,突然视线停留在一个美女脸上,有皮肤的,英气逼人,而且似乎也是中国人。

男女之间的故事都从八哥开始……船出八哥,柴油机罢工,老板说:“大家不用慌,很快就到湖心,我们用竹竿撑过去。”

又过了一会儿,船夫感觉竹竿变沉了,好像插到一个东西,提出水面,是一块骨盆……引起恐慌。

黄金灯专业地站出来说:“我上过人体解剖课,这个一定是人类的骨盆,很可能是个 20 岁左右的年轻男子。”

美女也专业地站出来说:“我是实习警察,最近确实有个 21 岁的失踪男子。”

黄金灯:“凶手或帮凶应该是船夫,知道这里深水区里有肉食性鳗鱼,所以把尸体扔到这喂鱼。”

美女:“怎么防止尸体浮起来呢?”

黄金灯:“绑块石头就行。”

2042 年,床上

古思:“好像是个不吉利的开头!”

圣小开:“结尾其实也不太好。”

1976 年,樱花岛

黄金灯:“你好,警官,我是东湖边上医学院的学生,黄金灯。您好像也是中国人?”

美女:“原来是医学院高材生!我爸爸是樱国人,妈妈是中国人,我的中文名叫施付。”

黄金灯:“施付?em……我还是叫你的樱文名吧!”

施付:“哦,那你就叫我京子吧!”

黄金灯:“京子!”心想:“怎么不是惠子……”

施付:“你今天不用上课吗?”

黄金灯:“我晕血,出来放松一下。”

施付:“学医的,还晕血?”

黄金灯:“是我想得太简单了,还没脱敏吧!”

施付:“你刚才不是很淡定?”

黄金灯:“是哦,好像没那么恶心了!咦!我现在看世界,不是血腥模式了!!”

施付:“嗯嗯,你的专业很有用,要加油!”

黄金灯:“京子小姐,你呢?”

施付:“我来祭拜我爸爸,他葬在这岛上。”

黄金灯:“葬在岛上……原来你是富家小姐!怎么当警察呢?”

施付:“我爸爸死于黑帮暗杀,所以我立志要替他报仇,消灭黑帮。”

黄金灯:“好理想。但是以警察的身份报仇,不会有些不方便吗?”

施付:“是的,要以大局为重,不能公报私仇。”

2042 年,床上

古思:“后来他们恋爱了?”

圣小开:“对。大师遇到京子后,开始对解剖脱敏,并苦练小灯飞刀。”

古思:“小灯飞刀?”

圣小开:“是的。小灯飞刀是一种很厉害的武器,他还发明双刀并进。”

古思:“有什么用?”

1976 年,东湖烟花

星空下,黄金灯搂着京子一起看烟花。

黄金灯:“我已经练成小灯双刀!”

施付:“有什么用?”

黄金灯:“我试过单刀瞄准人体模型的心脏,却可能插在骨头上,致死率降低,而用双刀,都撞到胸骨的几率低很多。”

施付:“但是飞刀又不能比枪快呀!”

黄金灯:“飞刀比枪容易弄到,我可以用它保护你。”

2042 年,床上

古思:“理科男的浪漫?”

圣小开:“哈哈,后来大师真的用飞刀帮京子报仇了。”

古思:“他们后来在一起了吧?”

圣小开:“没有。大师后来回国,京子改行在南洋做投资遇到周老师,很狗血地结婚了。所以大师一直称呼周老师为情敌。”

跟 UMU 一起玩 OpenWRT(入门篇20):WOL

需求

家里有个 PC,关机状态,想在公司远程开机,可是家里没人,怎么办?

条件

  • 机器支持并开启 WOL (Wake On LAN)。

  • 机器通过板载网卡连接路由器(USB 有线网卡不行)。

解决

  1. 路由器需要有公网地址,如果没有,请参考《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》做中转,总之需要能 SSH 到路由器上。

  2. 路由器上安装 etherwake 或 wakeonlan。两者差别是:wakeonlan 是个 Perl 脚本,使用 UDP 包,不需要 root 权限。

  • 如果是在 openwrt 直接使用 root 账号,建议用 etherwake。
1
2
3
opkg update
opkg install etherwake
etherwake MAC_ADDRESS_OF_PC
  • 如果是 armbian,建议平时使用非 root,所以推荐 wakeonlan。
1
2
3
sudo apt update
sudo apt install wakeonlan
wakeonlan MAC_ADDRESS_OF_PC

测试

组装 PC 两台、Intel NUC 7i7BNH 一台测试用过。

Armbian 分区优化

问题

Android 电视盒刷 Armbian,分区时,EMMC 前面一部分没被利用,为什么?以及怎么办?

原因

u-boot 是为 Android 设计的,分区是按照 Android 需求分的。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
Partition table get from SPL is :
name offset size flag
===================================================================================
0: bootloader 0 400000 0
1: reserved 2400000 4000000 0
2: cache 6c00000 20000000 2
3: env 27400000 800000 0
4: logo 28400000 2000000 1
5: recovery 2ac00000 2000000 1
6: misc 2d400000 2000000 1
7: boot 2fc00000 2000000 1
8: system 32400000 40000000 1
9: data 72c00000 15f400000 4

其中 reserved 分区放着其它分区的名字、位移、大小等信息,如果被破坏 u-boot 将无法识别分区。

env 分区保存启动脚本,如果被破坏,可能导致系统无法启动。

解决

一般的 Armbian 安装脚本,都会跳过前面的分区,从偏移 700MB 处开始分区。

1
2
3
parted -s "${DEV_EMMC}" mklabel msdos
parted -s "${DEV_EMMC}" mkpart primary fat32 700M 828M
parted -s "${DEV_EMMC}" mkpart primary ext4 829M 100%

作为优化狂,UMU 显然无法接受这样的浪费!

  • cache 分区有 0x20000000 Bytes,也就是 512MiB,拿来做 /boot 分区岂不美哉?

  • logo 分区?不,UMU 不想看启动画面,直接覆盖掉吧!

  • 分区之间还有空闲!也不能放过!

所以,reserved 分区之后到 env 分区之前的全部空间都拿来做 /boot 分区,env 分区之后全部做 / 分区:

1
2
3
parted -s "${DEV_EMMC}" mklabel msdos
parted -s "${DEV_EMMC}" mkpart primary fat32 100MiB 628MiB
parted -s "${DEV_EMMC}" mkpart primary ext4 636MiB 100%

测试

玩客云和斐讯 N1 测试通过。

跟 UMU 一起玩 OpenWRT(入门篇19):检测 WiFi 入侵

问题

我怀疑有人在用工具穷举我的 WiFi 密码,我该怎么确认?

解决

运行 iw event,如果看到频繁出现 new stationdel station 的 log,说明有设备在频繁连接和断开。

如果您的路由器是小米路由器 Pro,则可以用 iwevent 代替 iw event,密码不对的 log 是 had deauthenticated,断开是 had disassociated

安全建议

设置密码时,应该检查一下您的密码是否在“字典”里。字典参考:

rockyou.txt contains 14,341,564 unique passwords, used in 32,603,388 accounts.

举个例子吧!稣打算用 10 个 0 做密码,先查一下……嗯哼!

valentine
idontknow
pikachu
little
diamond1
iloveu1
babyphat
peanut1
kittens
goddess
ballet
damien
nascar
171717
rangers1
winston
0000000000
rocky1
coolgirl
maymay
charlene
caramelo
selena
lucero
wendy
volcom
1435254
copper
cindy
baby123

地球真危险!稣回月球了……