-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathatom.xml
1908 lines (1742 loc) · 322 KB
/
atom.xml
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Snow Memory | Andrew Liu</title>
<subtitle>Snow Memory, Do one thing, Do it best.</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://andrewliu.in/"/>
<updated>2017-06-17T23:22:51.000Z</updated>
<id>http://andrewliu.in/</id>
<author>
<name>Andrew Liu</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Mac重装小计</title>
<link href="http://andrewliu.in/2017/06/18/Mac%E9%87%8D%E8%A3%85%E5%B0%8F%E8%AE%A1/"/>
<id>http://andrewliu.in/2017/06/18/Mac重装小计/</id>
<published>2017-06-17T22:52:41.000Z</published>
<updated>2017-06-17T23:22:51.000Z</updated>
<content type="html"><![CDATA[<div class="tip"><br> 本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.<br></div>
<blockquote>
<p>很久没有更新博客了, 前段时间迷上了王者农药, 戒了农药后又重新入了暴雪爸爸<code>暗黑3</code>的大坑, 呵呵.<br>除此之外, 公司离职回来一直准备毕业论文、毕业答辩、毕业相关材料, 真是焦头烂额.<br>不过想想十九年求学生涯就要结束了, 即将AFK了, 简直幸福.</p>
</blockquote>
<p>为什么要重装? Mac系统的乱七八糟的东西已经占据了90%的磁盘空间, 无法减少文件保持一定空闲磁盘空间, 这种情况已经严重影响了我的日常工作.</p>
<p>重装方案严格按照 Apple 官方文档 <a href="https://support.apple.com/zh-cn/HT204904" target="_blank" rel="external">如何重新安装 macOS</a> 执行.</p>
<h2 id="系统偏好设置"><a href="#系统偏好设置" class="headerlink" title="系统偏好设置"></a>系统偏好设置</h2><ul>
<li>允许安装任何来源的APP: <code>安全性与隐私->通用</code>. 若无该选项,请命令行执行<code>sudo spctl --master-disable</code></li>
<li>设置快捷键: <code>键盘->快捷键</code> 更改输入法切换快捷键</li>
<li>设置触摸板: 选取全部触摸板设置</li>
<li>设置触发角: <code>桌面与屏幕保护程序->触发角</code></li>
<li><p>设置密码验证: <code>系统偏好设置->安全性与隐私->选择 进入休眠或屏保后立即要求输入密码</code></p>
</li>
<li><p>编辑 /etc/paths(<code>sudo vim /etc/paths</code>)</p>
</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">/usr/local/bin</div><div class="line">/usr/local/sbin</div><div class="line">/usr/bin</div><div class="line">/usr/sbin</div><div class="line">/bin</div><div class="line">/sbin</div></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="软件安装"><a href="#软件安装" class="headerlink" title="软件安装"></a>软件安装</h2><blockquote>
<p>若不需要Xcode可直接跳过该步骤, 安装Homebrew时同样会自动安装<code>Command Line Tools</code></p>
</blockquote>
<ul>
<li>通过App Store 安装Xcode</li>
<li>安装Command Line Tools</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ xcode-select --install</div></pre></td></tr></table></figure>
<h3 id="安装Homebrew"><a href="#安装Homebrew" class="headerlink" title="安装Homebrew"></a>安装<a href="http://brew.sh/" target="_blank" rel="external">Homebrew</a></h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ ruby -e <span class="string">"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</span></div></pre></td></tr></table></figure>
<h3 id="安装Git"><a href="#安装Git" class="headerlink" title="安装Git"></a>安装Git</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">$$ brew install git</div><div class="line"></div><div class="line"># SSH-KeyGen, 设置SSH密钥</div><div class="line">$ ssh-keygen -t rsa -C <span class="string">"[email protected]"</span> </div><div class="line"></div><div class="line"># 在Github中添加新生成的公钥, 验证是否成功请执行以下命令</div><div class="line">$ ssh -T [email protected]</div></pre></td></tr></table></figure>
<ul>
<li>参考<a href="http://andrewliu.in/2014/09/09/2014-09-09-Install-SSH-Use-Github/">Install-SSH-Use-Github</a></li>
</ul>
<h3 id="安装nodejs"><a href="#安装nodejs" class="headerlink" title="安装nodejs"></a>安装nodejs</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">$ brew install nodejs</div><div class="line"></div><div class="line"># 安装nvm或者n作为nodejs版本控制工具</div><div class="line">$ (sudo) npm install -g n</div><div class="line"># 如果不行, 则使用nvm进行版本控制</div><div class="line">$ n <span class="number">4.2</span><span class="number">.4</span></div></pre></td></tr></table></figure>
<ul>
<li><a href="https://npm.taobao.org/" target="_blank" rel="external">设置淘宝npm镜像</a></li>
</ul>
<h3 id="安装-Ruby"><a href="#安装-Ruby" class="headerlink" title="安装 Ruby"></a>安装 Ruby</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">$ brew install ruby</div><div class="line"></div><div class="line">$ rbenv install -l <span class="meta"># list all available versions</span></div><div class="line">$ rbenv install <span class="number">2.2</span><span class="number">.1</span> <span class="meta"># install a Ruby version</span></div><div class="line">$ rbenv global <span class="number">2.2</span><span class="number">.1</span> <span class="meta"># set the global version</span></div><div class="line">$ rbenv versions <span class="meta"># list all installed Ruby versions</span></div></pre></td></tr></table></figure>
<ul>
<li><a href="https://gems.ruby-china.org/" target="_blank" rel="external">配置 gem 墙内源</a></li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ gem sources --add https:<span class="comment">//gems.ruby-china.org/ --remove https://rubygems.org/</span></div><div class="line">$ gem sources -l</div><div class="line">https:<span class="comment">//gems.ruby-china.org</span></div><div class="line"># 确保只有 gems.ruby-china.org</div></pre></td></tr></table></figure>
<h3 id="安装vim和MacVim"><a href="#安装vim和MacVim" class="headerlink" title="安装vim和MacVim"></a>安装vim和MacVim</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">Step 1. Install homebrew from here: http://brew.sh</div><div class="line">Step 1.1. Run export PATH=/usr/local/bin:$PATH</div><div class="line">Step 2. Run brew update</div><div class="line">Step 3. Run brew install vim && brew install macvim</div><div class="line">Step 4. Run brew link macvim</div></pre></td></tr></table></figure>
<ul>
<li><a href="https://github.com/humiaozuzu/dot-vimrc" target="_blank" rel="external">Vim配置</a></li>
<li><a href="https://github.com/VundleVim/Vundle.vim" target="_blank" rel="external">vim.bundle</a></li>
<li><a href="http://blog.csdn.net/eric_xjj/article/details/8932502" target="_blank" rel="external">Mac开发利器之程序员编辑器MacVim学习总结</a></li>
</ul>
<h3 id="安装zsh和Oh-My-Zsh"><a href="#安装zsh和Oh-My-Zsh" class="headerlink" title="安装zsh和Oh My Zsh"></a>安装zsh和<a href="https://github.com/robbyrussell/oh-my-zsh" target="_blank" rel="external">Oh My Zsh</a></h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ brew install zsh</div><div class="line"># 安装oh-my-zsh</div><div class="line">$ sh -c <span class="string">"$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"</span></div></pre></td></tr></table></figure>
<ul>
<li>更换oh my zsh主题在<code>~/.oh-my-zsh/themes/</code>路径下, 在<a href="http://zshthem.es/" target="_blank" rel="external">zshthem</a>网站进行主题预览</li>
<li>安装<a href="https://github.com/wting/autojump" target="_blank" rel="external">autojump</a>, 一键跳转到目的目录, 不再不停的cd</li>
<li>安装<a href="https://github.com/sindresorhus/trash" target="_blank" rel="external">trash</a>, 不再用rm命令.</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"># 安装autojump</div><div class="line">$ brew install autojump</div><div class="line"># 安装trash</div><div class="line">$ npm install --global trash</div></pre></td></tr></table></figure>
<p>持久化SSH连接, 安装<a href="https://mosh.mit.edu/#usage" target="_blank" rel="external">mosh</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ brew install mobile-shell</div></pre></td></tr></table></figure>
<h3 id="安装python"><a href="#安装python" class="headerlink" title="安装python"></a>安装python</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">$ brew install python</div><div class="line"></div><div class="line">Pip <span class="keyword">and</span> setuptools have been installed. To update them</div><div class="line"> pip install --upgrade pip setuptools</div><div class="line"></div><div class="line">You can install Python packages with</div><div class="line"> pip install <package></div><div class="line"></div><div class="line">They will install into the site-package directory</div><div class="line"> /usr/local/lib/python2<span class="number">.7</span>/site-packages</div><div class="line"></div><div class="line">See: http:<span class="comment">//docs.brew.sh/Homebrew-and-Python.html</span></div></pre></td></tr></table></figure>
<h3 id="安装安装-MongoDB-MySQL"><a href="#安装安装-MongoDB-MySQL" class="headerlink" title="安装安装 MongoDB, MySQL"></a>安装安装 MongoDB, MySQL</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ brew install mongodb mysql</div></pre></td></tr></table></figure>
<p>设置开机自启动「可选」:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ mkdir -p ~/Library/LaunchAgents</div><div class="line">$ ln -sfv /usr/local/opt/mongodb<span class="comment">/*.plist ~/Library/LaunchAgents</span></div><div class="line">$ ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents</div></pre></td></tr></table></figure>
<h3 id="zshrc文件配置"><a href="#zshrc文件配置" class="headerlink" title=".zshrc文件配置"></a>.zshrc文件配置</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">alias zshconfig="vim ~/.zshrc"</div><div class="line">alias rezsh="source ~/.zshrc"</div><div class="line">alias ohmyzsh="cd ~/.oh-my-zsh"</div><div class="line"></div><div class="line"># The default command paramters</div><div class="line">alias vi='vim'</div><div class="line">alias egrep='egrep --color=auto'</div><div class="line">alias fgrep='fgrep --color=auto'</div><div class="line">alias bc='bc -l'</div><div class="line">alias wget='wget -c'</div><div class="line">alias chown='chown --preserve-root'</div><div class="line">alias chgrp='chgrp --preserve-root'</div><div class="line">alias rm='rm -I --preserve-root'</div><div class="line">alias ln='ln -i'</div><div class="line"></div><div class="line"># Colorful grep output</div><div class="line">alias grep='grep --color=auto'</div><div class="line">export GREP_COLOR='1;33'</div><div class="line"></div><div class="line"># Colorful ls</div><div class="line">export LSCOLORS='Gxfxcxdxdxegedabagacad'</div><div class="line">ls='ls --color=auto'</div><div class="line"></div><div class="line"># autojump</div><div class="line">[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] && . ~/.autojump/etc/profile.d/autojump.sh</div></pre></td></tr></table></figure>
<h3 id="安装Sublime-Text"><a href="#安装Sublime-Text" class="headerlink" title="安装Sublime Text"></a>安装Sublime Text</h3><ol>
<li>安装<a href="http://www.sublimetext.com/" target="_blank" rel="external">Sublime Text 3</a></li>
<li>安装<a href="https://packagecontrol.io/" target="_blank" rel="external">Package Control</a></li>
<li>自定义配置<a href="https://gist.github.com/Andrew-liu/86223a7f34a17080b0c33e36a09e5da3" target="_blank" rel="external">Settings</a></li>
</ol>
<p>Sublime Text 3 安装Package Control的程序<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">import urllib.request,os;pf = 'Package Control.sublime-package';ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) );open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())</div></pre></td></tr></table></figure></p>
<h2 id="常用收费软件"><a href="#常用收费软件" class="headerlink" title="常用收费软件"></a>常用收费软件</h2><ul>
<li>Alfred 2(效率神器)</li>
<li>Dash 3(程序员专用-文档查询)</li>
<li>CleanMyMac 3(电脑清理软件)</li>
<li>PopClip(选中即复制)</li>
<li>Near Lock(靠近解锁软件)</li>
<li>Bartender 2(状态栏图标管理器)</li>
<li>Manico(更方便的软件切换软件)</li>
</ul>
<h2 id="常用免费软件"><a href="#常用免费软件" class="headerlink" title="常用免费软件"></a>常用免费软件</h2><ul>
<li>Caffeine(不息屏神器)</li>
<li>XtraFinder(增强Finder)</li>
<li>Manico(快速切换神器, 相当与window上Alt+Tab)</li>
<li>Clipy, 重装时发现ClipMenu不维护了, 找了个代替品(剪切板管理)</li>
<li>Bear,MacDown,Mou(Markdown编辑器)</li>
<li>Movist(播放器)</li>
<li>Snip(截图软件)</li>
<li>Chrome(神之浏览器)</li>
<li>iTerm2(Mac上遗失的Terminal)</li>
<li>搜狗拼音(比原生的好用)</li>
<li>Window Tidy(窗口大小切换)</li>
<li>SmoothMouse</li>
<li>Reeder(RSS订阅)</li>
<li><p><a href="http://pilotmoon.com/scrollreverser/" target="_blank" rel="external">SCROLL REVERSER</a> (修改鼠标移动方向, 但不改变触摸板)</p>
</li>
<li><p>百度网盘</p>
</li>
<li>微信</li>
<li>QQ</li>
<li>阿里旺旺</li>
<li>JetBrain全家桶</li>
<li>TinyCal</li>
<li>Shadowsocks</li>
<li>Spark</li>
<li>网易云,QQ音乐</li>
<li>TickTick</li>
<li>富途牛牛</li>
<li>EverNote</li>
<li>TeamViewer</li>
<li>MacTex</li>
</ul>
<h2 id="命令行管理Wifi"><a href="#命令行管理Wifi" class="headerlink" title="命令行管理Wifi"></a>命令行管理Wifi</h2><p><a href="http://blog.mattcrampton.com/post/64144666914/managing-wifi-connections-using-the-mac-osx" target="_blank" rel="external">Managing WIFI connections using the Mac OSX terminal command line</a></p>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul>
<li><a href="http://www.jianshu.com/p/77a4349bf67b" target="_blank" rel="external">Mac开发配置</a></li>
<li><a href="http://blog.jobbole.com/85702/" target="_blank" rel="external">shell入门</a></li>
<li><a href="http://stackoverflow.com/questions/18144660/what-is-path-of-jdk-on-mac" target="_blank" rel="external">what is path of jdk on mac</a></li>
<li><a href="http://alfredtips.com/s/popular/1/" target="_blank" rel="external">Alfred web search custom</a></li>
<li><a href="https://kapeli.com/dash_guide" target="_blank" rel="external">Dash官方文档</a></li>
</ul>
]]></content>
<summary type="html">
<div class="tip"><br> 本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.<br></div>
<blockquote>
<p>很久没有更新博客了, 前段时间迷上了王者农药, 戒了农药后又重新入了暴雪爸爸<code>暗黑3</code>的大坑, 呵呵.<br>除此之外, 公司离职回来一直准备毕业论文、毕业答辩、毕业相关材料, 真是焦头烂额.<br>不过想想十九年求学生涯就要结束了, 即将AFK了, 简直幸福.</p>
</blockquote>
<p>为什么要重装? Mac系统的乱七八糟的东西已经占据了90%的磁盘空间, 无法减少文件保持一定空闲磁盘空间, 这种情况已经严重影响了我的日常工作.</p>
<p>重装方案严格按照 Apple 官方文档 <a href="https://support.apple.com/zh-cn/HT204904" target="_blank" rel="external">如何重新安装 macOS</a> 执行.</p>
<h2 id="系统偏好设置"><a href="#系统偏好设置" class="headerlink" title="系统偏好设置"></a>系统偏好设置</h2><ul>
<li>允许安装任何来源的APP: <code>安全性与隐私-&gt;通用</code>. 若无该选项,请命令行执行<code>sudo spctl --master-disable</code></li>
<li>设置快捷键: <code>键盘-&gt;快捷键</code> 更改输入法切换快捷键</li>
<li>设置触摸板: 选取全部触摸板设置</li>
<li>设置触发角: <code>桌面与屏幕保护程序-&gt;触发角</code></li>
<li><p>设置密码验证: <code>系统偏好设置-&gt;安全性与隐私-&gt;选择 进入休眠或屏保后立即要求输入密码</code></p>
</li>
<li><p>编辑 /etc/paths(<code>sudo vim /etc/paths</code>)</p>
</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">/usr/local/bin</div><div class="line">/usr/local/sbin</div><div class="line">/usr/bin</div><div class="line">/usr/sbin</div><div class="line">/bin</div><div class="line">/sbin</div></pre></td></tr></table></figure>
</summary>
<category term="Mac" scheme="http://andrewliu.in/tags/Mac/"/>
</entry>
<entry>
<title>2016成就墙完成情况总结</title>
<link href="http://andrewliu.in/2017/01/17/2016%E6%88%90%E5%B0%B1%E5%A2%99%E5%AE%8C%E6%88%90%E6%83%85%E5%86%B5%E6%80%BB%E7%BB%93/"/>
<id>http://andrewliu.in/2017/01/17/2016成就墙完成情况总结/</id>
<published>2017-01-17T14:03:46.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<p>一转眼,2016年又结束了,我的本命年就这样不知不觉溜走了,回头一看,很多年初许下的目标因为各种拖延症没有完成,心情还是有些小抑郁的。2016年算是奔波的一年吧,往返南京、北京、深圳三座城市也是挺心酸了,还不是为了生活的苟且。</p>
<blockquote>
<p>本文想到哪里写到哪里,毕竟我没有过目不忘的记忆</p>
</blockquote>
<p>2016年解锁成就:</p>
<ul>
<li>Zhihu.inc全体验成就达成,拿到Offer后跑路</li>
<li>Baidu.inc全体验成就达成,拿到Offer后又干了一个月因其他原因不得不跑路</li>
<li>Tencent.inc实习成就达成,并期待解锁终生成就奖(然而已经错过了一波企鹅18岁的全员股票)</li>
<li>NJU最浪/最不务正业研二学生成就达成,一整年没回几次学校,没睡几次宿舍的床,感觉宿舍的床已经长毛了,不能再睡了。</li>
<li>BAT实习成就解锁2/3,预计剩余1/3是没有机会解锁了,毕竟企业文化是很重要的,选择一个适合的企业文化才能让自己开心的浪</li>
<li>iPhone 7成就达成,喊了这么多年想拥有一个iPhone,终于这一次iPhone发布会剁手,虽然没有太多的外形变化,但是总是比我的辣鸡魅族不知道高到哪里去了,辣鸡魅族,毁我青春,败我钱财</li>
<li>Apple三件套成就达成,还记得第一件iPad是去南大读书的时候,妈妈送我的礼物,还记得第二件Macbook是送给自己的开发礼物,用Apple的产品总是不会错的,虽然我一直鼓吹自己是个谷歌脑残粉,嗯,谷歌大法好!</li>
</ul>
<a id="more"></a>
<ul>
<li>PS4成就达成,并完全解锁火影4,待解锁巫师3,神海四件套,三人一狗,还是索尼大法好</li>
<li>自如最佳送钱租客成就达成,两次自如强制节约,累计送出几个亿的违约金,住的房子也是越来越贵了,从不到2000租金的次卧到住进2000+租金的自如主卧,感觉好像就空间大了点,阳光多了点的样子。</li>
<li>看书最少的一年成就解锁,累计看完三本书,剩下的时间都被狗吃了吗</li>
<li>Github凹凸commit记录成就解锁,当你看到最近一个月在频繁commit的时候,说明我实习结束了,当你看到我最近一个月几乎没有commit的时候,说明我又开始新的实习了</li>
<li>校招成就解锁,经历了一次校招,还没什么感觉就结束了,我想去的offer收到了,就没心情继续做一名收offer狂魔了</li>
<li><p>负心员工成就解锁,有了两度收到offer跑路的经历了,也是没谁了,第一次跑路是因为开发遇到大坑,不跑路也要被迫跑路,还不如主动点,第二次跑路是因为我收到理想中的offer并且签了三方,都把公司的脸打了,再不跑路难道当商业间谍吗?</p>
</li>
<li><p>北京全景点解锁,南锣鼓巷,长城,圆明园,后海,故宫…全解锁,不想再留在北京作为一个吸霾卫士了</p>
</li>
<li>深圳二次游成就解锁,时隔2年,又回到了个这个梦开始的地方,上一次我以一个参观者的身份到腾讯科兴科学园,这一次我以一个实习生的身份再一次走进科兴科学园,期待我下次以一名正式员工的身份归来。</li>
<li><p>香港游成就解锁,第一次看到了资本主义社会的发展形态,听到只能在听歌的时候才能听到的粤语,发现中国香港人好像没大陆仔没什么区别,2333</p>
</li>
<li><p>人生第一次爱情三周年成就解锁,不过貌似这两天又遇到感觉危机了,工作忙(借口?),沟通不畅,为什么别人家的女朋友总是善解人意,小鸟依然呢?这是一个值得思考的问题</p>
</li>
<li><p>博客更新和维护成就解锁,累计写出不知道多少篇博客,至少没有中断过太久的更新。</p>
</li>
</ul>
<p>2017年待解锁成就:</p>
<ul>
<li>浪漫情人节成就,准备发一波狗粮</li>
<li>Jaybird X3成就,写这篇文章的当天,该成就已成功解锁,非常赞的耳机,值得拥有</li>
<li>粗粮加的手环和移动电源割草成就</li>
<li>Tencent.inc实习全体验成就</li>
<li>南京大学成功毕业及毕业典礼成就</li>
<li>毕业旅行成就</li>
<li>正式入职成就</li>
<li>读完十本书成就,包括但不限于开发相关书籍</li>
<li>PS4 三人一狗,神海四合集,巫师3成就</li>
<li>王者农药黄金段位成就,如果玩农药没有梦想和咸鱼有什么两样,毕竟非洲血统,排位必遇挂机党,大神带我上排位</li>
<li>订婚成就</li>
<li>博客更新与维护成就</li>
<li>参与开源项目开发成就</li>
<li>更多成就待补充…</li>
</ul>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<p>一转眼,2016年又结束了,我的本命年就这样不知不觉溜走了,回头一看,很多年初许下的目标因为各种拖延症没有完成,心情还是有些小抑郁的。2016年算是奔波的一年吧,往返南京、北京、深圳三座城市也是挺心酸了,还不是为了生活的苟且。</p>
<blockquote>
<p>本文想到哪里写到哪里,毕竟我没有过目不忘的记忆</p>
</blockquote>
<p>2016年解锁成就:</p>
<ul>
<li>Zhihu.inc全体验成就达成,拿到Offer后跑路</li>
<li>Baidu.inc全体验成就达成,拿到Offer后又干了一个月因其他原因不得不跑路</li>
<li>Tencent.inc实习成就达成,并期待解锁终生成就奖(然而已经错过了一波企鹅18岁的全员股票)</li>
<li>NJU最浪/最不务正业研二学生成就达成,一整年没回几次学校,没睡几次宿舍的床,感觉宿舍的床已经长毛了,不能再睡了。</li>
<li>BAT实习成就解锁2/3,预计剩余1/3是没有机会解锁了,毕竟企业文化是很重要的,选择一个适合的企业文化才能让自己开心的浪</li>
<li>iPhone 7成就达成,喊了这么多年想拥有一个iPhone,终于这一次iPhone发布会剁手,虽然没有太多的外形变化,但是总是比我的辣鸡魅族不知道高到哪里去了,辣鸡魅族,毁我青春,败我钱财</li>
<li>Apple三件套成就达成,还记得第一件iPad是去南大读书的时候,妈妈送我的礼物,还记得第二件Macbook是送给自己的开发礼物,用Apple的产品总是不会错的,虽然我一直鼓吹自己是个谷歌脑残粉,嗯,谷歌大法好!</li>
</ul>
</summary>
<category term="心路札记" scheme="http://andrewliu.in/tags/%E5%BF%83%E8%B7%AF%E6%9C%AD%E8%AE%B0/"/>
</entry>
<entry>
<title>开发机安装配置golang和使用CGI</title>
<link href="http://andrewliu.in/2016/12/13/%E5%BC%80%E5%8F%91%E6%9C%BA%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AEgolang%E5%92%8C%E4%BD%BF%E7%94%A8CGI/"/>
<id>http://andrewliu.in/2016/12/13/开发机安装配置golang和使用CGI/</id>
<published>2016-12-13T06:46:08.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<h2 id="安装golang"><a href="#安装golang" class="headerlink" title="安装golang"></a>安装golang</h2><ul>
<li><a href="https://golang.org/dl/" target="_blank" rel="external">Golang download</a>下载合适版本的<code>golang</code>二进制发布包.</li>
</ul>
<a id="more"></a>
<ol>
<li>Xshell5 登录跳板机->开发机</li>
<li>执行<code>rz -bey</code>选中本地电脑中下载的golang压缩包</li>
<li>执行以下命令解压并安装二进制文件到<code>/usr/local</code>中</li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ tar -C /usr/local -xzf <span class="keyword">go</span>$VERSION.$OS-$ARCH.tar.gz</div></pre></td></tr></table></figure>
<ol>
<li>配置golang对应的环境变量</li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"># 使用vim修改对应的配置文件</div><div class="line">$ vim /etc/profile</div><div class="line"># 配置环境变量</div><div class="line">export PATH=$PATH:/usr/local/<span class="keyword">go</span>/bin</div></pre></td></tr></table></figure>
<h2 id="什么是cgi"><a href="#什么是cgi" class="headerlink" title="什么是cgi?"></a>什么是cgi?</h2><ul>
<li>Web服务器负责管理连接, 数据传输,网络交互</li>
<li>CGI脚本负责管理具体的业务逻辑, <strong>CGI是一种网页和程序通讯的协议</strong></li>
</ul>
<blockquote>
<p><code>CGI</code>程序负责生成动态内容, 然后返回给服务器, 由服务器转交给客户端。CGI是一个独立的程序可以独立运行</p>
</blockquote>
<h2 id="使用golang和cgi包"><a href="#使用golang和cgi包" class="headerlink" title="使用golang和cgi包"></a>使用golang和cgi包</h2><blockquote>
<p>golang开发时, 需要对当前工作目录配置 <code>GOPATH</code>.</p>
</blockquote>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"># 到工作目录下执行以下目录, 将当前目录设置为GOPATH</div><div class="line">$ export <span class="string">"GOPATH=$PWD"</span></div></pre></td></tr></table></figure>
<p>简单的机遇HTTP Server的cgi处理程序</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> main</div><div class="line"></div><div class="line"><span class="keyword">import</span> (</div><div class="line"> <span class="string">"net/http"</span></div><div class="line"> <span class="string">"net/http/cgi"</span></div><div class="line"> <span class="string">"log"</span></div><div class="line"> <span class="string">"fmt"</span></div><div class="line">)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">CgiTestHandler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> {</div><div class="line"> fmt.Println(<span class="string">"get request..."</span>, r.URL.Path)</div><div class="line"> handler := <span class="built_in">new</span>(cgi.Handler)</div><div class="line"> handler.Path = <span class="string">"/usr/local/go/bin/go"</span></div><div class="line"> <span class="comment">// 运行脚本位置</span></div><div class="line"> script := <span class="string">"/root/AsyncLiu/Golang/CgiTest/script/"</span> + r.URL.Path</div><div class="line"> log.Println(handler.Path)</div><div class="line"></div><div class="line"> handler.Dir = <span class="string">"/root/AsyncLiu/Golang/CgiTest/script/"</span></div><div class="line"> args := []<span class="keyword">string</span>{<span class="string">"run"</span>, script}</div><div class="line"> handler.Args = <span class="built_in">append</span>(handler.Args, args...)</div><div class="line"> handler.Env = <span class="built_in">append</span>(handler.Env, <span class="string">"GOPATH=/root/AsyncLiu/Golang/CgiTest"</span>)</div><div class="line"> log.Println(handler.Args)</div><div class="line"></div><div class="line"> handler.ServeHTTP(w, r)</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</div><div class="line"> http.HandleFunc(<span class="string">"/"</span>, CgiTestHandler)</div><div class="line"> fmt.Println(<span class="string">"start web server...."</span>)</div><div class="line"> log.Fatal(http.ListenAndServe(<span class="string">":8888"</span>, <span class="literal">nil</span>))</div><div class="line">}</div></pre></td></tr></table></figure>
<p>对应的被执行的脚本</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> main</div><div class="line"></div><div class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">init</span><span class="params">()</span></span> {</div><div class="line"> fmt.Println(<span class="string">"Content-Type: test/plain;charset=utf-8\n\n"</span>)</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</div><div class="line"> fmt.Println(<span class="string">"This is executing go script"</span>)</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<h2 id="安装golang"><a href="#安装golang" class="headerlink" title="安装golang"></a>安装golang</h2><ul>
<li><a href="https://golang.org/dl/" target="_blank" rel="external">Golang download</a>下载合适版本的<code>golang</code>二进制发布包.</li>
</ul>
</summary>
<category term="Golang" scheme="http://andrewliu.in/tags/Golang/"/>
</entry>
<entry>
<title>传统软件公司/创业公司/大公司的工作机会如何选择?</title>
<link href="http://andrewliu.in/2016/11/21/%E4%BC%A0%E7%BB%9F%E8%BD%AF%E4%BB%B6%E5%85%AC%E5%8F%B8-%E5%88%9B%E4%B8%9A%E5%85%AC%E5%8F%B8-%E5%A4%A7%E5%85%AC%E5%8F%B8%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%9C%BA%E4%BC%9A%E5%A6%82%E4%BD%95%E9%80%89%E6%8B%A9%EF%BC%9F/"/>
<id>http://andrewliu.in/2016/11/21/传统软件公司-创业公司-大公司的工作机会如何选择?/</id>
<published>2016-11-21T03:30:55.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>背景介绍: 第一家工作的公司是一家跨国外企安全公司, 骄傲的称自己不是互联网公司而是传统软件公司, 第二家公司是当下最热的知识分享社区, 创业公司. 第三家公司是挤走谷歌, 曾一度称霸中国的搜索引擎公司, 体量很大的著名三大互联网公司之一.</p>
</blockquote>
<p><strong>每一家公司我都接触的不是很久, 没能用一生的时间来体验一个公司, 只能说一下我在短时间看到的优势和缺陷</strong></p>
<a id="more"></a>
<h2 id="传统软件公司"><a href="#传统软件公司" class="headerlink" title="传统软件公司"></a>传统软件公司</h2><p><strong>优势:</strong></p>
<ol>
<li>最大优势, 几乎从不加班, 其中包括很多外企传统软件公司, 养老的最好去处, 五点老大带你一起下班回家</li>
<li>次要优势, 工作压力小, 当然核心项目除外 (因为要抢占市场之类的), 我当时所在的部门, 工作目标不要太轻松, 两三天完成本周工作目标, 然后可以自由看书(当然也可能是老板看我太菜, 想闲置我)</li>
</ol>
<p><strong>缺陷:</strong></p>
<ul>
<li>技术栈不够丰富, 很难学到高深的姿势(大神除外), 很难接触到或者用到当下最流程的框架或者技术</li>
<li>福利少, 思想僵化, 体制化严重</li>
</ul>
<blockquote>
<p>建议: 想在互联网行业发展, 不要去传统软件行业和外企, 长久呆在这些地方, 很难适应国内互联网公司的工作压力和工作节奏</p>
</blockquote>
<h2 id="创业公司"><a href="#创业公司" class="headerlink" title="创业公司"></a>创业公司</h2><p>如果想去创业公司, 我觉得首先应该调查一下以下问题:</p>
<ol>
<li>老板是否有互联网背景? 是否有创业成功经历? 是否曾连续创业</li>
<li>公司是否有足够的创业资金, 公司处于第几轮融资, 是否有广阔的前景(这个比较难判断), 公司当前的估值如果</li>
<li>公司的创业团队如何? 带队领导的业界风评怎么样</li>
</ol>
<p>针对第一个问题, 问题比较大的是, 有些创业CEO本身毫无互联网行业背景, 总是想着<code>只差一个程序员</code>, 而又喜欢对技术实现指手画脚, 我个人不太喜欢这种创业公司. 针对第二个问题, 无论如何, 工作的本质都是为了挣钱, 最终实现财富自由, 所有公司有充足的资金比较重要, 我听过身边很多朋友说创业公司老板跑路或者发不起/拖欠工资. 针对第三个问题, 进入互联网行业的程序员很多人都有一个技术专家的梦想, 所以跟着一个技术大佬指引人生方向是很重要的(菊苣们不需要).</p>
<p><strong>优势</strong></p>
<ul>
<li>工作氛围年轻, 充满活力, 一起工作的人年龄都差不多, 简直不要太轻松愉悦</li>
<li>福利比较好, 创业公司为了吸引人才是舍得下本钱的, 标配Mac, Dell U系列显示器, 人体工程椅, 大量零食, 定期<code>Team building</code>等等</li>
<li>技术栈自由, 没有历史包袱, 可以任意使用新颖的框架和技术(但是会给以后埋坑)</li>
</ul>
<p><strong>缺陷</strong></p>
<ul>
<li>很多创业公司缺少同一的标准, 代码混乱缺乏review, 技术栈混乱造轮子严重(这需要有一个重视这方面的leader来引导)</li>
<li>技术积累比较弱, 大量使用外部开源项目, 很多时候都是业务堆积</li>
<li>没有升职空间和与之对应的职业路线, 大多创业公司是简单的三层管理方式, 普通员工, leader(一般员工到这里就到顶了), CXO</li>
<li>除非技术栈和技能点过硬, 否则跳槽比较困难, 创业公司因为没有固定的晋升体系, 并且职位和工作比较难被其他公司认可</li>
</ul>
<h2 id="大公司"><a href="#大公司" class="headerlink" title="大公司"></a>大公司</h2><p>互联网大公司有很多创业公司和传统软件公司所没有的优势, 而且业界容易被业界认可</p>
<p><strong>优势:</strong></p>
<ul>
<li>会有机会和一群名校毕业, 智商很高, 头脑清晰的人一起工作, 有时间压力就是动力(比如猪厂, 可能随便一个写脚本的都是清华毕业的)</li>
<li>技术基本雄厚, 外界知名的开源项目可能很快就能在内部造出合适的轮子, 并且有专人维护跟进, 代码提交, 风格和审核有一定的标准, 不容易导致代码库紊乱</li>
<li>跳槽相对容易, 俗称大公司镀金, 很多大公司晋升体系是被认可的, 如百度/腾讯的T序列, 阿里的P序列.</li>
<li>大量的内部或者外部知识分享或培训, 完整的入职培训</li>
</ul>
<p><strong>缺陷:</strong></p>
<ul>
<li>历史包袱比较严重, 可能一次简单的版本升级会引出大量的bug和不兼容, 写代码总是要小心翼翼.</li>
<li>流程/规范/会议较多, 大量的时间被浪费在其中, 然而我们总想着让我静静</li>
<li>不同团队间协作比较困难</li>
<li>内部轮子过多, 每个小部门都喜欢自己造论子, 正如技术的特点: <code>总是短期被重视,长期被忽视</code>.</li>
</ul>
<blockquote>
<p>总的来说, 我更喜欢大公司, 完整的工作体验和晋升流程 浓厚的技术积累适合刚毕业的同学们快速成长又能有一份不菲的薪资. </p>
</blockquote>
<p>工作的选择并不是很容易做出, 要考虑的地方很多, 比如:</p>
<ol>
<li>个人喜欢, 对公司的爱好, 对岗位的爱好</li>
<li>工作是否能够让你获得成就感</li>
<li>喜欢离家近一些还是离家远一些, 喜欢城市环境好一些还是城市节奏快一些</li>
</ol>
<p>最后, 希望每个人都能拿到自己梦想的offer, 进行自己心仪的公司</p>
<h2 id="TED心得"><a href="#TED心得" class="headerlink" title="TED心得"></a>TED心得</h2><p><strong>最近看了个TED, 感触颇深, 来干了这碗毒鸡汤</strong></p>
<ul>
<li>大多数人的梦想是实现不了的, 然而也并不重要, 但是人总要有梦想吗, 万一实现了呢</li>
<li>有些事情是可以自然而然的发生的, 如果你选择了这样的事情, 多停留一段时间一定会有收获的</li>
<li>无论是什么年龄段的人, 攒人品是没必要的, 当前的痛苦并不一定带来未来的快乐, 未来的快乐也代替不了现在的快乐, 所以要活在当下, 珍惜身边人</li>
<li>心情愉悦很重要</li>
</ul>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><p><a href="http://v.qq.com/x/cover/2mk64hchaksns1z.html?vid=e0143xi01p9" target="_blank" rel="external">TEDxDUFE:于宙 我们这一代的困惑</a></p>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>背景介绍: 第一家工作的公司是一家跨国外企安全公司, 骄傲的称自己不是互联网公司而是传统软件公司, 第二家公司是当下最热的知识分享社区, 创业公司. 第三家公司是挤走谷歌, 曾一度称霸中国的搜索引擎公司, 体量很大的著名三大互联网公司之一.</p>
</blockquote>
<p><strong>每一家公司我都接触的不是很久, 没能用一生的时间来体验一个公司, 只能说一下我在短时间看到的优势和缺陷</strong></p>
</summary>
<category term="Blog" scheme="http://andrewliu.in/tags/Blog/"/>
</entry>
<entry>
<title>Linux内核设计与实现读书笔记</title>
<link href="http://andrewliu.in/2016/11/15/Linux%E5%86%85%E6%A0%B8%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
<id>http://andrewliu.in/2016/11/15/Linux内核设计与实现读书笔记/</id>
<published>2016-11-15T02:13:27.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<p><strong>Unix强大的根本原因:</strong></p>
<ol>
<li>Unix简洁, 提供几百个系统调用, 设计目的明确</li>
<li>Unix中<code>所有东西都被当做文件对待</code></li>
<li>Unix内核和相关系统工具是用C语言开发的, 移植能力强大</li>
<li>Unix进程创建迅速, 有独特的fork机制</li>
<li>Unix提供简单稳定的进程间通信元语</li>
</ol>
<blockquote>
<p>Linux是类Unix系统, 借鉴了Unix设计并实现了Unix的API.<br>应用程序通常调用库函数(如C库函数)再由库函数通过系统调用界面, 让内核代其完成各种任务.</p>
</blockquote>
<a id="more"></a>
<ul>
<li>Linux支持动态加载内核模块</li>
<li>Linux支持对称多处理(SMP)机制</li>
<li>Linux为<code>抢占式内核</code></li>
<li>Linux并不区分线程和其他的一般进程</li>
<li>Linux提供具有设备类的面向对象的设备模型, 热插拔事件, 以及用户控件的设备文件系统</li>
</ul>
<h2 id="中断和中断处理"><a href="#中断和中断处理" class="headerlink" title="中断和中断处理"></a>中断和中断处理</h2><blockquote>
<p>中断是一种解决处理器和速度差异的方案, 只有在硬件需要的时候再向内核发出信号. 中断本质上是一种特殊的电信号.</p>
</blockquote>
<ul>
<li>内核响应特定中断, 然后<code>内核</code>调用特定的<code>中断处理程序</code>, 终端处理程序是设备驱动程序的一部分</li>
<li>Linux中的终端处理程序是不可重入的, 同一个中断处理程序不会被同时调用</li>
<li>中断上下文不可以睡眠(我理解当前被中断的程序再中断处理结束后需要继续执行)</li>
<li>中断处理程序不在进程上下文中进行, 他们不能阻塞</li>
<li>中断处理分为两部分, 上半部为中断处理程序, 要求尽可能快的执行, 下半部(<code>用于减少中断处理程序的工作量</code>)执行与中断处理密切相关但中断处理程序本身不执行的工作</li>
<li>下半部的实现方法 <code>软中断、tasklet、工作队列</code>,</li>
</ul>
<blockquote>
<p><strong>中断机制的实现:</strong> 设置产生中断, 通过电信号给处理器的特定管脚发送一个信号, 处理器听着当前处理工作, <code>关闭中断系统</code>, 然后调到内存中预定义的位置(中断处理程序的入口点)开始执行.计算终端号, <code>do_IRQ()</code>对接收的中断进行应答, 禁止这条线上的中断传递.</p>
</blockquote>
<h2 id="内核同步"><a href="#内核同步" class="headerlink" title="内核同步"></a>内核同步</h2><blockquote>
<p>对于共享资源, 如果同时被多个线程访问和操作, 就可能发生各线程之间相互覆盖共享数据, 造成访问数据不一致.</p>
</blockquote>
<p>同步实现通过主要<code>锁机制</code>对共享资源进行加锁, 只有持有锁的线程才能操作共享资源, 其他线程睡眠(或者轮询). 资源操作完成后, 持有锁的线程释放锁, 由等待线程抢锁.</p>
<p><strong>内核同步方法:</strong></p>
<ol>
<li><code>原子操作</code></li>
<li><code>自旋锁</code>, 特性是当线程无法获取锁, 会一直忙循环(<code>忙等</code>)等待锁重新可以, 适用于短期轻量级加锁</li>
<li><code>读/写自旋锁</code>(共享/排它锁), 一个或多个任务可以并发的持有读者锁, 写者锁只能被一个写任务持有.</li>
<li><code>信号量</code>(睡眠锁), 如果一个任务试图获得一个被占用的信用量时, 信号量会将其推进一个等待队列, 然后让其睡眠. 当信号量可用后, 等待队列中的任务会被唤醒. 适用于锁被长期占用的时候.</li>
<li>mutex(计数为1的信号量), 这个是编程中最常见的.</li>
<li><code>顺序锁</code></li>
<li><code>屏障</code>(barriers), 用于确保指令序列和读写的执行顺序</li>
</ol>
<p>内核中造成并发的原因:</p>
<ul>
<li>中断, 几乎可以再任何时刻异步发生, 可能随时打断当前正在执行的代码</li>
<li>软中断和tasklet, 内核能在任何时刻唤醒或调度软中断或tasklet, 打断当前正在执行的代码</li>
<li>内核抢占</li>
<li>睡眠及与用户空间的同步</li>
<li>对称多处理, 多个处理器同时执行代码</li>
</ul>
<h2 id="内存管理"><a href="#内存管理" class="headerlink" title="内存管理"></a>内存管理</h2><p>内核把物理页作为内存管理的基本单位, <code>内存管理单元(MMU, 管理内存并将虚拟地址转换为物理地址)</code>通常以页为单位来管理系统中的页表.</p>
<p>内核把也划分为不同的区(<code>zone</code>), 使用区对具有相似特性的页进行分组</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// <linux/gfp.h> 该函数分配2的order次方个连续`物理页`, 返回指针指向第一个页的page结构体</span></div><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">inline</span> struct page *</span></div><div class="line"><span class="title">alloc_pages</span><span class="params">(<span class="keyword">gfp_t</span> gfp_mask, <span class="keyword">unsigned</span> <span class="keyword">int</span> order)</span></div><div class="line"></div><div class="line"><span class="comment">// 释放物理页</span></div><div class="line"><span class="keyword">extern</span> <span class="keyword">void</span> <span class="title">free_pages</span><span class="params">(<span class="keyword">unsigned</span> <span class="keyword">long</span> addr, <span class="keyword">unsigned</span> <span class="keyword">int</span> order)</span>;</div><div class="line"></div><div class="line"><span class="comment">//<linux/slab.h>以字节为单位分配一块内核内存(物理上连续)</span></div><div class="line"><span class="keyword">static</span> __<span class="function">always_inline <span class="keyword">void</span> *<span class="title">kmalloc</span><span class="params">(<span class="keyword">size_t</span> size, <span class="keyword">gfp_t</span> flags)</span></span></div><div class="line"><span class="comment">//释放kmalloc分配的内存块</span></div><div class="line"><span class="keyword">void</span> <span class="title">kfree</span><span class="params">(<span class="keyword">const</span> <span class="keyword">void</span> *)</span>;</div></pre></td></tr></table></figure>
<h2 id="虚拟文件系统"><a href="#虚拟文件系统" class="headerlink" title="虚拟文件系统"></a>虚拟文件系统</h2><p>虚拟文件系统为用户控件程序提供了文件和文件系统相关接口.</p>
<p>文件的元数据, 被存储在一个单独的数据结构中, 被称为<code>inode</code>(索引节点)</p>
<p>虚拟文件系统(VFS)有四个主要的对象模型:</p>
<ul>
<li>超级块对象, 代表一个具体的已安装文件系统, 存储特定文件系统的信息</li>
<li>索引节点对象, 代表一个具体文件, 包含内核在操作文件或目录时需要的全部信息, 一个索引节点代表文件系统中的一个文件, </li>
<li>目录项对象, 代表一个目录项, 是路径的一个组成部分, <code>VFS把目录当做文件处理</code>, 目录项对象没有对应的磁盘数据结构</li>
<li>文件对象, 代表进程打开的文件, <code>进程直接处理的是文件</code></li>
</ul>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// <linux/fs.h> 文件对象的数据结构</span></div><div class="line"><span class="class"><span class="keyword">struct</span> <span class="title">file</span> {</span></div><div class="line"> <span class="keyword">union</span> {</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">llist_node</span> <span class="title">fu_llist</span>;</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span> <span class="title">fu_rcuhead</span>;</span></div><div class="line"> } f_u;</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">path</span> <span class="title">f_path</span>;</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">inode</span> *<span class="title">f_inode</span>;</span> <span class="comment">/* cached value */</span></div><div class="line"> <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">file_operations</span> *<span class="title">f_op</span>;</span></div><div class="line"></div><div class="line"> <span class="comment">/*</span></div><div class="line"> * Protects f_ep_links, f_flags.</div><div class="line"> * Must not be taken from IRQ context.</div><div class="line"> */</div><div class="line"> <span class="keyword">spinlock_t</span> f_lock;</div><div class="line"> <span class="keyword">atomic_long_t</span> f_count;</div><div class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> f_flags;</div><div class="line"> <span class="keyword">fmode_t</span> f_mode;</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">mutex</span> <span class="title">f_pos_lock</span>;</span></div><div class="line"> <span class="keyword">loff_t</span> f_pos;</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">fown_struct</span> <span class="title">f_owner</span>;</span></div><div class="line"> <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">cred</span> *<span class="title">f_cred</span>;</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">file_ra_state</span> <span class="title">f_ra</span>;</span></div><div class="line"></div><div class="line"> u64 f_version;</div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SECURITY</span></div><div class="line"> <span class="keyword">void</span> *f_security;</div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div><div class="line"> <span class="comment">/* needed for tty driver, and maybe others */</span></div><div class="line"> <span class="keyword">void</span> *private_data;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_EPOLL</span></div><div class="line"> <span class="comment">/* Used by fs/eventpoll.c to link all the hooks to this file */</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">f_ep_links</span>;</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">f_tfile_llink</span>;</span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* #ifdef CONFIG_EPOLL */</span></span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">address_space</span> *<span class="title">f_mapping</span>;</span></div><div class="line">} __attribute__((aligned(<span class="number">4</span>))); <span class="comment">/* lest something weird decides that 2 is OK */</span></div></pre></td></tr></table></figure>
<h2 id="块I-O层"><a href="#块I-O层" class="headerlink" title="块I/O层"></a>块I/O层</h2><blockquote>
<p>系统中能够<code>随机访问</code>固定大小数据片(chunks)的硬件设备称作块设备, 如硬盘. 按照字符流的方式被<code>有序访问</code>的硬件设备称为字符设备, 如键盘</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># <linux/bio.h>I/O设备基本容器由bio结构体表示</div></pre></td></tr></table></figure>
<ul>
<li><code>I/O调度程序</code>用于管理块设备的请求队列, 决定队列中的请求排列顺序以及什么时刻派发请求到挂设备. 这样有利于减少磁盘的寻址时间, 从而提高全局的吞吐量</li>
<li>linux实际使用的I/O调度程序有<code>linux电梯, 最终期限I/O调度, 预测I/O调度程序, 空操作的I/O调度程序</code></li>
</ul>
<h2 id="进程地址空间"><a href="#进程地址空间" class="headerlink" title="进程地址空间"></a>进程地址空间</h2><p>内核需要管理用户空间中进程的内存, 这个内存称为<code>进程地址空间</code>, 系统中所有进程之间以虚拟方式共享内存.</p>
<p>进程地址空间由进程可寻址的虚拟内存组成, 每个进程有32位或64位地址空间.</p>
<p>虚拟地址空间, 可被访问的合法地址空间称为<code>内存区域</code>:</p>
<ul>
<li>可执行文件代码的内存映射, 称为代码段</li>
<li>可执行文件的已初始化全局变量的内存映射, 称为数据段</li>
<li>包含未初始化全局变量,bss(block started by symbol)段的零页的内存映射</li>
<li>用于进程用户空间栈的零页内存映射</li>
<li>每一个如C库或动态链接程序等共享库的代码段、数据段和bss会被载入进程的地址空间</li>
<li>任何内存映射文件</li>
<li>任何共享内存段</li>
<li>任何匿名的内存映射, 如malloc分配的内存</li>
</ul>
<p>内核使用内存描述符结构体表示进程的地址空间, 内存描述符由mm_struct(<code><linux/sched.h></code>)结构体表示. <code>内核线程没有进程地址空间, 也没有相关的内存描述符, 所有内核线程没有用户上下文</code></p>
<blockquote>
<p>应用程序操作的对象是<code>映射到物理内存上的虚拟内存</code>, 而处理器操作的是物理内存, Linux使用三级页表完成地址转换, 每个虚拟地址作为索引指向页表, 页表项则指向下一级的页表. 在多级页表中通过TLB(translate lookaside buffer)作为一个虚拟地址映射到物理地址的缓存</p>
</blockquote>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><p><code><内核设计与实现></code></p>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<p><strong>Unix强大的根本原因:</strong></p>
<ol>
<li>Unix简洁, 提供几百个系统调用, 设计目的明确</li>
<li>Unix中<code>所有东西都被当做文件对待</code></li>
<li>Unix内核和相关系统工具是用C语言开发的, 移植能力强大</li>
<li>Unix进程创建迅速, 有独特的fork机制</li>
<li>Unix提供简单稳定的进程间通信元语</li>
</ol>
<blockquote>
<p>Linux是类Unix系统, 借鉴了Unix设计并实现了Unix的API.<br>应用程序通常调用库函数(如C库函数)再由库函数通过系统调用界面, 让内核代其完成各种任务.</p>
</blockquote>
</summary>
<category term="Linux" scheme="http://andrewliu.in/tags/Linux/"/>
</entry>
<entry>
<title>Google Protobuf源码剖析(一)</title>
<link href="http://andrewliu.in/2016/11/07/Google-Protobuf%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90-%E4%B8%80/"/>
<id>http://andrewliu.in/2016/11/07/Google-Protobuf源码剖析-一/</id>
<published>2016-11-07T13:52:00.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>很久之前写过一篇<a href="http://andrewliu.in/2016/06/05/Google-protobuf-C-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">Google protobuf(C++) 学习笔记</a>. <code>google protobuf</code>被大量用于公司的RPC通信中作为序列化和序列化工具, 高于JSON和XML的性能值得拥有. 刚好最近有时间, 准备强读一发<code>google protobuf源码</code></p>
</blockquote>
<h2 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h2><p>本文所有所有示例均基于官方示例<code>addressbook.proto</code>:</p>
<a id="more"></a>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line">package tutorial;</div><div class="line"></div><div class="line">message Person {</div><div class="line"> required <span class="built_in">string</span> name = <span class="number">1</span>;</div><div class="line"> required int32 id = <span class="number">2</span>;</div><div class="line"> optional <span class="built_in">string</span> email = <span class="number">3</span>;</div><div class="line"></div><div class="line"> <span class="keyword">enum</span> PhoneType {</div><div class="line"> MOBILE = <span class="number">0</span>;</div><div class="line"> HOME = <span class="number">1</span>;</div><div class="line"> WORK = <span class="number">2</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> message PhoneNumber {</div><div class="line"> required <span class="built_in">string</span> number = <span class="number">1</span>;</div><div class="line"> optional PhoneType type = <span class="number">2</span> [<span class="keyword">default</span> = HOME];</div><div class="line"> }</div><div class="line"></div><div class="line"> repeated PhoneNumber phone = <span class="number">4</span>;</div><div class="line">}</div><div class="line"></div><div class="line">message AddressBook {</div><div class="line"> repeated Person person = <span class="number">1</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li><code>required</code>字段初值是必须要提供的, 否则字段的便是未初始化的, 序列化的时候必须对<code>required</code>初始化</li>
<li><code>optional</code>字段如果未进行初始化,那么一个默认值将赋予该字段</li>
<li><code>repeated</code>字段可以理解为<code>数组</code>, </li>
</ul>
<blockquote>
<p>每个变量后的数字为标签, 用于标示了字段在二进制流中存放的位置</p>
</blockquote>
<p>运行<code>protoc -I=./ --cpp_out=./ ./addressbook.proto</code>通过<code>protoc</code>来生成 <code>.h和.cpp</code>文件.</p>
<p>那么<code>.h文件</code>中到底生成了什么呢?</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"># Person类的基类为::google::protobuf::Message类</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> :</span> <span class="keyword">public</span> ::google::protobuf::Message</div><div class="line"></div><div class="line"><span class="meta"># enum类型的数据, 可以通过Person::MOBILE来访问</span></div><div class="line"><span class="keyword">typedef</span> Person_PhoneType PhoneType;</div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> PhoneType MOBILE =</div><div class="line"> Person_PhoneType_MOBILE;</div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> PhoneType HOME =</div><div class="line"> Person_PhoneType_HOME;</div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> PhoneType WORK =</div><div class="line"> Person_PhoneType_WORK;</div><div class="line"> </div><div class="line"><span class="meta"># required和optional的普通类型, 产生的函数族都是差不多的. 对于每个字段会生成一个has函数、clear清除函数、set函数、get函数</span></div><div class="line"><span class="comment">// required string name = 1;</span></div><div class="line"><span class="function"><span class="keyword">bool</span> <span class="title">has_name</span><span class="params">()</span> <span class="keyword">const</span></span>; # <span class="function">has_xxx</span></div><div class="line"><span class="keyword">void</span> <span class="title">clear_name</span><span class="params">()</span>; # clear_xxx</div><div class="line"><span class="keyword">const</span> ::<span class="built_in">std</span>::<span class="function"><span class="built_in">string</span>& <span class="title">name</span><span class="params">()</span> <span class="keyword">const</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">set_name</span><span class="params">(<span class="keyword">const</span> ::<span class="built_in">std</span>::<span class="built_in">string</span>& value)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">set_name</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* value)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">set_name</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* value, <span class="keyword">size_t</span> size)</span></span>;</div><div class="line">::<span class="built_in">std</span>::<span class="function"><span class="built_in">string</span>* <span class="title">mutable_name</span><span class="params">()</span></span>;</div><div class="line">::<span class="built_in">std</span>::<span class="function"><span class="built_in">string</span>* <span class="title">release_name</span><span class="params">()</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">set_allocated_name</span><span class="params">(::<span class="built_in">std</span>::<span class="built_in">string</span>* name)</span></span>;</div><div class="line"></div><div class="line"><span class="meta"># repeated类型有些不同, 没有has_xxx函数族</span></div><div class="line"><span class="comment">// repeated .tutorial.Person.PhoneNumber phone = 4;</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">phone_size</span><span class="params">()</span> <span class="keyword">const</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">clear_phone</span><span class="params">()</span></span>;</div><div class="line"><span class="keyword">const</span> ::tutorial::<span class="function">Person_PhoneNumber& <span class="title">phone</span><span class="params">(<span class="keyword">int</span> index)</span> <span class="keyword">const</span></span>;</div><div class="line">::tutorial::<span class="function">Person_PhoneNumber* <span class="title">mutable_phone</span><span class="params">(<span class="keyword">int</span> index)</span></span>;</div><div class="line">::tutorial::<span class="function">Person_PhoneNumber* <span class="title">add_phone</span><span class="params">()</span></span>;</div><div class="line">::google::protobuf::RepeatedPtrField<::tutorial::Person_PhoneNumber >*</div><div class="line"> mutable_phone();</div><div class="line"><span class="keyword">const</span> ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >&</div><div class="line"> phone() <span class="keyword">const</span>;</div></pre></td></tr></table></figure>
<h2 id="Protobuf主要类"><a href="#Protobuf主要类" class="headerlink" title="Protobuf主要类"></a>Protobuf主要类</h2><ul>
<li><code>Message</code>类, 是一个抽象层, 记录了一个proto文件里的所有内容. <code>Message</code>继承自<code>MessageLite</code></li>
<li><code>MessageLite</code>类, 是一个轻量级的接口协议, 这个接口由所有协议的消息对象来实现, 这个类中包含大量定义的虚函数和纯虚函数. 使用<code>MessageLite</code>来生成代码, 需要在.proto中加入下面这行</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">option optimize_for = LITE_RUNTIME;</div></pre></td></tr></table></figure>
<ul>
<li><code>Arena</code>类主要用于协议消息的内存分配和释放, 并且分配内存是线程安全的.</li>
</ul>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 内存块的链表组织结构</span></div><div class="line"> <span class="comment">// Blocks are variable length malloc-ed objects. The following structure</span></div><div class="line"> <span class="comment">// describes the common header for all blocks.</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">Block</span> {</span></div><div class="line"> <span class="keyword">void</span>* owner; <span class="comment">// &ThreadCache of thread that owns this block, or</span></div><div class="line"> <span class="comment">// &this->owner if not yet owned by a thread.</span></div><div class="line"> Block* next; <span class="comment">// Next block in arena (may have different owner)</span></div><div class="line"> <span class="comment">// ((char*) &block) + pos is next available byte. It is always</span></div><div class="line"> <span class="comment">// aligned at a multiple of 8 bytes.</span></div><div class="line"> <span class="keyword">size_t</span> pos;</div><div class="line"> <span class="keyword">size_t</span> size; <span class="comment">// total size of the block.</span></div><div class="line"> <span class="function">GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t <span class="title">avail</span><span class="params">()</span> <span class="keyword">const</span> </span>{ <span class="keyword">return</span> size - pos; }</div><div class="line"> <span class="comment">// data follows</span></div><div class="line"> };</div><div class="line"></div><div class="line"><span class="comment">// Arena核心的初始化函数</span></div><div class="line"><span class="keyword">void</span> Arena::Init() {</div><div class="line"> lifecycle_id_ = lifecycle_id_generator_.GetNext();</div><div class="line"> blocks_ = <span class="number">0</span>;</div><div class="line"> hint_ = <span class="number">0</span>;</div><div class="line"> owns_first_block_ = <span class="literal">true</span>;</div><div class="line"> cleanup_list_ = <span class="number">0</span>;</div><div class="line"> <span class="comment">// options为构造函数的参数, 一个配置结构体ArenaOptions</span></div><div class="line"> <span class="keyword">if</span> (options_.initial_block != <span class="literal">NULL</span> && options_.initial_block_size > <span class="number">0</span>) {</div><div class="line"> GOOGLE_CHECK_GE(options_.initial_block_size, <span class="keyword">sizeof</span>(Block))</div><div class="line"> << <span class="string">": Initial block size too small for header."</span>;</div><div class="line"></div><div class="line"> <span class="comment">// Add first unowned block to list.</span></div><div class="line"> Block* first_block = <span class="keyword">reinterpret_cast</span><Block*>(options_.initial_block);</div><div class="line"> first_block->size = options_.initial_block_size;</div><div class="line"> first_block->pos = kHeaderSize;</div><div class="line"> first_block->next = <span class="literal">NULL</span>;</div><div class="line"> <span class="comment">// Thread which calls Init() owns the first block. This allows the</span></div><div class="line"> <span class="comment">// single-threaded case to allocate on the first block without taking any</span></div><div class="line"> <span class="comment">// locks.</span></div><div class="line"> first_block->owner = &thread_cache();</div><div class="line"> SetThreadCacheBlock(first_block);</div><div class="line"> AddBlockInternal(first_block);</div><div class="line"> owns_first_block_ = <span class="literal">false</span>;</div><div class="line"> }</div></pre></td></tr></table></figure>
<ul>
<li><code>Reflection</code>类, 是一个用于动态访问和修改协议消息各种变量域的类(也就是我们常说的反射机制), 该类只在Message中实现(<code>MessageLite中没有</code>)</li>
<li><code>Descriptor</code>类, 用于描述协议消息,通过<code>Message::GetDescriptor()</code>来获取Message对应的</li>
</ul>
<p>待续…</p>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>很久之前写过一篇<a href="http://andrewliu.in/2016/06/05/Google-protobuf-C-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">Google protobuf(C++) 学习笔记</a>. <code>google protobuf</code>被大量用于公司的RPC通信中作为序列化和序列化工具, 高于JSON和XML的性能值得拥有. 刚好最近有时间, 准备强读一发<code>google protobuf源码</code></p>
</blockquote>
<h2 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h2><p>本文所有所有示例均基于官方示例<code>addressbook.proto</code>:</p>
</summary>
<category term="C++" scheme="http://andrewliu.in/tags/C/"/>
</entry>
<entry>
<title>某度实习总结</title>
<link href="http://andrewliu.in/2016/10/29/%E6%9F%90%E5%BA%A6%E5%AE%9E%E4%B9%A0%E6%80%BB%E7%BB%93/"/>
<id>http://andrewliu.in/2016/10/29/某度实习总结/</id>
<published>2016-10-28T22:56:00.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>人呀,有时候也要考虑一下历史的行程,也要总结一下人生的经验。算算一个人来北京实习一年了,上半年在某乎,下半年在某度,而北京这个地方却没有给我留下太深的印象,喜欢的地方不多。马上要离开某度了,简单的总结一下自己吧,同时发泄一下最近消极的心情。过段时间可能会再写一篇,对传统互联网/创业公司/大体量公司的择业思考(又挖新坑)。</p>
</blockquote>
<p>文章大概几个部分吧,<strong>北京印象,人文关怀,工作感受,个人心得</strong>。文章中可能会出现一些某乎和某度的对比,仅个人见解。<strong>本文一切均个人视角请勿对号入座,想到哪里写到哪里。</strong></p>
<a id="more"></a>
<h2 id="北京印象"><a href="#北京印象" class="headerlink" title="北京印象"></a>北京印象</h2><blockquote>
<p>2015年10月,带着对未来的憧憬踏入祖国帝都。</p>
</blockquote>
<ul>
<li>去坐地铁的时候,让我印象深刻的是2号线地铁(好像是2号线)竟然没有护栏,简直恐怖。</li>
<li>北京的生活从自如租的的带阳台的出租屋开始。</li>
</ul>
<blockquote>
<p>2015年10月,正式进入互联网行业实习。</p>
</blockquote>
<ul>
<li>初入某乎实习,迎接我的是北京的雾霾天,我从来想到个一个地方的雾霾会那么严重,严重到大街上的所有人都不得不带着口罩,空气都被雾霾充斥,直到春夏雾霾渐歇。</li>
<li>某乎的冬天,在北京完成了人生第一次滑雪,只记得滑完雪,屁股好疼,内裤都是冰水。某乎的冬天,也完成了人生的第一次射箭,然而印象了了。</li>
<li>北京的冬天,会下雪,和我的老家一毛一样的。</li>
<li>某乎的团建和年会,给我的北京之旅留下了浓重的一笔,大家一起写剧本,一起演舞台剧,一起拍摄某乎五周年的视频频段,然而最后不得不和某乎的朋友说再见。</li>
</ul>
<blockquote>
<p>2016年4月,进入互联网三巨头之一实习。</p>
</blockquote>
<ul>
<li>初入某度,身边陌生,周围的同事也并不像某乎那样和蔼融洽。</li>
<li><p>某度的北京印象,平平淡淡,后文详述。</p>
</li>
<li><p>北京的人们,总是匆匆忙忙赶着地铁或者公交,快节奏的生活是在远方的小城中体验不到的。</p>
</li>
<li>北京的地上,总是到处拥堵,尤其是在互联网创造奇迹的<code>西二旗</code>,听说小米新发布的<code>小米Mix</code>意思是<strong>Made in 西二旗</strong></li>
<li>北京的景点,多是众众众众,天安门,故宫,长城,后海,圆明园,清华北京,都有去过,体会这个城市过去时代的繁华。</li>
</ul>
<h2 id="人文关怀"><a href="#人文关怀" class="headerlink" title="人文关怀"></a>人文关怀</h2><blockquote>
<p>叨叨了这么多才进入正题,年纪大了还是静不下来。</p>
</blockquote>
<p>在某度,没有感受到太多的人文关怀,毕竟人那么多,哪有那么周全的照顾到你的情绪,还是要自己动手丰衣足食才行。</p>
<ol>
<li>每天一人一份的水果或者酸奶</li>
<li>人均配置hp(i5/ssd/8G)加samsuang的19寸显示器,真心对眼睛不好,每天都拖着酸痛的眼睛回家,还是喜欢用自己的retina显示屏和大屏幕1080p的显示器,由奢入俭难呀。</li>
<li>某度半年也没有获得一个某熊吉祥物,这是我深深的怨念,给每个人入职的时候发一个不好吗,这样不是还能增加公司的归属感吗。</li>
<li>一周一次全公司抢票式报名的公开课,而我并未体验过,工作太忙?不感兴趣?我也不知道。</li>
<li>对新实习生的培训体系不健全,刚入职的时候全靠自己搜索,问身边的老司机,总算度过了当年痛苦的时光。</li>
<li>无限量供应的热水。还有咖啡,各种速溶冲泡饮料,然而喝了几天就再也不想碰了。</li>
<li>吃饭非免费,但可以报销,伙食并没有某乎的免费午餐那么好(不知道现在还有没有),毕竟我在某乎胖了十斤,而在某度又把这十斤瘦回去了。</li>
<li>晚上加班晚回去可以打车报销,然而我会说:我住的不是特别远(四十分钟的路)根本打不到车,女朋友经常嫌弃我回家太晚,其实心里挺内疚的,在这里很多时候,因为需求太多太急不得不加班,<code>但是生活不仅仅有工作</code>。</li>
</ol>
<blockquote>
<p>一到秋冬季节,北京的雾霾就非常严重,前段时间又是头疼,又是感冒发烧,我只能把这个锅丢给北京雾霾了(毕竟我是经常去健身房锻炼,还会经常和妹纸打羽毛球好吗),听说一次北京雾霾能让医院增收10%,能让口罩产业增收300%(逃</p>
</blockquote>
<h2 id="工作收获"><a href="#工作收获" class="headerlink" title="工作收获"></a>工作收获</h2><p>周围的同事都比较闷,或许是程序猿的共性?大家基本不聊天,吃饭的时候偶尔聊天也是和代码架构相关,但这些都掩盖不了周围的人们实力很强,和一群优秀的人在一起工作真是一种享受。</p>
<p>在某乎,最大的工作收获是:写代码要覆盖测试,虽然有时候测试写的不全会导致bug。然而即使有大量测试,也依然不能拯救某乎主站大姨妈式的服务器向你提了一个问题。</p>
<p>在某度,最大的工作收获是:学会了设计思维,<strong>写程序只是工作中很小很小的一部门</strong>,大部分时候应该是去全面思考当前工作的如何实现比较优秀。整理好自己的架构设计思路,拉上几个人一番头脑风暴,会有更多优化的地点,然后再开始写代码,一般效率更高。</p>
<p>在某乎,很多时候没有所谓的规范,没有日志规范,没有强制的代码规范,没有注释要求,带来的是各部门有自己规范或者说传统(代码段也有口口相传的),最后很难相互协作,出现问题只能看源码。</p>
<p>在某度,有强制的代码审查,有大量的注释(当然也有一些老坑需要自己看源码),注释写起来虽然浪费时间,但是有助于梳理函数功能和福泽后人。在某度所有的东西都规范化流程化了,虽然很好,但很多时间有大量的时间浪费在权限申请了,而且经常你不得不push别人帮你开通权限申请。</p>
<p>在某乎,这个年轻的公司,同事即朋友,代码库不大,跨部门开发总能找到合适的人结对编程,一起完成当前项目的推进,某乎的编程经历还是很开心的。</p>
<p>在某度,我最讨厌的就是跨部门合作,不是沟通的问题,而是很多跨部门合作是因为一方弱需求一方强需求,导致总有一方不配合,或者推出来一个新来的实习生背锅作为对接人,然而这有什么卵用,一问三不知?最后还不如自己好好看源码好,甩开膀子开干。</p>
<p>在某乎,我收获了好几个真诚的工友,现在依然可以偶然联系,微信吹吹流弊,ins互刷赞,一起膜蛤续命,还有我敬爱的郭教授(手动点赞)。</p>
<p>在某度,我没有收到几个朋友,大家都各自为政,每个人都有自己的家庭,也失去了年轻时候的朝气。<br>在某度,有些流程很拖沓,我不喜欢,做人做事干净利落,今天拖明天,明天拖后天,有什么意思?</p>
<p>在某乎,一个知识性社区,也是我现在依然每天都在刷,获取知识和时事的来源之一。记得当时,偶尔会有知友来公司送吃的以表感谢,感觉真是很好。</p>
<p>在某度,我来实习的时候,刚好是各种坏消息接踵而来的时候,我见到了很多big news,血友病卖吧,魏则西事件,某度外卖事件,PPT总监事件,各种无底线推广等等,虽然我也赞同技术无罪论,但我不喜欢这种为了追求kpi,为了追求盈利而无底线的做法,既然在国内属于这个技术顶尖的公司,就应该有这样公司的担当,勇于承认错误并改正,就像google那样选择不作恶。</p>
<p>在某度,我要强力吐槽一下,标配开发机,号称4G,双核CPU的开发机成天卡成狗,随便编译个代码就不能动了,你家开发机这么多人吐槽也不知道优化一下吗?(黑人问号,手动滑稽)。</p>
<p>不管怎么样,某乎和某度都是很赞的公司。</p>
<h2 id="个人小结"><a href="#个人小结" class="headerlink" title="个人小结"></a>个人小结</h2><p>说一些自己工作中的经验或者教训吧。</p>
<ol>
<li>工作中,需要别人协作的时候,要多push,自己的事情自己不推,还有谁在乎呢?你不管,别人也不管,然而锅还是在你身上甩不掉。</li>
<li>工作中,有问题就问,不要怕被嘲笑,被鄙视。你不问清楚,最后吃亏的一定是你。我听说很多不那么正面的话,<code>python的这个用法你都不会?</code>,<code>这个工作随便一个实习生都能做</code>,<code>这个算法你都不会,是怎么通过面试的?</code>。虽然明白这个道理,但依然没有做太好。</li>
<li>工作中,要勇于争取自己的利益,你不争取,你的那份就是别人或者充公了,人非圣贤,孰能无钱,我很缺钱,毕竟北京生活成本那么高,实习工资那么少?</li>
<li>不要人云亦云,做好自己的本职工作,无中生有的东西,你再帮他说一遍,等于你也有责任吧</li>
<li>有一个严格要求对你的人是很好的,这是对你负责,如果一个mentor对你不管不问,那他不是一个好的mentor。认真严格也是一种品质,这是mentor教给我的。</li>
<li>把当前手头的工作写入邮件发给别人review,这样一是可以给未来留下工作梳理依据,二是让别人知道你当前在做什么,<strong>这很重要</strong></li>
<li>离职的时候,尽量把自己的工作收尾,不要给人留下不可依赖的印象。</li>
</ol>
<blockquote>
<p>有时候很庆幸自己能够走进某度实习,感谢自己mentor和manager, 祝各自安好。</p>
</blockquote>
]]></content>
<summary type="html">
<p>本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" target="_blank" rel="external">署名-非商业用途-保持一致</a>的创作共用协议.</p>
<blockquote>
<p>人呀,有时候也要考虑一下历史的行程,也要总结一下人生的经验。算算一个人来北京实习一年了,上半年在某乎,下半年在某度,而北京这个地方却没有给我留下太深的印象,喜欢的地方不多。马上要离开某度了,简单的总结一下自己吧,同时发泄一下最近消极的心情。过段时间可能会再写一篇,对传统互联网/创业公司/大体量公司的择业思考(又挖新坑)。</p>
</blockquote>
<p>文章大概几个部分吧,<strong>北京印象,人文关怀,工作感受,个人心得</strong>。文章中可能会出现一些某乎和某度的对比,仅个人见解。<strong>本文一切均个人视角请勿对号入座,想到哪里写到哪里。</strong></p>
</summary>
<category term="Blog" scheme="http://andrewliu.in/tags/Blog/"/>
</entry>
<entry>
<title>Linux进程创建和调度学习笔记</title>
<link href="http://andrewliu.in/2016/10/08/Linux%E8%BF%9B%E7%A8%8B%E5%88%9B%E5%BB%BA%E5%92%8C%E8%B0%83%E5%BA%A6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<id>http://andrewliu.in/2016/10/08/Linux进程创建和调度学习笔记/</id>
<published>2016-10-08T12:45:56.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>读书笔记</p>
</blockquote>
<h2 id="进程管理"><a href="#进程管理" class="headerlink" title="进程管理"></a>进程管理</h2><blockquote>
<p>进程是处于执行期的程序, 包含代码段, 打开描述符, 挂起信号, 内核内部数据, 处理器状态, 一个或多个具有内存映射的内存地址空间及一个或多个执行线程.<br>线程是进程中活动对象, 包含<code>独立</code>的程序计数器, 栈和一组进程寄存器. <code>线程间可共享虚拟内存, 但每个都拥有各自的虚拟处理器</code></p>
</blockquote>
<ul>
<li>内核将进程的列表放在一个双向循环链表中, 每项为<code>task_struct</code></li>
<li>进程执行系统调用或者异常处理才会陷入内核空间(内核态)</li>
<li>Linux所有进程都是PID为1的init进程的后代</li>
</ul>
<a id="more"></a>
<p>每个进程或线程都有三个数据结构,分别是 <code>struct thread_info</code>, <code>struct task_struct</code> 和 <code>内核栈</code></p>
<p><strong>task_struct 结构体中的主要元素</strong>:</p>
<ul>
<li>struct thread_info *thread_info。thread_info 指向该进程/线程的基本信息。</li>
<li>struct mm_struct *mm。mm_struct 对象用来管理该进程/线程的页表以及虚拟内存区。</li>
<li>struct mm_struct *active_mm。主要用于内核线程访问主内核页全局目录。</li>
<li>struct fs_struct *fs。fs_struct 是关于文件系统的对象。</li>
<li>struct files_struct *files。files_struct 是关于打开的文件的对象。</li>
<li>struct signal_struct *signal。signal_struct 是关于信号的对象。</li>
</ul>
<h3 id="进程创建"><a href="#进程创建" class="headerlink" title="进程创建"></a>进程创建</h3><p>通过<code>fork和exec</code>来实现, fork() 拷贝当前进程创建一个子进程, exec() 负责读取可执行文件并将其载入地址空间开始执行.</p>
<ul>
<li>Linux的 fork() 使用写时复制(copy-on-write)页实现, 资源的复制只有在需要写入的时候才进行. <code>fork() 的实际开销是复制父进程的页表以及给子进程创建唯一的进程描述符</code></li>
<li>Linux通过 <code>Clone()</code> 实现 <code>fork()</code>. <code>fork() -> clone(SIGCHLD) -> do_fork() -> copy_process()</code></li>
</ul>
<p>copy_process()的工作:</p>
<ol>
<li>调用dup_task_struct为新进程创建一个内核栈, thread_info结果和task_struct, 值保持与当前进程相同</li>
<li>检查当前用户进程数未超出给定分配资源的限制</li>
<li>子进程部分信息被清0或重设为初始值</li>
<li>子进程状态被设置为 TASK_UNINTERRUPTIBLE, 保证他不会投入运行</li>
<li>更新 task_struct的flags成员</li>
<li>调用 alloc_pid为新进程分配有效的<code>PID</code>(此时才分配新pid)</li>
<li>根据传递给clone的参数, 设置拷贝或共享的资源.</li>
<li>返回一个指向子进程的指针.</li>
</ol>
<blockquote>
<p>vfork 与 fork 的区别是, vfork不拷贝父进程的页表项</p>
</blockquote>
<h3 id="线程"><a href="#线程" class="headerlink" title="线程"></a>线程</h3><ul>
<li>线程在Linux被视为一个与其他进程共享某些资源的进程</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"># 线程同样通过clone创建, 只是指定共享的资源不同</div><div class="line">clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, <span class="number">0</span>);</div></pre></td></tr></table></figure>
<h3 id="内核线程"><a href="#内核线程" class="headerlink" title="内核线程"></a>内核线程</h3><ul>
<li>内核线程用于完成内核需要在后台执行的一些操作</li>
<li>内核线程和普通进程的区别在于内核线程<code>没有独立的地址空间</code>, 只在内核空间运行, <strong>所有的内核线程共享内核地址空间</strong></li>
<li>内核线程可以被调度, 可以被抢占</li>
<li>内核线程只能由其他内核线程创建</li>
</ul>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"># <linux/kthread.h>, 内核线程创建</div><div class="line">struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),</div><div class="line"> void *data,</div><div class="line"> int node,</div><div class="line"> const char namefmt[], ...);</div><div class="line"></div><div class="line">#define kthread_create(threadfn, data, namefmt, arg...) \</div><div class="line"> kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg)</div><div class="line"></div><div class="line"># 创建并运行, kthread_create创建, wake_up_process唤醒</div><div class="line">#define kthread_run(threadfn, data, namefmt, ...) \</div><div class="line">({ \</div><div class="line"> struct task_struct *__k \</div><div class="line"> = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \</div><div class="line"> if (!IS_ERR(__k)) \</div><div class="line"> wake_up_process(__k); \</div><div class="line"> __k; \</div><div class="line">})</div></pre></td></tr></table></figure>
<h3 id="进程终止"><a href="#进程终止" class="headerlink" title="进程终止"></a>进程终止</h3><p>进程终止一般是调用 <code>exit()</code>, 最终基本是通过 <code>do_exit()</code>完成.</p>
<ol>
<li>task_struct的标志成员设置为 PF_EXITING</li>
<li>调用del_timer_sync()删除任一内核定时器</li>
<li>调用exit_mm()函数释放进程占用的 mm_struct</li>
<li>调用sem_exit()函数</li>
<li>调用exit_file()和exit_fs() 分别递减文件描述符, 文件系统数据的引用计数</li>
<li>执行一些其他的退出动作</li>
<li>调用exit_notify()向父进程发送信号, 为其子进程找继父(线程组其他线程或init进程). 进程状态设置为<code>EXIT_ZOMBIE</code></li>
<li>调度schedule()切换到新的进程. do_exit() 永不返回.</li>
</ol>
<blockquote>
<p>进程终止的清理工作和进程描述符的删除是分开执行的. 进程描述符的删除由<code>wait4()系统调用</code>完成. 两步完成所有资源才释放完成.</p>
</blockquote>
<h2 id="进程调度"><a href="#进程调度" class="headerlink" title="进程调度"></a>进程调度</h2><blockquote>
<p>进程调度程序可以看做在可运行态进程之间分配有限的处理器时间资源的内核子系统. Linux在2.6.23内核版本中使用了<code>完全公平调度算法(CFS)</code></p>
</blockquote>
<ul>
<li>进程分为I/O消耗型和处理器消耗型</li>
<li>Linux调度器以模块方式提供, 允许多种不同的可动态添加的调度算法并存.</li>
<li>Linux使用<code>完全公平调度(CFS)</code>, 允许每个进程运行一段时间, 循环轮转, 选择运行最少的进程作为下一个运行进程(不采用通过nice计算并分配给进程时间片做法), 分配给进程的是一个处理的使用比重. nice值在CFS中被作为进程获得处理器运行比的权重. 高nice值获得更低的处理器权重. 为防止可运行进程过趋于无限时, 进程各自获得处理器使用比趋于0, CFS为每个进程设置一个<code>最小粒度</code></li>
<li>CFS使用红黑树组织可运行进程队列, 选择可运行进程中最小<code>vruntime(进程虚拟运行时间)</code>的任务. 进程可运行或被fork()后被加入红黑树</li>
<li>Linux还提供两种实时调度策略(均为静态优先级) <code>SCHED_FIFO和SCHED_RR</code>由特殊的实时调度器管理. FIFO就是先入先出的调度策略. RR是一种带时间片的先入先出的调度策略</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"># <linux/sched.h> <span class="class"><span class="keyword">struct</span> <span class="title">sched_entity</span>对进程运行时间做记录</span></div><div class="line"><span class="title">struct</span> <span class="title">sched_entity</span> {</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">load_weight</span> <span class="title">load</span>;</span> <span class="comment">/* for load-balancing */</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">rb_node</span> <span class="title">run_node</span>;</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">group_node</span>;</span></div><div class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> on_rq;</div><div class="line"></div><div class="line"> u64 exec_start;</div><div class="line"> u64 sum_exec_runtime;</div><div class="line"> u64 vruntime;</div><div class="line"> u64 prev_sum_exec_runtime;</div><div class="line"></div><div class="line"> u64 nr_migrations;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SCHEDSTATS</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sched_statistics</span> <span class="title">statistics</span>;</span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_FAIR_GROUP_SCHED</span></div><div class="line"> <span class="keyword">int</span> depth;</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sched_entity</span> *<span class="title">parent</span>;</span></div><div class="line"> <span class="comment">/* rq on which this entity is (to be) queued: */</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">cfs_rq</span> *<span class="title">cfs_rq</span>;</span></div><div class="line"> <span class="comment">/* rq "owned" by this entity/group: */</span></div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">cfs_rq</span> *<span class="title">my_q</span>;</span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SMP</span></div><div class="line"> <span class="comment">/*</span></div><div class="line"> * Per entity load average tracking.</div><div class="line"> *</div><div class="line"> * Put into separate cache line so it does not</div><div class="line"> * collide with read-mostly values above.</div><div class="line"> */</div><div class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sched_avg</span> <span class="title">avg</span> ____<span class="title">cacheline_aligned_in_smp</span>;</span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div><div class="line">};</div></pre></td></tr></table></figure>
<blockquote>
<p>Linux优先级分两种. nice值(取值-20到+19, nice值最大优先级越低); 实时优先级(取值0到99, 实时优先级数值月大优先级越高)</p>
</blockquote>
<h3 id="上下文切换"><a href="#上下文切换" class="headerlink" title="上下文切换"></a>上下文切换</h3><p><code>schedule()</code>执行进程调度时, 调用kernel/sched.c中的<code>context_switch()</code>函数执行:</p>
<ul>
<li>调用声明<code>asm/mmu_context.h</code>中的switch_mm(), 该函数把虚拟内存从上一个进程切换到新的进程中.</li>
<li>调用<code><asm/system.h></code>中的<code>switch_to()</code>, 该函数负责从上一个进程的处理器状态切换到新进程的处理器状态. 包括保存、回复栈信息和寄存器信息</li>
</ul>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul>
<li>Linux内核设计与实现 - 原书第3版</li>
</ul>
]]></content>
<summary type="html">
<blockquote>
<p>读书笔记</p>
</blockquote>
<h2 id="进程管理"><a href="#进程管理" class="headerlink" title="进程管理"></a>进程管理</h2><blockquote>
<p>进程是处于执行期的程序, 包含代码段, 打开描述符, 挂起信号, 内核内部数据, 处理器状态, 一个或多个具有内存映射的内存地址空间及一个或多个执行线程.<br>线程是进程中活动对象, 包含<code>独立</code>的程序计数器, 栈和一组进程寄存器. <code>线程间可共享虚拟内存, 但每个都拥有各自的虚拟处理器</code></p>
</blockquote>
<ul>
<li>内核将进程的列表放在一个双向循环链表中, 每项为<code>task_struct</code></li>
<li>进程执行系统调用或者异常处理才会陷入内核空间(内核态)</li>
<li>Linux所有进程都是PID为1的init进程的后代</li>
</ul>
</summary>
<category term="Linux" scheme="http://andrewliu.in/tags/Linux/"/>
</entry>
<entry>
<title>深入探索C++对象模式读书笔记</title>
<link href="http://andrewliu.in/2016/09/30/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%B4%A2C-%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%BC%8F%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
<id>http://andrewliu.in/2016/09/30/深入探索C-对象模式读书笔记/</id>
<published>2016-09-30T06:49:01.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>什么是<code>C++对象模型</code>?</p>
<ol>
<li>语言中直接支持面向对象程序设计的部分.</li>
<li>对于各种支持的底层实现机制.</li>
</ol>
</blockquote>
<h2 id="Object-Lessons"><a href="#Object-Lessons" class="headerlink" title="Object Lessons"></a>Object Lessons</h2><ol>
<li>C++封装并未增加布局成本, 数据成员内含在class object中(像struct), <code>成员函数不会出现在object中</code>, <strong>非内敛函数只会诞生一个实例, 内联函数对每个使用者产生一个实例</strong></li>
<li>C++在布局及存取时间上主要的额外负担是由<code>virtual</code>引起的<ul>
<li>virtual function支持动态绑定</li>
<li>virtual base class实现单一而被共享的基类实例, 多用于多继承中</li>
</ul>
</li>
</ol>
<a id="more"></a>
<h3 id="C-Object-Model"><a href="#C-Object-Model" class="headerlink" title="C++ Object Model"></a>C++ Object Model</h3><ol>
<li>简单对象模式, object由很多slot组成, 每个slot(<code>指向member的指针</code>)指向一个memeber(包含数据成员和成员函数).</li>
<li>表格驱动对象模型, 将members相关信息分别放到data member table(持有data member)和member function table(member function的指针)中, class object本身包含指向两个表格的指针</li>
<li>C++对象模型, 非静态数据成员配置在class object内, 静态数据成员存放在个别class object外.</li>
</ol>
<p>C++对象模型之<code>虚函数</code>:</p>
<ol>
<li>每个<code>class(类)</code>产生一堆指向虚函数的指针, 放在virtual table(<code>vtbl</code>)中</li>
<li>每个<code>object(实例)</code>包含一个指针(<code>vptr</code>), 指向相关的vitual table. <code>vptr的设置和重置由class的构造/析构/拷贝赋值操作符完成</code>. 每个class的<code>type_info object</code>(支持RTTI)也经由virtual table被指出来.</li>
</ol>
<p><img src="http://ww4.sinaimg.cn/large/ab508d3dgw1f7we2123j2j21ce0waq7v.jpg" alt=""></p>
<blockquote>
<p>书中给出了一个struct和class结合使用的建议: 当要传递一个复杂的class object的全部或部分到C函数中, struct声明可以将数据封装起来, 并保证拥有与C兼容的空间布局.</p>
</blockquote>
<p>C++程序设计模型支持三种programming paradigms(编程范式):</p>
<ul>
<li>程序模型, 像C一样</li>
<li>抽象数据类型模型</li>
<li>面向对象模型</li>
</ul>
<blockquote>
<p>多态的主要用途是经由一个共同的接口来影响类型的封装, 这个接口通常被定义在一个抽象的base class中</p>
</blockquote>
<h2 id="The-Semantics-of-Constructors"><a href="#The-Semantics-of-Constructors" class="headerlink" title="The Semantics of Constructors"></a>The Semantics of Constructors</h2><h3 id="Default-Constructor"><a href="#Default-Constructor" class="headerlink" title="Default Constructor"></a>Default Constructor</h3><p>四种情况会造成编译器必须为未声明构造函数的 classes 合成一个 default constructor</p>
<ol>
<li><code>带有Default Constructor的Member Class</code>. 如果class没有任何构造函数, 但包含一个<code>member object</code>, 而后者有默认构造函数, 编译器会为该clas合成一个default constructor(只是为了满足编译器的需求). 如果class有默认构造函数, 且包含<code>member object</code>, 则<strong>编译器会扩张已存在的构造函数</strong>.</li>
<li><code>带有Default Constructor的Base Class</code>. 一个没有任何构造函数的class派生自一个带有default constructor的 base class, 这个派生类中的default constructor将会被合成.</li>
<li><code>带有一个Virtual Function的class</code>. <strong>默认构造函数正确的初始化每个class的vptr</strong>. class声明一个虚函数会合成默认构造函数</li>
<li><code>带有一个Virtual Base class的Class</code>, class派生自一个继承链, 其中有一个或者更多virtual base classes</li>
</ol>
<p>带有虚函数类在编译器:</p>
<ol>
<li>编译期一个virtual function table会被编译器产生, 内放class 的virtual functions地址</li>
<li>每个<code>class object</code>中, 一个额外的 pointer member(vptr) 被编译器合成出来, 内含相关与class vtbl的地址.</li>
</ol>
<h3 id="Copy-Constructor"><a href="#Copy-Constructor" class="headerlink" title="Copy Constructor"></a>Copy Constructor</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"># 三个场景使用拷贝构造函数</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span>;</span></div><div class="line">Base a;</div><div class="line">Base b = a; <span class="comment">//1. 显示拷贝</span></div><div class="line"><span class="keyword">void</span> (Base x); <span class="comment">//2. object参数值传递</span></div><div class="line"><span class="keyword">return</span> b; <span class="comment">//3. 值传递的函数返回object</span></div></pre></td></tr></table></figure>
<ol>
<li>class未提供显式copy constructor时, 默认拷贝构造函数会把<code>内建或派生</code>的 data member 的值, 从某个object拷贝到另一个object上, 但不会拷贝其中的<code>member class object</code></li>
</ol>
<h3 id="Member-Initialization-List"><a href="#Member-Initialization-List" class="headerlink" title="Member Initialization List"></a>Member Initialization List</h3><p>以下情况必须使用成员初始化列表:</p>
<ol>
<li>当初始化一个 reference member 时</li>
<li>当初始化一个 const member 时</li>
<li>当调用一个 base class 的 constructor, 而它拥有一组参数时</li>
<li>当调用一个 member class 的 constructor, 而它拥有一组参数时</li>
</ol>
<ul>
<li><strong>初始化成员列表的顺序是由class中的members声明顺序决定的</strong></li>
<li>调用<code>member function</code>设定一个member的初值可行, 因为与此object 相关的 this指针已经被建构妥当</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">X::X(<span class="keyword">int</span> val) :</div><div class="line"> i(xfoo(val)), <span class="comment">// xfoo必须是 member function</span></div><div class="line"> j(val) {</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="The-Semantics-of-Data"><a href="#The-Semantics-of-Data" class="headerlink" title="The Semantics of Data"></a>The Semantics of Data</h2><h3 id="Data-Member-Layout"><a href="#Data-Member-Layout" class="headerlink" title="Data Member Layout"></a>Data Member Layout</h3><ul>
<li>非静态数据成员在class object的排列顺序和其被声明的顺序一样</li>
<li><code>静态成员函数</code>不会放入对象布局中, 会被放入<strong>data segment</strong></li>
</ul>
<blockquote>
<p>C++标准对布局持放任态度.</p>
</blockquote>
<h3 id="Data-Member-get-set"><a href="#Data-Member-get-set" class="headerlink" title="Data Member get/set"></a>Data Member get/set</h3><ul>
<li><code>static data member</code>在class object中存取不会招致任何空间或执行时间上的额外负担(静态数据成员不在class object内部)</li>
<li><code>nonstatic data member</code>存放在 class object 内, 存取效率和 c struct member 或 nonderived class member 一样.</li>
</ul>
<blockquote>
<p>继承(非虚继承)不会不会增加空间和存取时间上的额外负担</p>
</blockquote>
<p>菱形继承的解决方案是导入虚拟继承</p>
<p><img src="http://ww3.sinaimg.cn/large/ab508d3djw1f80297j7bzj20ja0bqjs4.jpg" alt=""></p>
<p>虚继承的实现: class 如果内包含一个或多个 <code>virtual base class subobjects</code>, 将被分割成两部分: 一个不变区域和一个共享区域, 不变区域中的数据, 不管后继如何演化, 总有固定的offset用于直接存取, 共享区域只能被间接存取(在虚表中放置 virtual base class 的 offset)</p>
<h2 id="The-Semantics-of-Function"><a href="#The-Semantics-of-Function" class="headerlink" title="The Semantics of Function"></a>The Semantics of Function</h2><h3 id="Nonstatic-Member-Functions"><a href="#Nonstatic-Member-Functions" class="headerlink" title="Nonstatic Member Functions"></a>Nonstatic Member Functions</h3><p>C++设计准则之一: 非静态成员函数至少必须和一般的非成员函数有相同的效率.</p>
<blockquote>
<p>编译器将类的成员函数转换为非成员函数</p>
</blockquote>
<p>转换步骤:</p>
<ol>
<li>改写函数signature, 增加一个额外的参数(this)</li>
<li>将每一个<code>对 nonstatic data member 的存取操作</code>改为经过this指针存取</li>
<li>将 member function 重新谢伟一个外部函数(对函数名特殊处理. <code>name mangling</code>)</li>
</ol>
<h3 id="Virtual-Member-Functions"><a href="#Virtual-Member-Functions" class="headerlink" title="Virtual Member Functions"></a>Virtual Member Functions</h3><p>多态: 以 public base class的指针(或引用) 寻址出一个 derived class object.</p>
<ul>
<li>一个类(不是对象)只有一个virtual table, 每个object被安插一个由编译器产生的指针(vptr).</li>
<li>派生的子类,会 overriding 一个可能存在的 base class virtual function实例</li>
</ul>
<p><img src="http://ww2.sinaimg.cn/large/ab508d3djw1f806zpmvegj21520y047e.jpg" alt=""></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derived</span> :</span> <span class="keyword">public</span> Base1, <span class="keyword">public</span> Base2 {};</div><div class="line"># 两张虚表</div><div class="line">vtbl_Derived; <span class="comment">// 主要虚表</span></div><div class="line">vtbl_Base2_Derived; <span class="comment">// 次要虚表</span></div></pre></td></tr></table></figure>
<p><strong>多重继承</strong>情况下, 维护有多张虚表. 当Deriveed对象指定给Base1指针或Derived指针时, 被处理的virtual table 是主要表格<code>vtbl_Derived</code>, 当Deriveed对象指定给Base2时, 被处理的虚表为<code>vtbl_Base2_Derived</code></p>
<p><img src="http://ww2.sinaimg.cn/large/ab508d3djw1f807sjmgdfj214a108n6p.jpg" alt=""></p>
<h3 id="Static-Member-Function"><a href="#Static-Member-Function" class="headerlink" title="Static Member Function"></a>Static Member Function</h3><blockquote>
<p><strong>没有this指针</strong></p>
</blockquote>
<ul>
<li>静态成员函数将被转换为一般的非静态成员函数调用</li>
<li>不能被声明为 const, volatile, virtual</li>
<li>不需要经由class object 调用</li>
</ul>
<h3 id="Inline-Functions"><a href="#Inline-Functions" class="headerlink" title="Inline Functions"></a>Inline Functions</h3><p>处理 inline函数的两个阶段:</p>
<ol>
<li>分析函数定义, 以决定函数的 <code>intrinsic inline ability</code>(我理解为天生的内联能力).</li>
<li>真正的inline函数扩展操作是在调用的那一点上.</li>
</ol>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul>
<li>深入探索C++对象模型</li>
</ul>
]]></content>
<summary type="html">
<blockquote>
<p>什么是<code>C++对象模型</code>?</p>
<ol>
<li>语言中直接支持面向对象程序设计的部分.</li>
<li>对于各种支持的底层实现机制.</li>
</ol>
</blockquote>
<h2 id="Object-Lessons"><a href="#Object-Lessons" class="headerlink" title="Object Lessons"></a>Object Lessons</h2><ol>
<li>C++封装并未增加布局成本, 数据成员内含在class object中(像struct), <code>成员函数不会出现在object中</code>, <strong>非内敛函数只会诞生一个实例, 内联函数对每个使用者产生一个实例</strong></li>
<li>C++在布局及存取时间上主要的额外负担是由<code>virtual</code>引起的<ul>
<li>virtual function支持动态绑定</li>
<li>virtual base class实现单一而被共享的基类实例, 多用于多继承中</li>
</ul>
</li>
</ol>
</summary>
<category term="C++" scheme="http://andrewliu.in/tags/C/"/>
</entry>
<entry>
<title>macOS Sierra 惊险升级</title>
<link href="http://andrewliu.in/2016/09/24/macOS-Sierra-%E6%83%8A%E9%99%A9%E5%8D%87%E7%BA%A7/"/>
<id>http://andrewliu.in/2016/09/24/macOS-Sierra-惊险升级/</id>
<published>2016-09-24T10:26:27.000Z</published>
<updated>2017-06-17T22:14:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="惊现问题"><a href="#惊现问题" class="headerlink" title="惊现问题"></a>惊现问题</h2><p><code>2016年9月21</code> Apple开始推送 <code>macOS Sierra(10.12)</code>.</p>
<p><strong>此处升级的亮点:</strong></p>
<ul>
<li><strong>亮点就是没有亮点!!!</strong></li>
<li>最大的升级是<code>Mac OS X</code> 改名为 <code>macOS'</code>, 很大的改变有木有</li>
<li>Mac增加了Siri支持, 我知道我Mac多了个天气预报小助手</li>
<li>可以使用Apple Watch自动近距离解锁Mac, 听说<a href="">Near Lock</a>已哭晕在厕所? 然而首先你要买一部 <code>Apple Watch</code></li>
<li>跨设备复制粘贴, 可以使用云端剪切板, iPhone上复制的东西可以在Mac上直接黏贴. 然而首先你要买一部 <code>iPhone</code></li>
<li>Safari我就不喷了, 反正用了Chrome的我实在受不了龟速的Safari. 听说Safari很省电, 这个卖点不错!</li>
<li>还有啥? 这次升级只有很少的App闪退阵亡.(呵呵</li>
</ul>
<blockquote>
<p>然后开始作死升级之路… 怎么升级就不说了, 正常人都知道….</p>
</blockquote>
<a id="more"></a>
<p><img src="http://ww3.sinaimg.cn/large/ab508d3dgw1f81hwo4xcwj20qo0zk0t7.jpg" alt=""></p>
<p>告诉我macOS未能安装在电脑上, 磁盘没有足够的空间来安装..</p>
<p>我当时就哔了狗了, 你安装前不先检查磁盘剩余空间就敢给我安装?<br>重启后, 自动又开始安装, 然后再一次错误, 我就知道出事了…</p>
<p>都是我最近下片无数, 看完不删还想有空再回味一下, 这下子出事了… 磁盘不够了…</p>
<h2 id="尝试解决"><a href="#尝试解决" class="headerlink" title="尝试解决"></a>尝试解决</h2><p>方法一. <code>Failed</code>. 安全模式方法, 重启后, 按住<code>Shift</code>等待出现苹果标志, 进入Mac模式, 听说此模式可以进入电脑, 这样我就能够删除我的大片了, 然后就有足够空间了, 然而我天真了, 真的再也进不去系统了, 一到80%或者100%就卡住不动了,太坑爹了…</p>
<p><img src="http://ww3.sinaimg.cn/large/ab508d3dgw1f81i4hw4xaj20qo0zk3yx.jpg" alt=""></p>
<p>方法二. <code>Failed</code>. 恢复模式方法, 重启后, 按住<code>Command + R</code>进入恢复模式, 在菜单栏的工具中, 打开Terminal, 满心以为可以通过Terminal中删除home文件下的文件. 结果我发现里面全是一些系统文件, 没有任何个人文件的影响, 此方法猝..</p>
<p>方法三. <code>Failed</code>. Ubuntu大法. 插入制作了Ubuntu的U盘, 按住<code>Option</code>开机, 开机后选址<code>Efi</code>(大概是这个名字)模式, 然后选择<code>Try Ubuntu but not installing</code>方式试用Ubuntu. 通过Ubuntu挂载Mac的硬盘, 然后对Mac硬盘的文件进行删除. 结果我又天真了, 由于硬盘未能安装成功更新, 导致挂载失败, 只能挂载恢复盘的文件, 我要这玩意有何用…</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"># 安装hfsprogs用于支持hfsplus</div><div class="line">$ sudo apt-get install hfsprogs</div><div class="line"></div><div class="line"># 测试要挂载盘的状态, sdXX表示要挂载的磁盘, 如sda1, sda2</div><div class="line">$ sudo fsck.hfsplus -f /dev/sdXX</div><div class="line"># 输出结果为 The volume #### appears to be OK表示可以挂载</div><div class="line"></div><div class="line"># 挂载磁盘到本地的路径下, 此处我挂载sda2到本地/home/ubuntu路径下</div><div class="line">sudo mount -t hfsplus -o fore,rw /dev/sda2 /home/ubuntu</div><div class="line"># 若挂载成功可进行读写操作</div></pre></td></tr></table></figure>
<p><img src="http://ww3.sinaimg.cn/large/ab508d3dgw1f81ihpzf4cj20qo0zkta2.jpg" alt=""></p>
<ol>
<li><code>Success</code>. 最后实在没办法了, 我又让他重启自动安装了, 结果发现这次成功了, 我还能说什么????</li>
</ol>
<p><img src="http://ww4.sinaimg.cn/large/ab508d3dgw1f81ij42nrpj20js08adgg.jpg" alt=""></p>
<h2 id="自我反省"><a href="#自我反省" class="headerlink" title="自我反省"></a>自我反省</h2><ol>
<li>以后再升级, 千万不能硬上了, 记得备份呀. 说的我好像买的起<code>Time Machine</code>一样</li>
<li>升级前一定要看看剩余的磁盘空间呀, 千万别装备呀, 千万别信Apple粑粑的升级包呀</li>
</ol>
<blockquote>
<p>最后我只想大声说一句: 重启大法好!!!!</p>