在linux下用C實作netstat (Implement netstat)
在Linux 下,
netstat
指令常被用來查詢網路各種資訊,像是在TCP、UDP、IP ethernet 和 socket中的各種資訊。至於
netstat 則是去/proc中抓取各個所需要的資料。
/proc是系統模擬出來、假的(虛擬)檔案系統(pseudo-filesystem),它是外界讀取核心資訊的對外窗口。
說是假的檔案系統是因為/proc中每個檔案在當user-process讀取/proc下的檔案時,才會即時(real-time)產生檔案中的「內容」。
以下是Linux Programmer's Manual 中對於proc的描述:
The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
from man proc
在/proc 這個目錄下,可以分為兩種類型的檔案:一種是只有數字編號的目錄,其代表每個執行中的Process 的ID (i.e. pid); 另一種非數字編號的則是與系統資訊相關的檔案。
在這個實作中我們需要使用到的是 /proc/net,該目錄下儲存著各種網路層的資訊。其中的/tpc與/udp分別儲存著tpc socket table與udp socket。
當我們對其中一個(udp)貓一下(cat指令)後,會出現如下的表格:
在這些欄位中,我們所需要的分別是local_address、rem_address與inode。其中inode在這裡所代表的意義很重要,因為使用該addr:port的process
會link到該inode。講到這邊大概就已經講完所有原理了,最後只要找到link到所有inode的process就能完成了。
至於這個link要去哪裡找呢?這就要去/proc目錄下所有的數字目錄中的/fd(file descriptors)目錄去慢慢找,即/proc/[pid]/fd/,找到所有symbolic link到
inode
的
pid
。
例如我現找到一pid=878的process符合此條件(絕對剛好是87的),於是在/proc/878/fd 下執行 ls -l 指令:
其中最右邊的就是
symbolic link,
format為 type:[inode]
接下來我們觀察以上兩張圖,即會發現這個process 開啟的
inode
,能在udp table中搜尋匹配到,即代表該ip被此process所使用。如下圖所示:
若再仔細一看,會發現其實該process其實有不止一個inode對到此udp table,因此在做文件搜索時可別因為匹配到一筆就忘了搜尋接下來的inode。
至於c
要如何從ls中取得
symbolic link呢?這時候只要使用readlink(2)即可取得啦。其描述如下:
#includessize_t readlink(const char *path, char *buf, size_t bufsiz);
雖然我們找到了pid,但是pid只是對於linux而言方便辨識,但對人卻無法知曉到底是哪一個process,所以我們要在找到pid後,再去辨識process name,而這個name可由
/proc/[pid]/comm
之中
取得
。
因此就能得到該process的name(此處為avahi-daemon)。題外話,若該process為多執行緒時,comm取得的名字可能會不同。
若還想取得額外的訊息,可以再從/proc/[pid]/目錄中再挖其他需要的資料出來。這裡我們額外去取得
/proc/[pid]/cmdline
。
在/cmdline檔案中,會顯示"該process在被呼叫時,所下的完整command line",在定義中若該process為zombie時,此檔案為空,另外在指令之間是由 null bytes ('\0')所間隔。
在該例子中的
command line即為 running [grass-linux.local]
以上差不多把概念講述過,接下來就是大量的文件搜尋與字串處理了,我倒覺得整個程式中最麻煩的會是字串處理=~= 就是當個碼農一直農code。大概會變成以下成果:
受益良多
回覆刪除請問有 source code 可以實際測試嗎?謝謝
回覆刪除