1.2. 作者的私語(Administrata) 版權說明(copyright information)與合法的行逕規定(legalese),就擺在這份文件的尾端.除此之外,我......,我還有一些不得不提醒你的話要講:就算你□著沒事干,也不要在Usenet上丟一些呆瓜問的問題;還有啊,不要老以為自己C的功力深厚,專門發表一些不是bugs的bugs出來丟人現眼, 告訴別人你不學無術.最後;嚼口香糖的時候,不妨挖挖你的鼻孔(,and picking your nose while chewing gum)! [譯者注:不知道這是那一國的幽默? eh? :-)另一種可能是原文有缺漏字匯, 像是"and not picking your nose while chewing gum."]
4.3.3. K & R gcc是個與ANSI相容的編譯器;希奇的是,目前大多數的程式碼都不符合ANSI所定的標準.假如你熱愛ANSI,喜歡用ANSI提供的標準來撰寫C程式,似乎除了在編譯器的旗號上加上-traditional之外,就沒有什麼其它的可以多談的了. There is a certain amount of finer-grained control over which varieties of brain damage to emulate; 請自行查閱gcc info page. 要注重的是,盡管你用了-traditional來改變語言,它的效果也僅局限在gcc所能夠接受的□圍.例如, -traditional會打開(turn on)-fwritable-strings,使得字串常數(string constants)移至資料記憶體空間(data space)內(從程式碼記憶體空間(text space),這地方是不能任意寫入的).這樣做會讓程式碼的記憶體空間無形中增加的.
4.3.8. 產生中斷的系統呼叫(Interrupted system calls) 4.3.8.1. 徵兆(Symptom): 當一支程式以Ctrl-Z中止(stop),然後再重新執行(restart)時--或者是其它可以產生Ctrl-C中斷(interruption)信號的情況,如子程序(child process)終結(termination)等--系統就會抱怨說"interrupted system call"或是"write: unknown error",或者諸如此類的訊息.
4.3.8.2. 問題點: POSIX的系統檢查信號的次數,比起一些舊版的Unix是要多那麼一點.假如是Linux,可能就會執行signal handlers了--非同步地(asynchronously)(計時器的滴答聲) 系統呼叫的傳回值(on return from any system call) 在下列系統呼叫的執行期間: select(), pause(), connect(),accept(), read() on terminals, sockets, pipes or files in /proc, write() on terminals, sockets, pipes or the line printer, open() on FIFOs, PTYs or serial lines,ioctl() on terminals, fcntl() with command F_SETLKW, wait4(), syslog(), any TCP or NFS Operations.
修改成, int result; while (len > 0) { result = read(fd,buffer,len); if (result < 0) { if (errno != EINTR) break; } else { buffer += result; len -= result; } }
原始的程式片段,使用ioctl().
int result; result = ioctl(fd,cmd,addr);
修改成, int result; do { result = ioctl(fd,cmd,addr); } while ((result == -1) && (errno == EINTR)); 注重一點,有些版本的BSD Unix,其內定的行為(default behaviour)是重新執行系統呼叫.若要讓系統呼叫中斷,得使用 SV_INTERRUPT或SA_INTERRUPT旗號.
4.3.9. 可以寫入的字串(Writable strings) gcc對其users總懷抱著樂觀的想法(optimistic view),相信當他們打算讓某個字串當作常數來用時---那它就真的只是字串常數而已.因此,這種字串常數會儲存在程式碼的記憶體區段內(in the code area of the program).這塊區域可以page到磁碟機的image上,避免耗掉swap的記憶體空間,而且任何嘗試寫入的舉動都會造成分頁的錯誤(segmentation fault).這可是一種特色呢! 對老舊一點的程式而言, 這可能會產生一個問題.例如,呼叫mktemp(),傳遞引數(arguments)是字串常數. mktemp()會嘗試著在*適當的位置(in place)*重新寫入它的引數. 修正的方法不外乎(a)以-fwritable-strings編譯,迫使gcc將此常數置放在資料記憶體空間(data space)內.或者(b)將侵犯地權的部份(offending parts)重新改寫,配置一個不為常數的字串(non-constant string),在呼叫前,先以strcpy()將資料拷貝進去.
執行程式而不帶任何引數(with no arguments),可解釋成(construe)是一種邀請函(invitation),目的是把此程式的動態程式庫獨立(dynamic library dependencies)的特性印出來(print out).至少,a.out是這樣的.就ELF而言,事情就不是這樣了.
(假如你想得知此程式庫的資訊,有一些更簡單的介面可用;參考動態載入(dynamic loading)那一章節,或是ldd的manual page.) 11/16/97譯 5. Debugging and Profiling 5.1. Preventative maintenance (lint) lint對Linux而言并沒有很廣泛的用途,主要是因為大部份的人都能滿足於gcc所提供的警告訊息(warnings).可能最有用的就是-Wall參數了---這個參數的用途是要求gcc將所有的警告訊息顯現出來. but probably has more mnemonic value if thought of as the thing you bang your head against.
另外,UPS除錯程式已由Rick Sladkey移植成功.UPS可以在X底下活得很好,不像xxgdb那樣---僅僅是gdb的X前端介面(X front end).這支除錯程式有一大堆優良的特點,and if you spend any time debugging stuff, you probably should check it out.先前編譯(precompiled)好的Linux版與修正版(patches)的原始碼可以在ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/找到.而最初的原始程式則放在 ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z.
你可能會發現另一個用來除錯的工具strace,也是相當的有用.它可以顯示出由程序(process)所產生的系統呼叫,而且還擁有其它眾多繁復的功能(multiplicity),像是假如你手邊沒有原始碼的話,strace可以幫你找出(figure out)有那些路徑(path-names)已編譯進執行檔(binaries)內; exacerbating race conditions in programs that you suspect contain them;還有,strace可拿來學習程式是怎麼在電腦中執行的.最新的版本(目前是3.0.8)可在找到 ftp://ftp.std.com/pub/jrs/. 5.2.3. 背景程式(Background (daemon) programs) 早期典型的常駐程式(daemon programs)是執行fork(),然後終止(terminate)父程序(parent).這樣的做法使得除錯的時間減短了. 了解(get around)這點的最簡單的方法就是替fork()設一個breakpoint.當程式停止時,強迫fork()傳回0.
(gdb) list 1 #include 2 3 main() 4 { 5 if(fork()==0) printf("child "); 6 else printf("parent "); 7 } (gdb) break fork Breakpoint 1 at 0x80003b8 (gdb) run Starting program: /home/dan/src/hello/./fork Breakpoint 1 at 0x400177c4
Breakpoint 1, 0x400177c4 in fork () (gdb) return 0 Make selected stack frame return now? (y or n) y #0 0x80004a8 in main () at fork.c:5 5 if(fork()==0) printf("child "); (gdb) next Single stepping until exit from function fork, which has no line number information. child 7 }
假如你想要有個多才多藝(versatility)的核心檔命名(core file naming)(for example, if you're trying to conduct a post-mortem using a debugger that's buggy itself) ,那麼你可以對你的核心程式(kernel)做一點小小的更動(mod).找一找fs/binfmt_aout.c與fs/binfmt_elf.c檔內與下列相符的程式片段(in newer kernels, you'll have to grep around a little in older ones): memcpy(corefile,"core.",5); #if 0 memcpy(corefile+5,current->comm,sizeof(current->comm)); #else corefile[4] = ''; #endif 將0換成1.
6. 連結(Linking) 由於靜態(static)與共享(shared)程式庫兩者間不相容的格式(incompatible binary formats)的差異性(distinction)與動詞*link*過量使用(overloading)於指稱*編譯完成後的事情*與*當編譯過的程式使用時(invoke)所發生的事情*這兩件事上頭,使得這一章節變得復雜了許多.( and, actually, the overloading of the word `load' in a comparable but opposite sense)不過,再復雜也就是這樣了,所以閣下不必過於擔心. 為了稍微減輕讀者的困惑,我們稱執行期間(runtime)所發生的事為*動態載入(dynamic loading)*,這一主題會在下一章節中談到.你也會在別的地方看到我把動態載入描述成*動態連結(dynamic linking)*,不過不會是在這一章節中.換句話說,這一章節所談的,全部是指發生在編譯結束後的連結(linking).
The DLL tool `mkimage' fails to find libgcc, or 從libc.so.4.5.x之後,libgcc已不再是共享的格式.因此,你必須在*-lgcc*出現之處以`gcc -print-libgcc-file-name`取代(完整的倒單引號(back-quotes)).另外,刪除所有/usr/lib/libgcc*的檔案.這點很重要哩.
Only presidents, editors, and people with tapeworms have the right to use the editorial ``we''. (Mark Twain)
這份HOWTO文件幾乎完全根植於Mitchum Dsouza的GCC-FAQ; 文件內大部份的資訊(not to mention a reasonable amount of the text)是直接來自於GCC-FAQ的. 這份HOWTO文件用到的第一人稱代名詞,可視為我們兩人其中一個;通常,要是有人說"我還沒有測試過這些;假如它燒了(toast)你的硬碟/系統/配偶,可別怪我!",那這樣的話適用於我倆身上. 對這份文件有貢獻的名人雅士如下所列(以名字的ASCII碼的順序): Andrew Tefft, Axel Boldt, Bill Metzenthen, Bruce Evans, Bruno Haible, Daniel Barlow, Daniel Quinlan, David Engel, Dirk Hohndel, Eric Youngdale, Fergus Henderson, H.J. Lu, Jens Schweikhardt, Kai Petzke, Michael Meissner, Mitchum DSouza, Olaf Flebbe, Paul Gortmaker, Rik Faith, Steven S. Dick, Tuomas J Lukka, 當然還有Linux Torvalds,沒有了他,這整個運動就會變得一點意義也沒有了,所以不可能讓他孤單的.:-)
9.3. 歡迎任何的回饋(Feedback) 寄信給我dan@detached.demon.co.uk.我的PGP public key (ID 5F263625) 可在我的烘培雞web pages上使用, 假如你覺得事情有必要保密的話.
9.4. 合法的行逕規定 All trademarks used in this document are acknowledged as being owned by their respective owners.
This document is copyright (C) 1996 Daniel Barlow It may be reproduced and distributed in whole or in part, in any medium physical or electronic, as long as this copyright notice is retained on all copies. Commercial redistribution is allowed and encouraged; however, the author would like to be notified of any such distributions.
All translations, derivative works, or aggregate works incorporating any Linux HOWTO documents must be covered under this copyright notice. That is, you may not produce a derivative work from a HOWTO and impose additional restrictions on its distribution. Exceptions to these rules may be granted under certain conditions; please contact the Linux HOWTO coordinator at the address given below.
In short, we wish to promote dissemination of this information through as many channels as possible. However, we do wish to retain copyright on the HOWTO documents, and would like to be notified of any plans to redistribute the HOWTOs.
If you have questions, please contact Greg Hankins, the Linux HOWTO coordinator, at gregh@sunsite.unc.edu via email.'