popen 程式範例
最近公司有個案子在做 WiFi 管理系統,透過集中式的控制器(AC,Access Controller)來管理轄下的 AP(Access Points,CAPWAP 的用語是 WTP)。嗯,有些 sense 的人應該就會知道說:「啊,你在做 CAPWAP」,Bingo!不過這篇沒打算要介紹 CAPWAP,下次有機會來講講 CAPWAP 的故事(不是技術,因為技術的部份我覺得很無聊,所以來講講故事和我的一些心得)。在做的時候遇到一個問題,廠商提供的平台,但卻沒提供人來進行系統整合。簡單來說,就是版子往我桌上一扔,就說:「給我在上面做這個功能」,然後時間短的不像話。額外抱怨一下,他選的 AC 平台比 raspberry pi 的效能還差,居然還敢跟我開口要一堆功能 ... 。理論上來說,AC 會把 WTP 的相關資訊帶到各 WTP,然後這時候 WTP 的 capwap daemon 會對核心層的 driver 進行設定。
一般說來,這種設定的方式是透過 ioctl 的溝通管道,最常見的範例程式就是 ifconfig,透過上下層定義好的 SIOCSIFFLAGS(Socket I/O Control Set Interface Flags)來進行溝通,所以一般來說這是屬於系統平台人員所要處理的問題。可是對於那種把版子跟一堆文件丟在我桌上,又不給我足夠時間的傢伙,我才懶得幫他查 WiFi driver 上需要的 SIOCSFFLAGS 勒。但案子又要進行,那要怎麼辦呢?所以我決定採取最單純的作法:直接呼叫系統的 WiFi 控制指令,如 iwpriv、wlanconfig 等,透過這些指令直接呼叫來取得並設定相關參數。缺點很明顯,就是效能會比較差,但一來是差不了多少(在意效能就給我拿比較像話的版子來!),二來是我相信對方提供的這些指令應該是測試過了,代表系統應該已經整合完畢了(我覺得是我一廂情願,但起碼對方無法還口,要合作也拿點誠意來吧)。
下一個問題是,要怎麼執行系統指令?最直覺的作法,用 system 的函式,問題是我要怎麼撈回傳的資料呢?因此這篇文章就來紀錄另外一支系統函式:popen 的用法。先來看看 man 的說明吧。
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
簡單來說,popen 會開一個 process 來執行 shell 的指令,然後將結果 pipe 回來主程式。直接看看範例:
程式很簡單,就不多做說明了。還有一個問題是,read 很容易理解,那 write 是什麼意思呢? 想的簡單一點就是 standard input。至於實際的情況等我想到有意義的情況以後再來寫 example code。
這篇文章沒什麼技術難度,只是純粹做個紀錄。
一般說來,這種設定的方式是透過 ioctl 的溝通管道,最常見的範例程式就是 ifconfig,透過上下層定義好的 SIOCSIFFLAGS(Socket I/O Control Set Interface Flags)來進行溝通,所以一般來說這是屬於系統平台人員所要處理的問題。可是對於那種把版子跟一堆文件丟在我桌上,又不給我足夠時間的傢伙,我才懶得幫他查 WiFi driver 上需要的 SIOCSFFLAGS 勒。但案子又要進行,那要怎麼辦呢?所以我決定採取最單純的作法:直接呼叫系統的 WiFi 控制指令,如 iwpriv、wlanconfig 等,透過這些指令直接呼叫來取得並設定相關參數。缺點很明顯,就是效能會比較差,但一來是差不了多少(在意效能就給我拿比較像話的版子來!),二來是我相信對方提供的這些指令應該是測試過了,代表系統應該已經整合完畢了(我覺得是我一廂情願,但起碼對方無法還口,要合作也拿點誠意來吧)。
下一個問題是,要怎麼執行系統指令?最直覺的作法,用 system 的函式,問題是我要怎麼撈回傳的資料呢?因此這篇文章就來紀錄另外一支系統函式:popen 的用法。先來看看 man 的說明吧。
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
簡單來說,popen 會開一個 process 來執行 shell 的指令,然後將結果 pipe 回來主程式。直接看看範例:
#include#include #include static void printCmd( char * ); static void printIp( void ); static void printMask( void ); int main() { printCmd( "pwd" ); printIp(); printMask(); return 0; } static void printCmd( char *pCmd ) { static char buffer[256]; FILE *pFile = popen( pCmd, "r" ); memset( buffer, 0, 256 ); while( fgets( buffer, 256, pFile ) != NULL ) { printf( "%s", buffer ); memset( buffer, 0, 256 ); } pclose( pFile ); return; } static void printIp( void ) { static char buffer[256]; FILE *pFile = popen( "ifconfig eth0 | grep \"inet addr\" | awk '{print $2}' | awk -F : '{print $2}'", "r" ); memset( buffer, 0, 256 ); while( fgets( buffer, 256, pFile ) != NULL ) { printf( "%s", buffer ); memset( buffer, 0, 256 ); } pclose( pFile ); return; } static void printMask( void ) { static char buffer[256]; FILE *pFile = popen( "ifconfig eth0 | grep Mask | awk '{print $4}' | awk -F : '{print $2}'", "r" ); memset( buffer, 0, 256 ); while( fgets( buffer, 256, pFile ) != NULL ) { printf( "%s", buffer ); memset( buffer, 0, 256 ); } pclose( pFile ); return; }
程式很簡單,就不多做說明了。還有一個問題是,read 很容易理解,那 write 是什麼意思呢? 想的簡單一點就是 standard input。至於實際的情況等我想到有意義的情況以後再來寫 example code。
這篇文章沒什麼技術難度,只是純粹做個紀錄。
留言
張貼留言