導航:首頁 > 源碼編譯 > frag文件編譯出錯

frag文件編譯出錯

發布時間:2022-11-26 23:12:35

㈠ 如何分析android的Log

首先,讓我們看一看AndroidLog的格式。下面這段log是以所謂的long格式列印出來的。從前面Logcat的介紹中可以知道,long格式會把時間,標簽等作為單獨的一行顯示。

[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]

Start procnet.coollet.infzmreader:umengService_v1 for service
net.coollet.infzmreader/com.umeng.message.

UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}

[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]

Turning on JNI app bug workarounds fortarget SDK version 8...

[ 12-09 21:39:35.611 21745:21745D/AgooService ]

onCreate()

我們以第一行為例:12-09 是日期,21:39:35.510是時間396是進程號,416是線程號;I代表log優先順序,ActivityManager是log標簽。

在應用開發中,這些信息的作用可能不是很大。但是在系統開發中,這些都是很重要的輔助信息。開發工程師分析的log很多都是由測試工程師抓取的,所以可能有些log根本就不是當時出錯的log。如果出現這種情況,無論你怎麼分析都不太可能得出正確的結論。如何能最大限度的避免這種情況呢?筆者就要求測試工程師報bug時必須填上bug發生的時間。這樣結合log里的時間戳信息就能大致判斷是否是發生錯誤時的log。而且根據測試工程師提供的bug發生時間點,開發工程師可以在長長的log信息中快速的定位錯誤的位置,縮小分析的范圍。

同時我們也要注意,時間信息在log分析中可能被錯誤的使用。例如:在分析多線程相關的問題時,我們有時需要根據兩段不同線程中log語句執行的先後順序來判斷錯誤發生的原因,但是我們不能以兩段log在log文件中出現的先後做為判斷的條件,這是因為在小段時間內兩個線程輸出log的先後是隨機的,log列印的先後順序並不完全等同於執行的順序。那麼我們是否能以log的時間戳來判斷呢?同樣是不可以,因為這個時間戳實際上是系統列印輸出log時的時間,並不是調用log函數時的時間。遇到這種情況唯一的辦法是在輸出log前,調用系統時間函數獲取當時時間,然後再通過log信息列印輸出。這樣雖然麻煩一點,但是只有這樣取得的時間才是可靠的,才能做為我們判斷的依據。

另外一種誤用log中時間戳的情況是用它來分析程序的性能。一個有多年工作經驗的工程師拿著他的性能分析結果給筆者看,但是筆者對這份和實際情況相差很遠的報告表示懷疑,於是詢問這位工程師是如何得出結論的。他的回答讓筆者很驚訝,他計算所採用的數據就是log信息前面的時間戳。前面我們已經講過,log前面時間戳和調用log函數的時間並不相同,這是由於系統緩沖log信息引起的,而且這兩個時間的時間差並不固定。所以用log信息前附帶的時間戳來計算兩段log間代碼的性能會有比較大的誤差。正確的方法還是上面提到的:在程序中獲取系統時間然後列印輸出,利用我們列印的時間來計算所花費的時間。

了解了時間,我們再談談進程Id和線程Id,它們也是分析log時很重要的依據。我們看到的log文件,不同進程的log信息實際上是混雜在一起輸出的,這給我們分析log帶來了很大的麻煩。有時即使是一個函數內的兩條相鄰的log,也會出現不同進程的log交替輸出的情況,也就是A進程的第一條log後面跟著的是B進程的第二條log,對於這樣的組合如果不細心分析,就很容易得出錯誤的結論。這時一定要仔細看log前面的進程Id,把相同Id的log放到一起看。

不同進程的log有這樣的問題,不同的線程輸出的log當然也存在著相同的問題。Logcat加上-vthread就能列印出線程Id。但是有一點也要引起注意,就是Android的線程Id和我們平時所講的linux線程Id並不完全等同。首先,在Android系統中,C++層使用的Linux獲取線程Id的函數gettid()是不能得到線程Id的,調用gettid()實際上返回的是進程Id。作為替代,我們可以調用pthread_self()得到一個唯一的值來標示當前的native線程。Android也提供了一個函數androidGetThreaId()來獲取線程Id,這個函數實際上就是在調用pthread_self函數。但是在java層線程Id又是另外一個值,Java層的線程Id是通過調用Thread的getId方法得到的,這個方法的返回值實際上來自Android在每個進程的java層中維護的一個全局變數,所以這個值和C++層所獲得的值並不相同。這也是我們分析log時要注意的問題,如果是Java層線程Id,一般值會比較小,幾百左右;如果是C++層的線程,值會比較大。在前裡面的log樣本中,就能很容易的看出,第一條log是Jave層輸出的log,第二條是native層輸出的。明白了這些,我們在分析log時就不要看見兩段log前面的線程Id不相同就得出是兩個不同線程log的簡單結論,還要注意Jave層和native層的區別,這樣才能防止被誤導。

AndroidLog的優先順序在列印輸出時會被轉換成V,I,D,W,E等簡單的字元標記。在做系統log分析時,我們很難把一個log文件從頭看到尾,都是利用搜索工具來查找出錯的標記。比如搜索「E/」來看看有沒有指示錯誤的log。所以如果參與系統開發的每個工程師都能遵守Android定義的優先順序含義來輸出log,這會讓我們繁重的log分析工作變得相對輕鬆些。

Android比較常見的嚴重問題有兩大類,一是程序發生崩潰;二是產生了ANR。程序崩潰和ANR既可能發生在java層,也可能發生在native層。如果問題發生在java層,出錯的原因一般比較容易定位。如果是native層的問題,在很多情況下,解決問題就不是那麼的容易了。我們先看一個java層的崩潰例子:

I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:
pid=1760 uid=10065 gids={50065, 1028}

D/AndroidRuntime( 1760): Shutting downVM

W/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)

E/AndroidRuntime( 1760): FATALEXCEPTION: main

E/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo
{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerException

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)

E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)

E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
(ZygoteInit.java:793)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)

E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)

E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerException

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)

E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)

E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)

E/AndroidRuntime( 1760): ... 11more

I/Process ( 1760): Sending signal.PID: 1760 SIG: 9

W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivity

Jave層的代碼發生crash問題時,系統往往會列印出很詳細的出錯信息。比如上面這個例子,不但給出了出錯的原因,還有出錯的文件和行數。根據這些信息,我們會很容易的定位問題所在。native層的crash雖然也有棧log信息輸出,但是就不那麼容易看懂了。下面我們再看一個native層crash的例子:

F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)

D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36ms

I/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocation

D/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34ms

I/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******

I/DEBUG ( 127):Build fingerprint:
'Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys'

I/DEBUG ( 127):Revision: '9'

I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<
I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000

I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000

I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2c

I/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1c

I/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030

I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8

I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08

I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8

I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78

I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000

I/DEBUG ( 127): d10 0000000000000000 d110000000000000000

I/DEBUG ( 127): d120000000000000000 d130000000000000000

I/DEBUG ( 127): d14 0000000000000000 d150000000000000000

I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fc

I/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000

I/DEBUG ( 127): d20 0000000000000000 d210000000000000000

I/DEBUG ( 127): d22 0000000000000000 d230000000000000000

I/DEBUG ( 127): d24 0000000000000000 d250000000000000000

I/DEBUG ( 127): d26 0000000000000000 d270000000000000000

I/DEBUG ( 127): d28 0000000000000000 d290000000000000000

I/DEBUG ( 127): d30 0000000000000000 d310000000000000000

I/DEBUG ( 127): scr 00000010

I/DEBUG ( 127):

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

I/DEBUG ( 127):

I/DEBUG ( 127):stack:

I/DEBUG ( 127): beb4aaa8 000000c8
I/DEBUG ( 127): beb4aaac 00000000
I/DEBUG ( 127): beb4aab0 00000000
I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linker

I/DEBUG ( 127): beb4aab8 00001000
I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testapp

I/DEBUG ( 127): beb4aac8 00000000
I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testapp

I/DEBUG ( 127): beb4aad0 beb4ab24 [stack]

I/DEBUG ( 127): beb4aad4 00000001
I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]

I/DEBUG ( 127): beb4aadc 00000000
I/DEBUG ( 127): beb4aae0 df0027ad
I/DEBUG ( 127): beb4aae4 00000000
I/DEBUG ( 127): #00 beb4aae8 00000000
I/DEBUG ( 127): ........ ........

I/DEBUG ( 127): #01 beb4aae8 00000000
I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)

I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]

I/DEBUG ( 127): beb4aaf4 00000000
I/DEBUG ( 127): beb4aaf8 00000000
I/DEBUG ( 127): beb4aafc 00000000
I/DEBUG ( 127): beb4ab00 00000000
I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testapp

I/DEBUG ( 127):

這個log就不那麼容易懂了,但是還是能從中看出很多信息,讓我們一起來學習如何分析這種log。首先看下面這行:

pid: 2102, tid: 2102,name: testapp >>>./testapp <<<
從這一行我們可以知道crash進程的pid和tid,前文我們已經提到過,Android調用gettid函數得到的實際是進程Id號,所以這里的pid和tid相同。知道進程號後我們可以往前翻翻log,看看該進程最後一次列印的log是什麼,這樣能縮小一點范圍。

接下來內容是進程名和啟動參數。再接下來的一行比較重要了,它告訴了我們從系統角度看,出錯的原因:

signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000

signal11是Linux定義的信號之一,含義是Invalidmemory reference,無效的內存引用。加上後面的「faultaddr 00000000」我們基本可以判定這是一個空指針導致的crash。當然這是筆者為了講解而特地製造的一個Crash的例子,比較容易判斷,大部分實際的例子可能就沒有那麼容易了。

再接下來的log列印出了cpu的所有寄存器的信息和堆棧的信息,這裡面最重要的是從堆棧中得到的backtrace信息:

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

因為實際的運行系統里沒有符號信息,所以列印出的log里看不出文件名和行數。這就需要我們藉助編譯時留下的符號信息表來翻譯了。Android提供了一個工具可以來做這種翻譯工作:arm-eabi-addr2line,位於prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目錄下。用法很簡單:

#./arm-eabi-addr2line -f -eout/target/proct/hammerhead/symbols/system/bin/testapp0x0000045e

參數-f表示列印函數名;參數-e表示帶符號表的模塊路徑;最後是要轉換的地址。這條命令在筆者的編譯環境中得到的結果是:

memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108

剩餘三個地址翻譯如下:

main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38

out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361

_start libgcc2.c:0

利用這些信息我們很快就能定位問題了。不過這樣手動一條一條的翻譯比較麻煩,筆者使用的是從網上找到的一個腳本,可以一次翻譯所有的行,有需要的讀者可以在網上找一找。

了解了如何分析普通的Log文件,下面讓我們再看看如何分析ANR的Log文件。

㈡ java裡面,想把一個String類型一維數組的某一個值傳遞給一個integer的變數,怎麼做

1、setRateId的參數是int類型嗎?
2、ginfRagRelate的類型正確嗎?可以在調用前 System.out.println(ginfRagRelate)看看它到底是啥類型

㈢ 如圖,這是vray材質,中文具體名稱是什麼

其實單詞可以分開看glsl是OpenGL著色語言(OpenGL Shading Language)是用來在OpenGL中著色編程的語言,網上搜索了下,據說是用來實時渲染用的。

找了好久,才把官方幫助網址找到了http://help.chaosgroup.com/vray/help/300R1/
3.0的沒有中文的。下面材質欄目里有解釋http://help.chaosgroup.com/vray/help/300R1/vrayglsltex.htm

沒事你慢慢看下吧,用網路翻譯了下,大致看下吧,呵呵

在VRayGLSLTex紋理貼圖可以用來載入GLSL著色器(.frag,.glsl文件)的V-Ray預編譯的片段著色器(.pfrag文件)或精神穆勒項目(.xmsl文件),並直接採用V-Ray渲染他們。如果將著色文件描述了一種材料(而不是一個紋理),它可以通過分配的紋理映射到的VRayLightMtl材料或者僅僅通過使用VRayGLSLMtl材料的色彩時隙中呈現。

如果心理廠項目文件中包含材料定義節點或者GLSL著色器文件描述已連接BRDFs的VRayGLSLTex紋理貼圖不會評價材料,並會呈現黑色的著色器。在這種情況下,VRayGLSLMtl材料應該被使用。既VRayGLSLMtl和VRayGLSLTex共享相同的用戶界面。

該紋理映射和材料是所述的V-Ray實施GLSL支持的第一階段。在這個版本中,著色器編譯成位元組代碼的軟體的虛擬機,然後將其進行解釋。由於這種運行時解釋,GLSL著色器可能有點慢渲染比用C
++編寫的V-Ray著色器。在未來的V-Ray版本,著色器將直接編譯成機器碼更快的渲染。

㈣ 網路ping程序在編譯執行時出錯 部分1

叔叔,抱歉,太復雜,我不知道誒,不過別的問題還可以,真的很抱歉!不過你可以參考下面這篇文章,這也許會對你有幫助。
ping程序:C語言實現Ping程序功能
來源: 發布時間:星期四, 2008年9月25日 瀏覽:77次 評論:0
大部分人用ping命令只是作為查看另一個系統的網路連接是否正常的一種簡單方法。在這篇文章中,作者將介紹如何用C語言編寫一個模擬ping命令功能的程序。

ping命令是用來查看網路上另一個主機系統的網路連接是否正常的一個工具。ping命令的工作原理是:向網路上的另一個主機系統發送ICMP報文,如果指定系統得到了報文,它將把報文一模一樣地傳回給發送者,這有點象潛水艇聲納系統中使用的發聲裝置。

例如,在Linux終端上執行ping localhost命令將會看到以下結果:
PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=112 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=79 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=255 time=78 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=255 time=82 usec

--- localhost.localdomain ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/mdev = 0.078/0.087/0.112/0.018 ms

由上面的執行結果可以看到,ping命令執行後顯示出被測試系統主機名和相應IP地址、返回給當前主機的ICMP報文順序號、ttl生存時間和往返時間rtt(單位是毫秒,即千分之一秒)。要寫一個模擬ping命令,這些信息有啟示作用。

要真正了解ping命令實現原理,就要了解ping命令所使用到的TCP/IP協議。

ICMP(Internet Control Message,網際控制報文協議)是為網關和目標主機而提供的一種差錯控制機制,使它們在遇到差錯時能把錯誤報告給報文源發方。ICMP協議是IP層的一個協議,但是由於差錯報告在發送給報文源發方時可能也要經過若乾子網,因此牽涉到路由選擇等問題,所以ICMP報文需通過IP協議來發送。ICMP數據報的數據發送前需要兩級封裝:首先添加ICMP報頭形成ICMP報文,再添加IP報頭形成IP數據報。如下圖所示

IP報頭
ICMP報頭
ICMP數據報

IP報頭格式
由於IP層協議是一種點對點的協議,而非端對端的協議,它提供無連接的數據報服務,沒有埠的概念,因此很少使用bind()和connect()函數,若有使用也只是用於設置IP地址。發送數據使用sendto()函數,接收數據使用recvfrom()函數。IP報頭格式如下圖:

在Linux中,IP報頭格式數據結構()定義如下:
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};

其中ping程序只使用以下數據:

IP報頭長度IHL(Internet Header Length)――以4位元組為一個單位來記錄IP報頭的長度,是上述IP數據結構的ip_hl變數。
生存時間TTL(Time To Live)――以秒為單位,指出IP數據報能在網路上停留的最長時間,其值由發送方設定,並在經過路由的每一個節點時減一,當該值為0時,數據報將被丟棄,是上述IP數據結構的ip_ttl變數。

ICMP報頭格式
ICMP報文分為兩種,一是錯誤報告報文,二是查詢報文。每個ICMP報頭均包含類型、編碼和校驗和這三項內容,長度為8位,8位和16位,其餘選項則隨ICMP的功能不同而不同。

Ping命令只使用眾多ICMP報文中的兩種:\"請求回送\'(ICMP_ECHO)和\"請求回應\'(ICMP_ECHOREPLY)。在Linux中定義如下:
#define ICMP_ECHO 0
#define ICMP_ECHOREPLY 8

這兩種ICMP類型報頭格式如下:

在Linux中ICMP數據結構()定義如下:
struct icmp
{
u_int8_t icmp_type; /* type of message, see below */
u_int8_t icmp_code; /* type sub code */
u_int16_t icmp_cksum; /* ones complement checksum of struct */
union
{
u_char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* gateway address */
struct ih_idseq /* echo datagram */
{
u_int16_t icd_id;
u_int16_t icd_seq;
} ih_idseq;
u_int32_t ih_void;

/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu
{
u_int16_t ipm_void;
u_int16_t ipm_nextmtu;
} ih_pmtu;

struct ih_rtradv
{
u_int8_t irt_num_addrs;
u_int8_t irt_wpa;
u_int16_t irt_lifetime;
} ih_rtradv;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa

㈤ shader文件怎麼創建

學習方法

(1)由簡入繁:自己寫Shader,從最簡單寫起,簡單的測試通過了,再一點點往裡加。
(2)多調試:例如,有一個float變數x。假如x范圍是[0,1],則在frag片段函數里輸出 float4(x,0,0,1)的顏色,以紅色的深淺來觀察x的值;如果x范圍是[0,1000],則可在frag片段函數里輸出 float4(x/1000,0,0,1)的顏色。方法就這么簡單,具體根據需要去調整。
(3)結合查看UnityCG.cginc等文件,以及unity的自帶Shader,即Build-in Shader。
Build-in Shader下載地址
(4)看看書:建議看本教程的同時,多看看書。推薦英文的The CG Tutorial,也就是中文版的Cg教程_可編程實時圖形權威指南
相關教材鏈接

學習小技巧
(1)查看UnityCG.cginc等文件
使用Vertex and Fragment的CG時,會#include "UnityCG.cginc",用到裡面的很多函數,如TRANSFORM_TEX,UNITY_TRANSFER_DEPTH等函數的定義。那麼怎麼查看這些定義呢?

windows路徑:Unity\Editor\Data\CGIncludes
mac路徑:右鍵點擊unity圖標->show contents->Data->CGIncludes
文件夾下有Unity關於Shader的庫,如UnityCG.cginc,UnityCG.glslinc,Lighting.cginc等。打開
UnityCG.cginc(寫字板MONODev等均可),後即可查看相關函數的定義。

(2)電子書的學習技巧
中文電子書,學起來快,好理解,但大多數是影印版。
英文電子書,可以很好的用關鍵詞搜索知識點。

(3)使用#prama only_renderers d3d9 , 限定編譯平台。(3)(4)配合使用效果更好

(4)打開編譯後的Shader,查看對應的匯編代碼或者OpenGL ES代碼。
方法:左鍵單機shader文件,然後在Inspector面板里點擊Open Compiled Shader.

㈥ Linux日誌式文件系統面面觀

文件系統是用來管理和組織保存在磁碟驅動器上的數據的系統軟體,其實現了數據完整性的保 證,也就是保證寫入磁碟的數據和隨後讀出的內容的一致性。除了保存以文件方式存儲的數據以外,一個文件系統同樣存儲和管理關於文件和文件系統自身的一些重要信息(例如:日期時間、屬主、訪問許可權、文件大小和存儲位置等等)。這些信息通常被稱為元數據(metadata)。

由於為了避免磁碟訪問瓶頸效應,一般文件系統大都以非同步方式工作,因此如果磁碟操作被突然中斷可能導致數據被丟失。例如如果出現這種情況:如果當你處理一個在linux的ext2文件系統上的文檔,突然機器崩潰會出現什麼情況?

有這幾種可能:

*當你保存文件以後,系統崩潰。這是最好的情況,你不會丟失任何信息。只需要重新啟動計算機然後繼續工作。

*在你保存文件之前系統崩潰。你會丟失你所有的工作內容,但是老版本的文檔還會存在。

*當正在將保存的文檔寫入磁碟時系統崩潰。這是最糟的情況:新版文件覆蓋了舊版本的文件。這樣磁碟上只剩下一個部分新部分舊的文件。如果文件是二進制文件那麼就會出現不能打開文件的情況,因為其文件格式和應用所期待的不同。

在最後這種情況下,如果系統崩潰是發生在驅動器正在寫入元數據時,那麼情況可能更糟。這時候就是文件系統發生了損壞,你可能會丟失整個目錄或者整個磁碟分區的數據。

linux標准文件系統(ext2fs)在重新啟動時會通過調用文件掃描工具fsck試圖恢復損壞的元數據信息。由於ext2文件系統保存有冗餘的關鍵元數據信息的備份,因此一般來說不大可能出現數據完全丟失。系統會計算出被損壞的數據的位置,然後或者是通過恢復冗餘的元數據信息,或者是直接刪除被損壞或是元數據信息損毀的文件。

很明顯,要檢測的文件系統越大,檢測過程費時就越長。對於有幾十個G大小的分區,可能會花費很長時間來進行檢測。由於Linux開始用於大型伺服器中越來越重要的應用,因此就越來越不能容忍長時間的當機時間。這就需要更復雜和精巧的文件系統來替代ext2。

因此就出現了日誌式文件系統(journalling filesystems)來滿足這樣的需求。

什麼是日誌式文件系統

這里僅僅對日誌式文件系統進行簡單的說明。如果需要更深入的信息請參考文章日誌式文件系統,或者是日誌式文件系統介紹。

大多數現代文件系統都使用了來自於資料庫系統中為了提高崩潰恢復能力而開發的日誌技術。磁碟事務在被真正寫入到磁碟的最終位置以前首先按照順序方式寫入磁碟中日誌區(或是log區)的特定位置。

根據日誌文件系統實現技術的不同,寫入日誌區的信息是不完全一樣的。某些實現技術僅僅寫文件系統元數據,而其他則會記錄所有的寫操作到日誌中。

現在,如果崩潰發生在日誌內容被寫入之前發生,那麼原始數據仍然在磁碟上,丟失的僅僅是最新的更新內容。如果當崩潰發生在真正的寫操作時(也就是日誌內容已經更新),日誌文件系統的日誌內容則會顯示進行了哪些操作。因此當系統重啟時,它能輕易根據日誌內容,很快地恢復被破壞的更新。

在任何一種情況下,都會得到完整的數據,不會出現損壞的分區的情況。由於恢復過程根據日誌進行,因此整個過程會非常快只需要幾秒鍾時間。

應該注意的是使用日誌文件系統並不意味著完全不需要使用文件掃描工具fsck了。隨機發生的文件系統的硬體和軟體錯誤是根據日誌是無法恢復的,必須藉助於fsck工具。

目前Linux環境下的日誌文件系統

在下面的內容里將討論三種日誌文件系統:第一種是ext3,由Linux內核Stephen Tweedie開發。ext3是通過向ext2文件系統上添加日誌功能來實現的,目前是redhat7.2的默認文件系統;Namesys開發的ReiserFs日誌式文件系統,可以下載,目前Mandrake8.1採用該日誌式文件系統。SGI在2001年三月發布了XFS日誌式文件系統。可以在 oss.sgi.com/projects/xfs/下載。下面將對這三種日誌文件系統採用不同的工具進行檢測和性能測試。

安裝ext3

關於ext3文件系統技術方面的問題請參考Dr. Stephen Tweedie的論文和訪談。ext3日誌式文件系統直接來自於其祖先ext2文件系統。其具有完全向後兼容的關鍵特性,實際上其僅僅是在ext2日誌式文件系統上添加了日誌功能。其最大的缺點是沒有現代文件系統所具有的能提高文件數據處理速度和解壓的高性能。

ext3從 2.2.19開始是作為一個補丁方式存在的。如果希望對內核添加對ext3文件系統的支持,就需要使用補丁,可以得到補丁程序,一共需要如下文件:

* ext3-0.0.7a.tar.bz2:內核補丁

* e2fsprogs-1.21-WIP-0601.tar.bz2 支持ext3的e2fsprogs程序套件

拷貝linux-2.2.19.tar.bz2和ext3-0.0.7a.tar.bz2到/usr/src目錄下,進行解壓:

mv linux linux-old

tar -Ixvf linux-2.2.19.tar.bz2

tar -Ixvf ext3-0.0.7a.tar.bz2

cd linux

cat ../ext3-0.0.7a/linux-2.2.19.kdb.diff | patch -sp1

cat ../ext3-0.0.7a/linux-2.2.19.ext3.diff | patch -sp1

首先對內核添加SGI的kdb內核調試器補丁,第二個是ext3文件系統補丁。下來就需要配置內核,對文件系統部分的"Enable Second extended fs development code"回答Yes。然後編譯。

內核編譯安裝以後,需要安裝e2fsprogs軟體套件:

tar -Ixvf e2fsprogs-1.21-WIP-0601.tar.bz2

cd e2fsprogs-1.21

./configure

make

make check

make install

下來要做的工作就是在分區上創建一個ext3文件系統,使用新內核重新啟動,這時候你有兩種選擇創建新的日誌文件系統或者對一個已有的ext2文件系統升級到ext3日誌文件系統。

對於需要創建新ext3文件系統的情況下,只需要使用安裝的e2fsprogs軟體包中的mke2fs命令加-f參數就可以創建新的ext3文件系統:

mke2fs -j /dev/xxx

這里/dev/xxx是希望創建ext3文件系統的新分區。-j參數表示創建ext3而不是ext2文件系統。可以使用參數"-Jsize="來指定希望的日誌區大小(n單位為M)。

升級一個已有的ext2,使用tune2fs就可以了:

tune2fs -j /dev/xxx

你可以對正在載入的文件系統和沒有載入的文件系統進行升級操作。如果當前文件系統正在被載入,則文件.journal會在文件系統載入點的所在目錄被創建。如果是升級一個當時沒有載入的文件系統,則使用隱含的系統inode來記錄日誌,這時候文件系統的所有內容都會被保留不被破壞。

你可以使用下面的命令載入ext3文件系統:

mount -t ext3 /dev/xxx /mount_dir

由於ext3實際上是帶有日誌功能的ext2文件系統 ,因此一個ext3文件系統可以以ext2的方式被載入。

安裝XFS文件系統

如果需要從技術方面了解XFS文件系統,請參考SGI的XFS文件系統和SGI信息頁面。也可以參考FAQ。

XFS是一個SGI開發的linux環境下的日誌文件系統,它是一個成熟的技術,最初是使用在IRIX系統上的文件系統。XFS遵循GPL版權申明。目前xfs文件系統最新版本是1.02。下載得到對內核xfs文件系統支持補丁或者直接下載RPM包方式的內核,下面我們就以補丁方式說明如何對2.4.14內核使用xfs。首先下載如下內容

patch-2.4.14-xfs-1.0.2.bz2

patch-2.4.14-xfs-1.0.2-kdb.bz2

拷貝Linux內核linux-2.4.2.tar.bz2到 /usr/src目錄下,修改老的內核目錄名,然後解壓新內核:

mv linux linux-old

tar -Ixf inux-2.4.2.tar.bz2

拷貝每個每個補丁到內核源碼目錄下(例如:/usr/src/linux),並打補丁:

zcat patch-2.4.14-xfs-1.0.2.bz2 | patch -p1

zcat patch-2.4.14-xfs-1.0.2-kdb.bz2 | patch -p1

然後配置內核,打開文件系統部分的內核選項:"XFS filesystem support" (CONFIG_XFS_FS)和"Page Buffer support" (CONFIG_PAGE_BUF)。同時需要升級下面這些系統工具到下面或更高的版本:

motils-2.4.0

autoconf-2.13

e2fsprogs-devel-1.18

安裝新內核並重啟伺服器。

然後下載xfs工具。這個軟體包包括下面的命令來處理文件系統,使用下面的命令來安裝該軟體包::

tar -zxf xfsprogs-1.2.0.src.tar.gz

cd xfsprogs-1.2.0

make configure

make

make install

安裝這些命令以後,就可以創建新的XFS文件系統:

mkfs -t xfs /dev/xxx

如果xxx是一個已經存在的文件系統,那麼就需要使用"-f"參數來創建新分區,但是記得這將會破壞該分區的所有數據。

mkfs -t xfs -f /dev/xxx

創建以後就可以使用基於下面的命令載入新文件系統:

mount -t xfs /dev/xxx /mount_dir

安裝ReiserFS文件系統

如果希望更多地從技術方面了解reiserFS文件系統,請參考NAMESYS和FAQ。

ReiserFS文件系統從2.4.1-pre4開始就是Linux內核的正式支持的文件系統了。為了使用reiserFS文件系統那你首先需要在系統上安裝文件系統支持工具(如:創建ReiserFS文件系統的mkreiserfs工具)。最新的ReiserFS文件系統版本可以以補丁的方式添加到2.2.x或者2.4.x內核中。這里我們以2.2.19為例:

第一步,首先下在內核源碼,並下在ReiserFS文件系統的2.2.19補丁 ,目前補丁最新版本是linux-2.2.19-reiserfs-3.5.34-patch.bz2。同時應該下載工具軟體包:reiserfsprogs-3.x.0j.tar.gz。

然後解壓內核源碼和補丁包到/usr/src中:

tar -Ixf linux-2.2.19.tar.bz2

bzcat linux-2.2.19-reiserfs-3.5.34-patch.bz2 | patch -p0

編譯內核支持reiserfs,安裝內核。然後安裝文件系統工具軟體:

cd /usr/src/linux/fs/reiserfs/utils

make

make install

安裝新內核並重新啟動。現在就可以創建新的'reiserfs文件系統,並載入:

mkreiserfs /dev/xxxx

mount -t reiserfs /dev/xxx /mount_dir

文件系統性能測試

測試環境使用的計算機環境如下:Pentium III - 16 Mb RAM - 2 Gb HD,操作系統為RedHat6.2。所有的文件系統都能正常工作,所以就進行benchmark分析來對它們進行性能比較。首先我直接拔掉系統電源以模擬系統掉電情況,以測試日誌文件系統恢復過程。所有的文件系統都成功地經過了文件掃描檢測階段,在數秒以後系統都經過了掃描然後正常啟動了系統。

下一步就採用了bonnie++性能測試程序進行測試,這個程序對一個文件進行資料庫類型的訪問,進行了創建、讀和刪除小文件,這些操作對於Squid、INN或者Maildir格式的郵件伺服器程序(qmail)是最常見的操作。性能測試命令為:

bonnie++ -d/work1 -s10 -r4 -u0

其對載入在/work1目錄下的文件系統進行了10Mb(-s10)的測試。因此在執行測試之前必須創建適當類型的文件系統並載入到目錄/work1下。其他的參數指定內存大小(-r4)的M數,和以root身份運行測試程序,測試結果如下:

每種測試都有兩組數據:文件系統速度(K/sec)和CPU佔用率(%CPU)。速度越高,文件系統越好。而對於CPU率來說,數字越小性能越好。可以看到Reiserfs文件系統在文件操作方面(Sequential Create和Random Create部分的) 的性能最好,超出其他文件系統10倍之多。在其他方面(Sequential Output和Sequential Input)則和其他文件系統性能不相上下。對於其他文件系統則沒有特別明顯的區別。XFS性能接近ext2文件系統,ext3文件系統則比ext2要稍微慢上一些(因為記錄日誌需要一些額外的時間)。 最後使用從得到的性能測試程序mongo,並對其進行了修改以對三種日誌文件系統進行測試。這里在mongo.pl程序中添加了添加了載入xfs和ext3文件系統的命令,並對其進行格式化處理,然後就開始性能測試分析。 該腳本格式劃分區/dev/xxxx,載入其並在每個階段運行指定數目的進程:創建、拷貝、符號連接處理、讀、顯示文件狀態信息、重命名和刪除文件。同時,該程序在創建和拷貝階段以後會計算分段數(fragmentation)。

Fragm = number_of_fragments / number_of_files

可以在結果文件中得到同樣的測試比較結果:

log - 原始結果

log.tbl - 比較程序的輸出結果

log_table - 表格式的結果

下面的命令進行測試:

mongo.pl ext3 /dev/hda3 /work1 logext3 1

如果要測試其他文件系統,就需要把上面命令的參數中的ext3修改為reiserfs或xfs。其他參數分別為要載入的分區,載入路徑,保存測試結果的文件名及啟動的進程數。

下面的表格是測試結果。數據單位為秒。值越低性能越好。第一個表格測試使用的數據塊大小為100位元組,第二個表格為1000位元組,最後一個為10000位元組

從上面的表格可以看到ext3在狀態刪除和重命名方面要性能更好一些,而ReiserFS文件系統在文件創建和拷貝性能表現更出色。同時也可以看到reiserFS正如其技術文檔提到的其在小文件處理方面性能相當出色。

結論

目前Linux至少有兩個健壯可靠的日誌文件系統可供選擇(XFS和reiserFS),其都得到了廣泛的應用。例如Mandrake8.1就默認支持reiserFS文件系統。

從性能測試的結果可以看到,reiserFS是最好的選擇。

㈦ /proc文件系統的作用

理解 Proc 文件系統

--------------------------------------------------------------------------------

作者:王旭 翻譯 2004-10-05 18:25:55 來自:linuxfocus

目錄:
/proc --- 一個虛擬文件系統
載入 proc 文件系統
察看 /proc 的文件
得到有用的系統/內核信息
有關運行中的進程的信息
通過 /proc 與內核交互
結論
參考文獻

摘要:

Linux 內核提供了一種通過 /proc 文件系統,在運行時訪問內核內部數據結構、改變內核設置的機制。盡管在各種硬體平台上的 Linux 系統的 /proc 文件系統的基本概念都是相同的,但本文只討論基於 intel x86 架構的 Linux /proc 文件系統。

_________________ _________________ _________________

/proc --- 一個虛擬文件系統
/proc 文件系統是一種內核和內核模塊用來向進程 (process) 發送信息的機制 (所以叫做 /proc)。這個偽文件系統讓你可以和內核內部數據結構進行交互,獲取 有關進程的有用信息,在運行中 (on the fly) 改變設置 (通過改變內核參數)。 與其他文件系統不同,/proc 存在於內存之中而不是硬碟上。如果你察看文件 /proc/mounts (和 mount 命令一樣列出所有已經載入的文件系統),你會看到其中 一行是這樣的:

grep proc /proc/mounts
/proc /proc proc rw 0 0

/proc 由內核控制,沒有承載 /proc 的設備。因為 /proc 主要存放由內核控制的狀態信息,所以大部分這些信息的邏輯位置位於內核控制的內存。對 /proc 進行一次 'ls -l' 可以看到大部分文件都是 0 位元組大的;不過察看這些文件的時候,確實可以看到一些信息。這怎麼可能?這是因為 /proc 文件系統和其他常規的文件系統一樣把自己注冊到虛擬文件系統層 (VFS) 了。然而,直到當 VFS 調用它,請求文件、目錄的 i-node 的時候,/proc 文件系統才根據內核中的信息建立相應的文件和目錄。

載入 proc 文件系統
如果系統中還沒有載入 proc 文件系統,可以通過如下命令載入 proc 文件系統:

mount -t proc proc /proc

上述命令將成功載入你的 proc 文件系統。更多細節請閱讀 mount 命令的 man page。

察看 /proc 的文件
/proc 的文件可以用於訪問有關內核的狀態、計算機的屬性、正在運行的進程的狀態等信息。大部分 /proc 中的文件和目錄提供系統物理環境最新的信息。盡管 /proc 中的文件是虛擬的,但它們仍可以使用任何文件編輯器或像'more', 'less'或 'cat'這樣的程序來查看。當編輯程序試圖打開一個虛擬文件時,這個文件就通過內核中的信息被憑空地 (on the fly) 創建了。這是一些我從我的系統中得到的一些有趣結果:

$ ls -l /proc/cpuinfo
-r--r--r-- 1 root root 0 Dec 25 11:01 /proc/cpuinfo

$ file /proc/cpuinfo
/proc/cpuinfo: empty

$ cat /proc/cpuinfo

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 8
model name : Pentium III (Coppermine)
stepping : 6
cpu MHz : 1000.119
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
sep_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
cmov pat pse36 mmx fxsr xmm
bogomips : 1998.85

processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 8
model name : Pentium III (Coppermine)
stepping : 6
cpu MHz : 1000.119
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
sep_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
cmov pat pse36 mmx fxsr xmm
bogomips : 1992.29

這是一個從雙 CPU 的系統中得到的結果,上述大部分的信息十分清楚地給出了這個系統的有用的硬體信息。有些 /proc 的文件是經過編碼的,不同的工具可以被用來解釋這些編碼過的信息並輸出成可讀的形式。這樣的工具包括:'top', 'ps', 'apm' 等。

得到有用的系統/內核信息

proc 文件系統可以被用於收集有用的關於系統和運行中的內核的信息。下面是一些重要的文件:

/proc/cpuinfo - CPU 的信息 (型號, 家族, 緩存大小等)
/proc/meminfo - 物理內存、交換空間等的信息
/proc/mounts - 已載入的文件系統的列表
/proc/devices - 可用設備的列表
/proc/filesystems - 被支持的文件系統
/proc/moles - 已載入的模塊
/proc/version - 內核版本
/proc/cmdline - 系統啟動時輸入的內核命令行參數
proc 中的文件遠不止上面列出的這么多。想要進一步了解的讀者可以對 /proc 的每一個文件都'more'一下或讀參考文獻[1]獲取更多的有關 /proc 目錄中的文件的信息。我建議使用'more'而不是'cat',除非你知道這個文件很小,因為有些文件 (比如 kcore) 可能會非常長。

有關運行中的進程的信息
/proc 文件系統可以用於獲取運行中的進程的信息。在 /proc 中有一些編號的子目錄。每個編號的目錄對應一個進程 id (PID)。這樣,每一個運行中的進程 /proc 中都有一個用它的 PID 命名的目錄。這些子目錄中包含可以提供有關進程的狀態和環境的重要細節信息的文件。讓我們試著查找一個運行中的進程。

$ ps -aef | grep mozilla
root 32558 32425 8 22:53 pts/1 00:01:23 /usr/bin/mozilla

上述命令顯示有一個正在運行的 mozilla 進程的 PID 是 32558。相對應的,/proc 中應該有一個名叫 32558 的目錄

$ ls -l /proc/32558
total 0
-r--r--r-- 1 root root 0 Dec 25 22:59 cmdline
-r--r--r-- 1 root root 0 Dec 25 22:59 cpu
lrwxrwxrwx 1 root root 0 Dec 25 22:59 cwd -> /proc/
-r-------- 1 root root 0 Dec 25 22:59 environ
lrwxrwxrwx 1 root root 0 Dec 25 22:59 exe -> /usr/bin/mozilla*
dr-x------ 2 root root 0 Dec 25 22:59 fd/
-r--r--r-- 1 root root 0 Dec 25 22:59 maps
-rw------- 1 root root 0 Dec 25 22:59 mem
-r--r--r-- 1 root root 0 Dec 25 22:59 mounts
lrwxrwxrwx 1 root root 0 Dec 25 22:59 root -> //
-r--r--r-- 1 root root 0 Dec 25 22:59 stat
-r--r--r-- 1 root root 0 Dec 25 22:59 statm
-r--r--r-- 1 root root 0 Dec 25 22:59 status

文件 "cmdline" 包含啟動進程時調用的命令行。"envir" 進程的環境變兩。 "status" 是進程的狀態信息,包括啟動進程的用戶的用戶ID (UID) 和組ID(GID) ,父進程ID (PPID),還有進程當前的狀態,比如"Sleelping"和"Running"。每個進程的目錄都有幾個符號鏈接,"cwd"是指向進程當前工作目錄的符號鏈接,"exe"指向運行的進程的可執行程序,"root"指向被這個進程看作是根目錄的目錄 (通常是"/")。目錄"fd"包含指向進程使用的文件描述符的鏈接。 "cpu"僅在運行 SMP 內核時出現,裡面是按 CPU 劃分的進程時間。

/proc/self 是一個有趣的子目錄,它使得程序可以方便地使用 /proc 查找本進程地信息。/proc/self 是一個鏈接到 /proc 中訪問 /proc 的進程所對應的 PID 的目錄的符號鏈接。

通過 /proc 與內核交互

上面討論的大部分 /proc 的文件是只讀的。而實際上 /proc 文件系統通過 /proc 中可讀寫的文件提供了對內核的交互機制。寫這些文件可以改變內核的狀態,因而要慎重改動這些文件。/proc/sys 目錄存放所有可讀寫的文件的目錄,可以被用於改變內核行為。

/proc/sys/kernel - 這個目錄包含反通用內核行為的信息。 /proc/sys/kernel/{domainname, hostname} 存放著機器/網路的域名和主機名。這些文件可以用於修改這些名字。

$ hostname
machinename.domainname.com

$ cat /proc/sys/kernel/domainname
domainname.com

$ cat /proc/sys/kernel/hostname
machinename

$ echo "new-machinename" > /proc/sys/kernel/hostname

$ hostname
new-machinename.domainname.com

這樣,通過修改 /proc 文件系統中的文件,我們可以修改主機名。很多其他可配置的文件存在於 /proc/sys/kernel/。這里不可能列出所有這些文件,讀者可以自己去這個目錄查看以得到更多細節信息。
另一個可配置的目錄是 /proc/sys/net。這個目錄中的文件可以用於修改機器/網路的網路屬性。比如,簡單修改一個文件,你可以在網路上癮藏匿的計算機。

$ echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

這將在網路上癮藏你的機器,因為它不響應 icmp_echo。主機將不會響應其他主機發出的 ping 查詢。

$ ping machinename.domainname.com
no answer from machinename.domainname.com

要改回預設設置,只要

$ echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all

/proc/sys 下還有許多其它可以用於改變內核屬性。讀者可以通過參考文獻 [1], [2] 獲取更多信息。

結論
/proc 文件系統提供了一個基於文件的 Linux 內部介面。它可以用於確定系統的各種不同設備和進程的狀態。對他們進行配置。因而,理解和應用有關這個文件系統的知識是理解你的 Linux 系統的關鍵。

參考文獻

[1] 有關Linux proc 文件系統的文檔位於: /usr/src/linux/Documentation/filesystems/proc.txt

[2] RedHat Guide: The /proc File System: http://www.redhat.com/docs/manuals/linux/RHL-7.3-Manual/ref-guide/ch-proc.html

㈧ 建立UT伺服器

UT2003伺服器架設指南

做伺服器前先到:
http://www.unrealtournament2003.com/...atedserver.php
下載伺服器版UT2003,(v2107, Windows: 265MB | Linux: 249MB)安裝需要780M硬碟空間。
http://ut2003master.epicgames.com/ut...rver/cdkey.php
申請伺服器專用CD-KEY

下載伺服器安裝文件後:
linux用戶:新建一個用戶帳號專門用來運行伺服器,用這個用戶登錄,運行ut2003lnxded.sh.bin文件。跟具屏幕提示繼續。
windows用戶:把zip文件解壓縮到硬碟中,沒有安裝程序,解開來就行了。

在配置伺服器前先下載最新升級補丁,給伺服器程序升級。
再下載evolutionpack2,它能幫你解決許多用web頁面管理上面的問題,和修正了一些bug。
http://unreal.cpgl.net/UT2003/patch/evolutionpack2.zip 20KB

安裝伺服器:

在你下載完並解壓縮所有需要的文件後:

A 如果你已經在機器上裝了零售版UT2003,那麼跳到第M條
B 如果你下載了免費的伺服器專用程序,且不需要再申請伺服器專用cdkey,那麼跳到第D條
C 如果你是使用零售版UT2003來運行伺服器的話,那先安裝游戲,游戲會自動添加註冊表中必要的信息。跳到第M條。
D 打開 http://ut2003master.epicgames.com/ut...rver/cdkey.php ,輸入一些需要的信息後,伺服器專用CDkey會通過email發給你。linux用戶需要把收到的cdkey文件復制到你的系統文件夾中
E 如果你已經知道怎麼在注冊表裡添加CDKEY就跳過這一步到J。
F 點擊開始--->運行。在窗口中輸入 regedit ,回車。
G 在注冊表管理器中,雙擊"HKEY_LOCALMACHINE"展開它,雙擊"software"展開它,在它下面找到"Unreal Technology"文件夾.如果這個文件夾已經存在,跳到J。
H 添加一個新的鍵值。單擊"software"文件夾,然後點編輯--->新建--->主鍵。一個新的文件夾就出現了,有一個高亮的區域讓你給它命名,輸入Unreal Technology 回車。
I 單擊剛才新建的文件夾,點編輯--->新建--->主鍵。一個新的文件夾出現啦,又有一個高亮的區域讓你命名,輸入 Install Apps 回車,跳到K。
J 在Unreal Technology Installed apps文件夾下找到"UT2003"文件夾,如果它存在,跳到L
K 單擊"Installed Apps"文件夾,點編輯--->新建--->主鍵。一個嶄新的文件夾誕生啦,有一個高亮的區域讓我們命名,輸入UT2003 回車。
L 單擊"UT2003"文件夾,點編輯--->新建--->建值。一個新的文件夾又出現啦,又有一個高亮的區域可以讓我們起名字啦。輸入 "CDKEY",回車。雙擊新建立的鍵值,你就可以編輯它的值。在裡面輸入你的cdkey序列號。點OK。關掉注冊表編輯器。
M 如果你知道怎麼用命令行命令進入你的虛幻安裝文件夾里的system文件夾,跳到步驟O
N 用命令行建立伺服器。我把我的文件安裝在UT2003server,我用這個舉例子,輸入cd ut2003server\system
O 輸入ucc server DM-Antalus.ut2

如果一切順利,一個專用伺服器就架設好了,游戲中的地圖是DM-Antalus。
默認下面,專用伺服器的配置是給internet游戲配置的。這意味著它他嘗試和國外的主伺服器聯系把它加入到主伺服器的資料庫里,這樣你的伺服器就可以出現在別人的伺服器搜索列表裡。目前有兩個不同的主伺服器在運行,Epic的和Gamespy的。

如果你在機器上已經安裝了零售版的UT2003,那就不必運行Epic mail給你的.reg文件了,否則你注冊表裡的CDKEY會被改成伺服器專用的,這樣你自己就不能用這台機器玩了。

如果你是在居域網里建立伺服器,並且想禁止UT2003和主伺服器聯系那就編輯UT2003.ini里修改下面的句子(如果找不到這部分,就在最後加後這幾行):
[IpDrv.MasterServerUplink]
DoUplink=False
UplinkToGamespy=False

配置伺服器
現在你應該知道最基本的架設伺服器的方法了,你需要把它配置成你需要的。下面的每個部分都有詳細的常見問題解答

System 文件夾里有最重要的三個文件:user.ini runserver.bat和ut2003.ini 。 user.ini保存了地圖循環列表。ut2003.ini保存了許多其他設置。runserver.bat 保存了啟動伺服器的設置。Linux用戶沒有runserver.bat文件,你要把每次都輸入一長串命令啟動伺服器,或者你必須用一個外殼腳本啟動伺服器。(linux上用腳本啟動UT2003伺服器的例子參見http://www.ina- community.com/forums/showthread.php?s=&threadid=231043)
如果你架設多個伺服器,通常你會使用一個共同的ut2003.ini文件,然後用不同的runserver.bat或者外殼腳本啟動不同的伺服器,下面是一個runserver.bat的例子:
ucc.exe server DM-Antalus?game=XGame.XDeathmatch?maxplayers=16?minplayers=4?timelimit=20?fraglimit=25

ucc.exe 是伺服器的執行文件,"server"告訴uccc下面要架設一個專用伺服器。後面的東西是一些參數,設置伺服器的游戲規則。第一條是伺服器初始游戲的地圖名字,這個例子中是DM-Antalus。跟著是游戲類型,例子中是死亡模式。不同的參數用問號分隔。不管你輸入多少參數,整個命令都必須在一行中,如果分開來就不管用了。
下面列出ucc後面可以使用的所有參數列表。注意下面有一些參數在運行伺服器是是感覺不出有什麼變化的,列出它們只是為了列表了完整性:

AccessControl 用來打開高級管理員系統。和UT2003.ini中[Engine.GameInfo]部分里的AccessConrolClass一行的參數相同。
AdminName=xxxx 網頁管理和控制台管理員的名字--參看下面的高級網頁管理員部分。
adminpassword=xx 管理員密碼。至少5位,否則無效。
bAutoNumBots=true/false 設置成true在人數小於地圖默認設定的最小數時,會自動加入電腦bot補足。設置成false則不會。
autoadjust=true/false 設置成true,電腦bot會跟具玩家水平自動調整自己的等級。false則不會。
bPlayerMustBeReady=true/false 設置成true打開比賽模式,每局開時前所有玩家要按下滑鼠確認後游戲才開始。false則不需要。
Balanceteams=true/false 自動分配玩家平衡隊伍。
BlueTeam= 設置藍隊的名字。但是,不要以為你可以改變隊伍的名字。However, don't get clever and decide you'll name the blue team Purple or something like that. Many classes in the game refer to this variable to perform team info logic這句話不太好翻自己看吧。總之最好不要加這個參數,加上它會有不良後果。
BlueTeamAI= 特別的參數用來控制藍隊電腦AI。給MOD製作者用來配置自己寫的AI給新的游戲模式用的。別碰它。
BlueTeamSymbol= 設置藍隊的隊標。最好別設它。
Character=X 玩家用的人物,架伺服器時無效。
Class 如果在架伺服器的時候使用,在伺服器玩的玩家只能用默認的人物皮膚。通常玩家都會用自己喜歡的人物皮膚。所以這個命令毫無用處。
difficulty=x 設置電腦登記,從1到7分別是novice到godlike。
FF=x 友隊傷害的百分比。0是關閉,1是100% 所以.25就是25%友隊傷害。
fraglimit=x 死亡模式最多殺人數。
game= 游戲類型,可以用:xDeathmatch, xCTFgame,xBombingRun,或者xDoubleDom
gamepassword= 做為客戶端加入游戲時需要的密碼。
GameRules 設置特別的GameRules類,GameRules是mutator在UT2003中增加的新類型。通常你不需要用它。幾乎所有的mod都會自己動配置它們自己的GameRules。
Gamespeed=x 設置游戲速度,默認是1。最大2
Gamestats=true/false 設置成true會打開統計功能(玩家的游戲資料,如命中率等會上傳到主伺服器資料庫進行統計並參加全世界排名),電腦數量必須設為0才能生效。
goalscore=x CTF,DOM和BR模式里的隊伍分數上限。
maxlivers=x last man standing模式,死x後玩家就出局,直到只剩最後一人游戲結束。
maxplayers=x 最大同時游戲人數。
maxspectators=x 最大同時觀戰者人數。
minplayers=x 最小游戲人數,小於此數用電腦bot補足。
mutator= 在游戲中添加mutator(具體看下面)
numbots=x 設置電腦bot數量。注意打死bot,游戲統計功能就無效了。
Password=xxxx 別的游戲者端加入游戲時需要的密碼。
PlayerMustbeready=true/false 在每局開始前等待其他的玩家。
QuickStart 允許游戲在沒有人的時候照常進行,當然有電腦bot在玩的時候有效。
RedTeam 參看BlueTeam
RedTeamAI 參看BlueTeamAI
RedTeamSymbol 參看BlueTeamSymbol
SaveGame 繼續一個保存過的單人游戲。架伺服器時沒用。
SpectatorOnly=True/False 客戶端選項,允許客戶端用命令行指定觀察者模式,架伺服器時沒用。
Team 客戶端選項,允許客戶端用命令行指定希望加入的隊伍。同樣架伺服器時沒用。
translocator=true/false 設置為true允許使用移位器,false相反。
timelimit=x 每局時間限制。
Tournament=true/false 設置成競技場模式
weaponstay=true/false 武器保留。

幾個例子:

ucc server DM-Antalus?game=XGame.XDeathmatch?minplayers=4 架設死亡模式伺服器,初始地圖DM-Antalus,最少4人,不足4人用電腦補足。

ucc server CTF-Citadel?game=XGame.xCTFGame?FF=0 架設奪旗模式伺服器,初始地圖CTF-Citadel,無友隊傷害。

ucc server DOM-SunTemple?game=xGame.xDoubleDom?mutator=UnrealGame.MutLowGrav 雙重據點模式伺服器,初始地圖DOM-SunTemple,低重力模式開啟。

ucc server BR-Anubis?game=XGame.xBombingRun?weaponstay=true 架設BR模式伺服器,初始地圖BR-Anubis,武器保留開啟。

ucc server DM-Curse3?game=XGame.xTeamGame?fraglimit=100 團隊死亡模式,初始地圖DM-Curse3,殺人數上限100.

關於和主伺服器的聯系
如果你不想你的伺服器顯示在游戲的伺服器搜索列表裡,或者你只是在居域網里的伺服器,你可以在UT2003.ini里把下面這些關掉
[IpDrv.MasterserverUplink]
DoUplink=true|false 控制你的伺服器是否與internet上的主伺服器聯系。
UplinkToGamespy=true|false 和DoUplink相似,是決定是否和gamespy伺服器建立聯系。
SendStats=true|false 是否發送統計信息到主伺服器
ServerBehindNAT=true|false 伺服器是否在網關後面。
DoLANBroadcast=true|false 設置伺服器是否可以在居域網中查找到。一般設true

地圖循環和個性化地圖列表
默認下游戲會地圖會循環出現。 循環順序在user.ini文件裡面控制。 每個游戲類型都有一個部分列出循環的地圖。你可以編輯它,去掉你不喜歡的,加上你喜歡的地圖。如

[XInterface.MapListDeathMatch]
MapNum=0
Maps=DM-Morbias-2k3
Maps=DM-Spacepir8
Maps=DM-KillingField
Maps=DM-Deck16]i[-BETA
Maps=DM-MoonTemple
Maps=DM-Reigncaster
Maps=DM-Golgatha
Maps=DM-Tooth-N-Claw
Maps=DM-Stage1
Maps=DM-Liandri2003_BETA2

如果你想玩更多的地圖,就去網上下載吧。把他們解壓縮後把ut2文件放到map文件夾里,utx放到texture文件夾里,以及其他相應文件都放到相應目錄里,你就能使用新地圖了。

在一個游戲伺服器上運行多個游戲類型
你可能會想在一個游戲伺服器上運行多個游戲類型,比如 CTF,DOM,BR。可以用以下方法切換地圖,舉例如下:
比如 我們先開始一個死亡模式游戲在DM-Asbestos地圖上。因為現在是死亡模式,游戲結束後UT會檢查user.ini中[XInterface.MapListDeathMatch]部分索取下一張地圖的名字。它找到了BR-Anubis地圖名字,然後就切換到BR模式讀取BR-Anubis地圖。一但BR-Anubis的游戲結束後,UT會檢查 [XInterface.MapListBombingRun]部分,因為已經是BR模式了。它又找到CTF-Citadel地圖,然後就換成CTF模式,繼續....

[XInterface.MapListCaptureTheFlag]
MapNum=0
Maps=DM-Asbestos?game=XGame.xDeathMatch

[XInterface.MapListDeathMatch]
MapNum=0
Maps=BR-Anubis?game=XGame.xBombingRun

[XInterface.MapListBombingRun]
MapNum=0
Maps=CTF-Citadel?game=XGame.xCTFGame

第三方地圖和重定向
如果你使用了不是游戲自帶的第三方地圖,別人連上伺服器就可能花很長時間下載地圖同時佔用別的游戲者的帶寬使游戲不流暢,解決方法可以是把地圖文件放到另一個網頁伺服器上然後告訴客戶端自動從那裡下載
用 UT2003compress(可以在http://www.drunksnipers.com下載)...?的ut2003.ini 下面的部分重定向下載伺服器:
IpDrv.HTTPDownload]
HTTPServer=http://server.domain.name/myUTmaps/
Proxyserver=
Proxyport=
UseCompression=True

記住httpserver=後面的地址最後一定要加上個"/" ,否則它不會工作。如果碰到問題的話,把域名改成網頁伺服器的IP地圖試試看(比如192.168.1.10)

Mutators
Mutators要和啟動命令加在同一行里。下面的例子是架設一個死亡模式的伺服器地圖是DM-Asbestor帶大頭的mutator和Instagib的mutator:
ucc.exe DM-Asbestos?Game=XGame.xDeathmatch?Mutator=UnrealGame.MutBigHead,XGame.MutInstaGib

默認mutator參數列表:
Arena - XWeapons.MutArena
Big Head - UnrealGame.MutBigHead
Float-Away Corpses - XGame.MutHeliumCorpses
InstaGib - XGame.MutInstaGib
Zoom InstaGib - XGame.ZoomInstaGib
LowGrav - UnrealGame.MutLowGrav
No Adrenaline - XGame.MutNoAdrenaline
No Super Weapons - XWeapons.MutNoSuperWeapon
Quad Jump - XGame.MutQuadJump
AutoHealing - XGame.MutRegen
Slow Motion Deaths - XGame.MutSlomoDeath
Species Specific Stats - XGame.MutSpeciesStats
Vampire - XGame.MutVampire
注意部分mutator參數的前綴的不同:XWeapons , UnrealGame 等。

給每張地圖不同的Mutator
你可以通過修改user.ini為每張地圖設置不同的mutator 。除非你換掉它們,這些mutator會在所有地圖中生效。你可以用"mutator="後面什麼也不要加來在下一張地圖中去掉mutator。下面的例子是在DM-Antalus地圖上的游戲帶有Slow-mo death和low-grav兩個mutator,然後在下一張DM-Golgotha時去掉它們。
Maps=DM-Reigncaster
Maps=DM-Antalus?game=XGame.xDeathMatch?mutator=XGame.MutSlomoDeath,unrealGame.MutLowGrav
Maps=DM-Golgatha?mutator=
Maps=DM-Asbestos

同樣的方法可以載入其他的命令在後面,比如你可能想在某一張地圖上有隊友傷害,然後在下一張地圖中去掉它:
Maps=CTF-Chrome?FF=0.75
Maps=CTF-Citadel?FF=0

頁面管理員和高級頁面管理
基本的頁面管理員通過在runserver.bat里指定管理員名字和密碼,並編輯ut2003.ini中[UWeb.WebServer]部分啟用。這將允許你通過web頁面完全控制伺服器,只需要一個管理員帳號。注意,這些都不需要通過IIS或者Apache就可以完成。UT伺服器提供了自己的web頁面伺服器。如果你的伺服器上運行了IIS或者Apache,你要把它們的監聽埠口改成80以外的。
[UWeb.WebServer]
bEnabled=True
Listenport=xxxx
高級網頁管理員允許多個不同控制許可權的管理員帳號。注意,那個evolutionpack目前發現在使用高級管理員下有潛在的嚴重安全漏洞。我強烈建議在互聯網遠程式控制制系統中不要使用它。
具體的高級管理員指南參見http://www.unrealadmin.org/moles.p...rticle&artid=7
你應該在你的runserver.bat里加上管理員名字和密碼參數,除非你不想使用高級網頁管理工具。

一台機器上架設多個伺服器
你可以有兩種方法在一台機器上架設多個伺服器:給每個伺服器不同的埠號,或者分配不同的IP地址給你的每個UT伺服器,
如果你用不同的埠號架設伺服器,你可能碰到他們在游戲的伺服器搜索列表裡顯示不出來的問題。
如果你有多個IP你可以用-multihome 參數在runserver.bat里給每個伺服器綁定不同IP。例如下面把IP地址192.168.0.1綁到伺服器上
ucc server DM-Antalus?game=XGame.xDeathMatch -multihome 192.168.0.1
在linux下面,你需要戀情multihome=ip的參數:
ucc server DM-Antalus?game=XGame.xDeathMatch -multihome=192.168.0.1

伺服器在網關,防火牆,路由器後面
如果你的伺服器在網關,防火牆,路由器後面你需要打開一些埠讓外面的客戶端連進來。默認的埠有7777,7778,7787,7788,28900,28902。我現在還不確定他們是TCP,UDP或者兩者都是。
你還要在UT2003.ini中找到[IpDrv.MasterServerUplink]部分,把ServerBehindNat設為true。
除非你改變了埠(如上面說的一台機器運行多個伺服器)那麼凡是你用到的埠都要打開。

硬體要求
Epic建議,兩個32人的專用伺服器在一台伺服器主機上需要一台1.7G的CPU。你至少需要128M內寸(最小級限了)。
最近改一些客戶端的項目,測試的時候需要使用windows,因為是windows的客戶軟體,所以不得不使用windows, 原來總是在我的debian上安裝vmware, 自從升級內核到2.6.17後,發現怎麼安裝vmware都有問題, 就比較煩,原來看到過華華說過qemu,0.8.1的時候安裝過一次,感覺不是太理想,尤其是sdl的屏幕造成滑鼠拖動很慢, 去主戰的forum里看了看,發現這個已經被patch掉了。
而且kqemu又到了pre9了。正好試一下。

說一下目的:
安裝qemu和kqemu, 配好網路。實現virtual machine 和 host 能夠互通,也就是不是使用默認的user模式。 而改使用tun/tap的模式。

這里有兩個要求:
第一:內核要支持network filter. 尤其要用到的是nat.
第二:內核要支持tun/tap模塊。

我的是debian,自己編譯的內核,所以在編譯的時候就已經弄好了,由於我從來不用官方的內核,所以我就不知道debian的管方內核是不是已經有了。
不過可以自己看一下。
iptables的支持是不用問的,一般都是內置的。
就是tun/tap設備的支持。 這一點,可以這樣看一下:
modprobe tun, lsmod 看一下有沒有tun 如果成功,就是支持的, 而且是被編譯成了模塊,如果沒有,可以看一下:/dev/net/,看看是不是存在tun這樣一個文件,如果存在就是內核內置的,沒有編譯成模塊,另外, 如果編譯成了模塊,也要注意是否有這個文件存在。不在的話,得自己建了。
mknode /dev/net/tun, 一般現在的發行版都會在你modprobe tun時自動幫你弄好,所以不用擔心這個。

好了。我們開工了。

從主站上下載回來qemu的源碼:
tar zxvf qemu-0.8.2.tar.gz
cd qemu-0.8.2
gcc -v
這里看一下gcc的版本。
qemu目前只能用gcc3來編譯。如果你的是gcc4,
就su - 一下,到root, 然後到/usr/bin/
看一下有沒有gcc3
有的話,看看原來的gcc是鏈接還是一個文件。如果是一個文件,就備份一下,呆會恢復。 如果是鏈接就不用管它了。看它指向哪一個gcc, 記得呆會兒要恢復過來的。 鏈接的做法簡單了: ln -s gcc-3.3 gcc
就這樣的。 備份就更簡單了。mv gcc gcc.bak

回到我們剛才的目錄里。
運行:
./configure
make
make install
這樣就裝好了qmeu,

現在我們需要使用kqemu模塊來加速了。
下載回來kqemu-1.3.0pre9.tar.gz.
解開後。
tar zxvf kqemu-1.3.0pre9.tar.gz
然後進入到目錄里。這個時候有兩件事要注意:
1. 需要有你現在所用的內核的內核頭文件。
2. gcc的版本要和你的內核編譯的gcc版本一致。一搬來說就是你剛才改過的哪個了。恢復回來就好了。
好了。
./configure && make && make install
就好了。

我們已經就裝好了所有的軟體。
但是有時候我們需要一些設置才能工作。

1. modprobe kqemu
2. 看看/dev/kqemu 字元文件是否存在。
3. /dev/kqemu 文件的許可權要是0666的。

做好這些後就可以開始安裝你的虛擬機了,
安裝好,我們再設置你的網路

退出你的root, 然後
cd ~ 進入你的home directory
mkdir qemu
cd qemu
qemu-img create win2k.img 2G
建立一個硬碟文件。然後我們就可以在這個上面安裝win2000了。

可以使用iso文件, 也可以使用光碟。

我們這里使用光碟來安裝。
qemu -hda win2k.img -cdrom /dev/cdrom -boot d -localtime -m 256 -win2k-hack

這樣就可以開始安裝2000了。解釋一下這里的選項:
-hda 指定第一個硬碟。
-cdrom 指定你的cdrom 後面的文件可以是一個iso文件
-boot d 從光碟啟動,如果從你的硬碟啟動,就-boot c, -localtime使用本機的時間。 -m 就是設定內存的大小。默認是128, 注意可以設得大一點的內存,但是需要你的/dev/shm足夠大。
-win2k-hack, 在安裝2000的時候會有一個問題,它會提示你磁碟空間不夠,加上這個參數就可以了。

好了。
安裝完成了之後,就可以啟動來看一把了。
啟動如下:
qemu -hda win2k.img -boot c -localtime -m 256. 這樣就默認使用了kqemu

現在應該也可以上網了,但是注意虛擬機使用的是dhcp的方式來上網的。
而且不能ping通你的本機,我想這個可能是大多數人不想要的,所以下面我們來配置網路。 通過tun/tap, 有點象vmware里的host-only

要配置host-only(tun/tap)這樣的網路,我們上面已經講過了兩個要求,現在我們來做更多的事:

1、 建立一個文件 /etc/qemu-ifup
內容很簡單:
#!/bin/sh
sudo /sbin/ifconfig $1 192.168.0.1 netmask 255.255.255.0

然後chmod a+x /etc/qemu-ifup

注意這里的192.168.0.1是你的tun/tap網卡的地址,一定要注意:不能和你的實際的網卡在同一個網段。 也就是如果tun/tap是192.168.2.0.0/24, 那麼你的時間網卡就不能在這個網段。

然後寫一個小的腳本:
userinit 這個是文件名:
文件內容如下:

#!/bin/bash

case "$1" in
start)
[ ! -e /dev/kqemu ] && mknod -m 666 /dev/kqemu c 250 0
echo 1024 > /proc/sys/dev/rtc/max-user-freq
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
;;
stop)
;;
esac

然後:chmod a+x userinit

再:mv userinit /etc/init.d/
再: update-rc.d userinit start 25 2 3 .

要注意的是這個操作是在debian 下面的做法。
如果是在其他發行版:比如Fedora, 你可以直接寫這樣的script在你的/etc/rc.local文件里

[ ! -e /dev/kqemu ] && mknod -m 666 /dev/kqemu c 250 0
echo 1024 > /proc/sys/dev/rtc/max-user-freq
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE

編輯你的/etc/moles. 加上: kqemu (如果你的tun被編譯成了模塊,也加上tun)

最後還有一點。大家一定注意到了一個問題: 就是qemu-ifup腳本哩使用了so, 所以如果想普通用戶能用,那麼就配一下sudoer.
這個好配極了。 編輯:/etc/sudoers
你的用戶名 ALL=(ALL):ALL NOPASSWD:ALL
這樣就可以不用輸入密碼了。

現在我們可以開始啟動你的虛擬機了。
要象這樣啟動:

qemu -hda win2k.img -boot c -localtime -m 256 -net nic,vlan=0 -net tap,vlan=0

如果嫌麻煩,
就乾脆寫一個一句話的腳本:
#!/bin/bash
qemu -hda win2k.img -boot c -localtime -m 256 -net nic,vlan=0 -net tap,vlan=0

存儲為win2k, 加上x的許可權,然後放置到/usr/bin, 或者是/usr/local/bin下
以後直接運行win2k, 就可以啟動2000了。
同理也可以安裝多個系統,寫多個腳本啟動。
這樣比較的酷

㈨ 如何分析Android的Log

首先,讓我們看一看AndroidLog的格式。下面這段log是以所謂的long格式列印出來的。從前面Logcat的介紹中可以知道,long格式會把時間,標簽等作為單獨的一行顯示。

[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]

Start procnet.coollet.infzmreader:umengService_v1 for service
net.coollet.infzmreader/com.umeng.message.

UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}

[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]

Turning on JNI app bug workarounds fortarget SDK version 8...

[ 12-09 21:39:35.611 21745:21745D/AgooService ]

onCreate()

我們以第一行為例:12-09 是日期,21:39:35.510是時間396是進程號,416是線程號;I代表log優先順序,ActivityManager是log標簽。

在應用開發中,這些信息的作用可能不是很大。但是在系統開發中,這些都是很重要的輔助信息。開發工程師分析的log很多都是由測試工程師抓取的,所以可能有些log根本就不是當時出錯的log。如果出現這種情況,無論你怎麼分析都不太可能得出正確的結論。如何能最大限度的避免這種情況呢?筆者就要求測試工程師報bug時必須填上bug發生的時間。這樣結合log里的時間戳信息就能大致判斷是否是發生錯誤時的log。而且根據測試工程師提供的bug發生時間點,開發工程師可以在長長的log信息中快速的定位錯誤的位置,縮小分析的范圍。

同時我們也要注意,時間信息在log分析中可能被錯誤的使用。例如:在分析多線程相關的問題時,我們有時需要根據兩段不同線程中log語句執行的先後順序來判斷錯誤發生的原因,但是我們不能以兩段log在log文件中出現的先後做為判斷的條件,這是因為在小段時間內兩個線程輸出log的先後是隨機的,log列印的先後順序並不完全等同於執行的順序。那麼我們是否能以log的時間戳來判斷呢?同樣是不可以,因為這個時間戳實際上是系統列印輸出log時的時間,並不是調用log函數時的時間。遇到這種情況唯一的辦法是在輸出log前,調用系統時間函數獲取當時時間,然後再通過log信息列印輸出。這樣雖然麻煩一點,但是只有這樣取得的時間才是可靠的,才能做為我們判斷的依據。

另外一種誤用log中時間戳的情況是用它來分析程序的性能。一個有多年工作經驗的工程師拿著他的性能分析結果給筆者看,但是筆者對這份和實際情況相差很遠的報告表示懷疑,於是詢問這位工程師是如何得出結論的。他的回答讓筆者很驚訝,他計算所採用的數據就是log信息前面的時間戳。前面我們已經講過,log前面時間戳和調用log函數的時間並不相同,這是由於系統緩沖log信息引起的,而且這兩個時間的時間差並不固定。所以用log信息前附帶的時間戳來計算兩段log間代碼的性能會有比較大的誤差。正確的方法還是上面提到的:在程序中獲取系統時間然後列印輸出,利用我們列印的時間來計算所花費的時間。

了解了時間,我們再談談進程Id和線程Id,它們也是分析log時很重要的依據。我們看到的log文件,不同進程的log信息實際上是混雜在一起輸出的,這給我們分析log帶來了很大的麻煩。有時即使是一個函數內的兩條相鄰的log,也會出現不同進程的log交替輸出的情況,也就是A進程的第一條log後面跟著的是B進程的第二條log,對於這樣的組合如果不細心分析,就很容易得出錯誤的結論。這時一定要仔細看log前面的進程Id,把相同Id的log放到一起看。

不同進程的log有這樣的問題,不同的線程輸出的log當然也存在著相同的問題。Logcat加上-vthread就能列印出線程Id。但是有一點也要引起注意,就是Android的線程Id和我們平時所講的Linux線程Id並不完全等同。首先,在Android系統中,C++層使用的Linux獲取線程Id的函數gettid()是不能得到線程Id的,調用gettid()實際上返回的是進程Id。作為替代,我們可以調用pthread_self()得到一個唯一的值來標示當前的native線程。Android也提供了一個函數androidGetThreaId()來獲取線程Id,這個函數實際上就是在調用pthread_self函數。但是在Java層線程Id又是另外一個值,Java層的線程Id是通過調用Thread的getId方法得到的,這個方法的返回值實際上來自Android在每個進程的java層中維護的一個全局變數,所以這個值和C++層所獲得的值並不相同。這也是我們分析log時要注意的問題,如果是Java層線程Id,一般值會比較小,幾百左右;如果是C++層的線程,值會比較大。在前裡面的log樣本中,就能很容易的看出,第一條log是Jave層輸出的log,第二條是native層輸出的。明白了這些,我們在分析log時就不要看見兩段log前面的線程Id不相同就得出是兩個不同線程log的簡單結論,還要注意Jave層和native層的區別,這樣才能防止被誤導。

AndroidLog的優先順序在列印輸出時會被轉換成V,I,D,W,E等簡單的字元標記。在做系統log分析時,我們很難把一個log文件從頭看到尾,都是利用搜索工具來查找出錯的標記。比如搜索「E/」來看看有沒有指示錯誤的log。所以如果參與系統開發的每個工程師都能遵守Android定義的優先順序含義來輸出log,這會讓我們繁重的log分析工作變得相對輕鬆些。

Android比較常見的嚴重問題有兩大類,一是程序發生崩潰;二是產生了ANR。程序崩潰和ANR既可能發生在java層,也可能發生在native層。如果問題發生在java層,出錯的原因一般比較容易定位。如果是native層的問題,在很多情況下,解決問題就不是那麼的容易了。我們先看一個java層的崩潰例子:

I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:
pid=1760 uid=10065 gids={50065, 1028}

D/AndroidRuntime( 1760): Shutting downVM

W/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)

E/AndroidRuntime( 1760): FATALEXCEPTION: main

E/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo
{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerException

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)

E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)

E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
(ZygoteInit.java:793)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)

E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)

E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerException

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)

E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)

E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)

E/AndroidRuntime( 1760): ... 11more

I/Process ( 1760): Sending signal.PID: 1760 SIG: 9

W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivity

Jave層的代碼發生crash問題時,系統往往會列印出很詳細的出錯信息。比如上面這個例子,不但給出了出錯的原因,還有出錯的文件和行數。根據這些信息,我們會很容易的定位問題所在。native層的crash雖然也有棧log信息輸出,但是就不那麼容易看懂了。下面我們再看一個native層crash的例子:

F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)

D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36ms

I/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocation

D/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34ms

I/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******

I/DEBUG ( 127):Build fingerprint:
'Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys'

I/DEBUG ( 127):Revision: '9'

I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<
I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000

I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000

I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2c

I/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1c

I/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030

I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8

I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08

I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8

I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78

I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000

I/DEBUG ( 127): d10 0000000000000000 d110000000000000000

I/DEBUG ( 127): d120000000000000000 d130000000000000000

I/DEBUG ( 127): d14 0000000000000000 d150000000000000000

I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fc

I/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000

I/DEBUG ( 127): d20 0000000000000000 d210000000000000000

I/DEBUG ( 127): d22 0000000000000000 d230000000000000000

I/DEBUG ( 127): d24 0000000000000000 d250000000000000000

I/DEBUG ( 127): d26 0000000000000000 d270000000000000000

I/DEBUG ( 127): d28 0000000000000000 d290000000000000000

I/DEBUG ( 127): d30 0000000000000000 d310000000000000000

I/DEBUG ( 127): scr 00000010

I/DEBUG ( 127):

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

I/DEBUG ( 127):

I/DEBUG ( 127):stack:

I/DEBUG ( 127): beb4aaa8 000000c8
I/DEBUG ( 127): beb4aaac 00000000
I/DEBUG ( 127): beb4aab0 00000000
I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linker

I/DEBUG ( 127): beb4aab8 00001000
I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testapp

I/DEBUG ( 127): beb4aac8 00000000
I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testapp

I/DEBUG ( 127): beb4aad0 beb4ab24 [stack]

I/DEBUG ( 127): beb4aad4 00000001
I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]

I/DEBUG ( 127): beb4aadc 00000000
I/DEBUG ( 127): beb4aae0 df0027ad
I/DEBUG ( 127): beb4aae4 00000000
I/DEBUG ( 127): #00 beb4aae8 00000000
I/DEBUG ( 127): ........ ........

I/DEBUG ( 127): #01 beb4aae8 00000000
I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)

I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]

I/DEBUG ( 127): beb4aaf4 00000000
I/DEBUG ( 127): beb4aaf8 00000000
I/DEBUG ( 127): beb4aafc 00000000
I/DEBUG ( 127): beb4ab00 00000000
I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testapp

I/DEBUG ( 127):

這個log就不那麼容易懂了,但是還是能從中看出很多信息,讓我們一起來學習如何分析這種log。首先看下面這行:

pid: 2102, tid: 2102,name: testapp >>>./testapp <<<
從這一行我們可以知道crash進程的pid和tid,前文我們已經提到過,Android調用gettid函數得到的實際是進程Id號,所以這里的pid和tid相同。知道進程號後我們可以往前翻翻log,看看該進程最後一次列印的log是什麼,這樣能縮小一點范圍。

接下來內容是進程名和啟動參數。再接下來的一行比較重要了,它告訴了我們從系統角度看,出錯的原因:

signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000

signal11是Linux定義的信號之一,含義是Invalidmemory reference,無效的內存引用。加上後面的「faultaddr 00000000」我們基本可以判定這是一個空指針導致的crash。當然這是筆者為了講解而特地製造的一個Crash的例子,比較容易判斷,大部分實際的例子可能就沒有那麼容易了。

再接下來的log列印出了cpu的所有寄存器的信息和堆棧的信息,這裡面最重要的是從堆棧中得到的backtrace信息:

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

因為實際的運行系統里沒有符號信息,所以列印出的log里看不出文件名和行數。這就需要我們藉助編譯時留下的符號信息表來翻譯了。Android提供了一個工具可以來做這種翻譯工作:arm-eabi-addr2line,位於prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目錄下。用法很簡單:

#./arm-eabi-addr2line -f -eout/target/proct/hammerhead/symbols/system/bin/testapp0x0000045e

參數-f表示列印函數名;參數-e表示帶符號表的模塊路徑;最後是要轉換的地址。這條命令在筆者的編譯環境中得到的結果是:

memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108

剩餘三個地址翻譯如下:

main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38

out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361

_start libgcc2.c:0

利用這些信息我們很快就能定位問題了。不過這樣手動一條一條的翻譯比較麻煩,筆者使用的是從網上找到的一個腳本,可以一次翻譯所有的行,有需要的讀者可以在網上找一找。

了解了如何分析普通的Log文件,下面讓我們再看看如何分析ANR的Log文件。

㈩ 在linux代碼中,乘號不起作用

直接用下面的代碼測試一下:
int x=5*6;
int y=x*3;
printf("x=%d,y=%d",x,y);
或者你也可以通過單步運行的方式,查看運行到offset=....
這個語句時各變數的值。
不會你的編譯器有問題吧?也沒報警啥的?

閱讀全文

與frag文件編譯出錯相關的資料

熱點內容
asp防紅系統源碼模板 瀏覽:240
雙手握住文件夾 瀏覽:47
php分析html 瀏覽:623
加密貨幣權力 瀏覽:252
如何統計伺服器的流量 瀏覽:163
安卓游戲中文叫什麼 瀏覽:775
obs軟體支持雲伺服器嗎 瀏覽:6
假冒的程序員 瀏覽:617
優先順序演算法流程圖 瀏覽:211
軟體設計師跟程序員區別 瀏覽:581
哪個app能出售皮箱 瀏覽:20
格式工廠pdf 瀏覽:367
非對稱加密屬於哪一層 瀏覽:239
程序員病假暈倒 瀏覽:465
如何啟動帆軟內置伺服器 瀏覽:884
我的世界如何把命令方塊取出 瀏覽:2
單片機應用的場合 瀏覽:345
連接超時伺服器ip地址或埠配置錯誤 瀏覽:280
程序員常說的底層 瀏覽:716
伺服器cpu都是什麼封裝 瀏覽:708