2010年5月11日 星期二

[books] 程式設計師的自我修養 - 連結、載入、程式庫



中文書名: 程序员的自我修养:链接、装载与库
中文書名: 程式設計師的自我修養:連結、載入、程式庫

傻笑的看著這兩本書, 心中真是開心, 兩個中文世界各自有一本同樣的好書。

繁體中文版本 20100321 以 458/580 購於高雄多米。
簡體中文版本 20140812 代購 (中國亞馬遜), 20140823 拿到, 12 天, 有點慢阿!
花費: 45.7/65rmb 112.5 + 45.7 * 5.2 = 350.14

就算加上 112.5 這麼高的運費, 還是比繁體中文版本便宜, 所以呢? 沒有所以, 碁峰出版的繁體中文品質很好, 458 不貴, 那我為什麼要買簡體中文版本呢?

好書難得, 只是想看看原文本長什麼樣而已。不少書籍我同時有英文原文版本和中文譯本, 那簡體中文有需要嗎? Orange's 一個作業系統的實現我購買簡體中文版本, 是因為他的製作實在有些問題, 而這本的繁體中文版本製作的很好, 無可挑剔, 我只是以「尊敬」的想法來購買簡體中文版本。

技術人尊敬技術人, 本書作者的努力實在令我佩服, 我只是花錢買他們研究的知識, 比起來渺小多了。

我通常會紀錄購買金額和管道, 讀這篇文章的朋友我覺得你們應該也會想知道, 尤其是在台灣買不到的書籍。

台灣出版社是不是以後只能出版初學者的書籍, 說實在, 翻譯簡體中文書籍我覺得是多此一舉, 目前已經愈來愈多人接受中國術語, 對這些術語的接受度很高, 再加上差價, 直接購買簡體中文版本來閱讀不是什麼問題, 也許現在還可以撈一票 (我可不是說碁峰), 只會出版簡體中文還做不好的出版社遲早要倒大楣。



簡體中文封面折頁有作者群的簡介, 這個繁體版怎麼可以沒有呢? 簡體版本是 20090501 出版的, 我的版本是 201401 第 12 刷。

好久沒讀電腦書讀得這麼痛快了。這是一本中國出版的書籍, 最近台灣電腦出版界開始出版很多中國的電腦技術書籍, 看看書名, 有些真的是很深入的技術, 或是台灣這邊比較少有的主題。

但這些書籍幾乎有著共同的問題, 翻譯, 是的, 簡體中文, 中國術語, 對我來說, 和英文一樣, 就是外國文字, 需要翻譯為台灣的用字遣詞。

大部份的出版社只把簡體中文繁體一下, 就出書了, 這很不負責任。這本書在碁峰的出版下, 找來了賴榮樞作術語的轉換, 看來令人舒服, 沒有惱人的中國術語, 都是我那時代的電腦術語, 難怪讀來行雲如流水, 刷刷刷, 一直往下翻, 不過這本書可不是容易啃的書籍, 需要有點耐心仔細閱讀。但是有些詞句沒注意到, 沒有翻好, 上一行是指標, 下一行是指針, 還好大部份都有處理, 算是很用心的出版社, 我能看的這麼順暢, 峰哥 ... 呃 ... 是碁峰功不可沒。

翻譯簡體中文已經比英文容易多了, 卻還不用心, 有些出版社真的該打屁股了。那些讓我看的很痛苦的書, 該出版社也提供不少助力。

很佩服這本書的作者群俞甲子、石凡、潘愛民, 太厲害了, 雖然說原始碼之下沒有秘密, 但有多少人可以有如此功力, 如此多的時間, 去從原始碼中挖掘背後的秘密。至少我沒有這樣的能力, 而只要花 458 台幣, 就可以輕易吸收這樣的知識, 真的是太便宜了。

linker, loader, C runtime library 這些知識, 也許對於大多數編程人員沒有立即性的幫助, 不知道這些, 一樣可以寫程式, 因為若是重要到不了解這些知識就沒辦法寫程式, 早就有一堆書籍會討論這些技術, 也不用去辛苦的挖原始碼了。

我對這些議題早有興趣, 不是為了精進自己的程式功力, 我只是想「知道」而已。到底 compiler, linker, loader 在我寫的程式背後做了什麼事情, 程式真的是只有執行我寫的那段而已嗎?一步一步帶領讀者看著 linker 做了什麼好事, 將 binary 檔案中的位址重新填入正確的值, 真是過癮, 原來程式就是這樣被修改的。其實大學的系統程式就是這樣的課程, 但我那時候應該還沒有與之結緣吧!

4.6.3 p 127 稍微解釋了 gnu ld 的 linker script, 讓我大受俾益, 看 ld 英文手冊實在頭痛, 有了簡單的認識在看英文手冊, 應該會好讀點。不過後來讀的書籍/程式實作更加讓我理解 linker script, 現在我已經不在害怕 linker script 了 (縱使我並不完全理解他)。

page 350, 最上方的 FAQ 好像漏了一段, msvcrt.dll 和 msvcr90.dll 有什麼區別, 不過簡體中文版也是一樣, 錯不在碁峰。

c/c++ runtime 的說明也很精彩, 原來 c/c++ runtime 就是這樣完成的。

我大概花了一個月的時間讀完, 因為實在太精彩, 欲罷不能。雖然我可以看懂書上的知識, 不過書中的知識很容易就忘記了, 我認為是自己沒有實際做過類似的苦工。在研究 os 時, 不知道由於什麼緣故 (我忘了因為什麼接觸這些工具), 我大量使用 objdump, readelf, nm 這些工具, 再重新翻閱此書時, 心中有了些許連結,  這本書的東西還是要有相關的實作來配合, 要不然很容易就忘記這些東西, 因為本書的內容在一般的程式設計中, 幾乎不太會用到, 能在學生時代就把這些知識掌握好是比較適合的, 出了社會, 有了工作壓力, 要在這樣玩這些東西, 是很困難的。

20130622 (已經過了 3 年) 我重新閱讀此書的 chapter 3, 4, 6, 7, 經過 os 洗禮後, 我更能理解這幾章談的東西, 果然沒有實作就無法深入理解本書的內容, 我打算參考 Binary Hacks--駭客秘傳技巧一百招 #72, 實作一樣的功能, 但不使用 bfd library, 試試自己的理解程度, 這有什麼用呢?不知道耶!但這麼有趣的東西, 實在無法拒絕這誘惑阿!

和 binary hacks 不同的是, 我沒有使用 bfd library, 單純靠著 elf object 的內容, 改寫所有的位址, 就是 relocation 的動作, 成功載入了 hello.o。這是集這兩本書之大成發展的程式, 也為我徹底解除 linker 的疑惑, 再加上我已經能看懂 x86 machine code, 有了這些知識的集合, 才有了這個程式。

很苦嗎?真的很苦, 但痛苦過後的甘甜才真的能深入人心, 我的身體已經記住了什麼是 dynamic linker/loader, 若真的只是純看書的話, 沒有下過和作者一樣的苦工, 那這些知識可能真的沒想像中的有理解, 這是我讀第二次後的體驗。

這幾章大概就是本書的重點了, 完整的解釋 static/dynamic linker 和 loader 的動作, 和前一次的閱讀, 我相信我的體會一定有所不同, 很高興中文世界能有這本書籍。

這本書不能讓你寫程式變得厲害, 如果你是想要增進寫程式的能力才閱讀此書, 你可能挑錯課本了 (可以練 ACM)。這本書談的是 linker/loader 的基本知識, 這不能讓你寫程式的技能變強, 那是另外一個專業。

電腦世界知識更新的很快速, 但基本原理是不會改變的, 我自己覺得把時間花在追求新技術 (指那種很快又被更新的新新技術取代), 不如把時間花在學習基本上, 看過图灵和 ACM 图灵奖後, 我才知道現在很流行的 thread, 平行處理, 虛擬機器技術, 在 1960 年代計算機發展時期, 就有人在研究了。

我曾經醉心於 c++ 的學習, 而 c++ 11 的東西更是複雜, 現在我已經不再那麼沉迷於 c++, 有更有趣的基本知識讓我去學習, 但我還是很愛 c++ 就是。它是一個了不起的語言, 在各項技術上取得平衡, 這可不容易。

能完成 load_obj 這個小程式, 令我開心不已, 你若有興趣看的話, 也許可以發現程式寫的不好, 那是當然, 寫出好程式那是另外一種專業 (還是練 ACM), 我還沒能把這方面練好。

elf relocation 書上剖析的極為清楚, windows coff 則沒那麼詳細, 這篇  http://www.mouseos.com/assembly/07.html 補足了這部份。

而有了 elf relocation 的基本知識, 我順道把 win32 coff object 也實作出來, load_obj 這支程式, 也可以載入 win32 coff object, 當然也可以在 linux 執行該 coff object 的 function, 甚至使用 printf 印出變數, 怎麼把 win32 printf 換成 linux printf? 把 printf 的位址 relocate 成 linux printf 的位址就好, 沒想到是如此的簡單吧! 這就是基本知識的威力。

程式碼在這裡:
https://github.com/descent/progs/tree/master/load_obj

可參考這兩篇文章:
  1. dynamic loader/linker 實作 (0) - 自行載入 linux/elf object file
  2. dynamic loader/linker 實作 (1) - 自行載入 object file win32 coff 篇

3.4, 3.5 在介紹 elf 相關結構, ex: symbol table, string table, section header table ... 對於理解 elf 很有幫助, 這得要有相當功力才能看懂, 因為只懂名詞解釋大概只完成 40% 的理解, 能看懂名詞解釋就算前進一大步了。試試自己的程度吧!

7.3 介紹與位址無關的程式碼, 這是什麼意思? 就是字面上的意思。XD 你知道你用 c compiler 做出來的程式執行位址是哪裡嗎? 應該這麼說, 它會被一種稱為 loader 的程式載入到記憶體的某個位址, 你想知道是哪個位址嗎? 是 0x100, 0x200 還是 0x300。

用 readelf 可以得知這個位址:
readelf -a /bin/ls
  Entry point address:               0x804c1b4

readelf -a /bin/cat 
  Entry point address:               0x804a11c

奇怪? 怎麼會不一樣? 我還以為應該都會一樣, 算了不管, 這我沒研究。

又如果是 0x100, 那我把他搬到 0x500 這個程式還能正常執行嗎? 若是可以, 那這個程式就是所謂的和位址無關的程式碼, 很直覺的感受到, 要能這樣, 得付出一些代價吧!



簡體中文和繁體中文真的是頁頁對照, 都是 459 頁。這也是理所當然吧!

書上官方網站: http://blog.csdn.net/justpub/

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。