2008年6月14日 星期六

兩個M$底下的工具

在linux/unix底下,automake/autoconfig是一大工具,或者rpm/deb都算是標準的格式,在windows底下呢?當然也有,不過好像要收費
Nullsoft Scriptable Install System是一個可以幫你自動把檔案放到適當路徑的軟體工具,另外有一個好玩的工具叫做AutoIt,本來設計是為了執行GUI批次作業,但是目前有人開始使用他做一些GUI功能的測試

2008年6月5日 星期四

三個好用的C語言工具

老實說,覺得Linux有時候code的documents跟comments實在是很少,真的很佩服那些有空去trace code的人,不過現在發現幾個存在已久的工具(自己孤陋寡聞),可以減少負擔

分別就是ctags, cxref, cflow,簡單的功能介紹如下
  • ctags:列表function的定義
  • cxref:分析各個symbol使用到的地方
  • cflow:分析呼叫次序
這幾個工具真的可以大幅度幫忙減輕trace code的負擔,不過我還是想說,把documents跟comments寫好吧

2008年6月3日 星期二

系統程式設計

話說以前有專門的課程都叫做系統程式設計,可是卻是兩碼子事情,一個教導你如何把程式語言變成系統上的machine code,另外一個卻是類似一般程式設計

後者卻是初學者容易陷入混亂的地方,目前大多是C語言,因為一開始還是排除不開一般標準的IO處理,這又是一般初學者在學習程式語言的時候最先接觸的地方,他們就開始有一個懷疑:系統程式設計跟一般程式設計不是差不多嗎?還不就是那些IO

接個更是低階IO的部分,使用的如read, write之類的函數,然後使用者可能覺得這根本是拖褲子放屁,多此一舉(我用fread跟fwrite不是用的好好的嗎?),對於一些啥select, dup之類的function背景又不大了然(我想寫書的作者背景的關係,他們認為已經解釋的很明白,其實初學者根本不懂來由),結果這方面他們就不會去深究

以M$或者java初學者,看到linux系統程式設計,他們大概為覺得signal跟process很不能適應吧,因為他們用的是event跟timer,M$系統程式設計另外又有一套,所以一整個混亂,我想這是一般初學者在進入時候最大的"心理障礙"(當然跟背景也有些關連)

學習過後可能就會發現一件事情,那就是系統程式非常的"底層",他是跟系統強烈相關的,你可能無法很順利的無痛移植到另外一個OS,比方說,你可能寫了一個RS232的通訊程式,可是你卻發現windows並不包含unistd.h這個標頭(我還沒試驗過,我是說可能會有這樣的狀況),然後整個程式就要從新開發

我想在踏入kernel之前,系統程式設計是一門不錯的熱身操

IPC之pipe

在沒有thread之前process大概是unix底下最重要的執行單位之一,所以很多基於process的溝通方式變的很重要,比方說pipe、share memory跟message box
thread出來之後,就可以單純的使用共用的memory,在thread之間溝通是比較方便(當然有其他問體衍生出來)
由IPC學習,漸漸的感覺到,對於unix like的系統來說,幾乎啥都是被當作file

高階的pipe使用兩個函數

#include 〈stdio.h〉

FILE *popen(const char *command, const char *open_mode)
pclose(FILE *stream_to_close);

比方說popen("uname -a","r"),可以看到popen回傳的是一個FILE指標,所以一個pipe也被當作了檔案來運作
高階pipe的運作方式是先建立一個shell然後把command執行類似execl的程序來取得資料,這樣一個運作方式其實還蠻消耗資源的

當然不是一定要透過類似command的模式執行,unix提供另外一種方式,直接套用低階的descriptor

#include 〈unistd.h〉
int pipe(int file_descriptor[2]);

可以看到上面放入了兩個低階的file descriptor,可以將任何寫入file_descriptor[1]的資料透過file_descriptor[0]讀取,採用fifo的原理
回傳的value有可能是
EMFILE:已經超過單一process可用的file descriptor個數
ENFILE:已經超過系統可用的file descriptor個數
EFAULT:descriptor是錯的
這常用在fork後的process於parent/child process之間的溝通上

那如果跨越process呢?本身並沒有絕對的關連,那麼怎麼辦?我不知道unix是否有提供及他的模式可以讓process查詢其他process提供哪些介面的方式,所以他有一個named pipe,看到named就表示過去已經存在,也就是你程式在compile time已經決定名稱的pipe,這樣就可以知道如何存取pipe(以為已經有名字了),其實是透過

#include 〈sys/types.h〉
#include 〈sys/stat.h〉

int mkfifo(const char *filename,mode_t mode);
int mknod(const char *filename,mode_t mode|S_IFIFO,(dev_t) 0);

其中mknod在有些系統並不提供,其實這個函數就是建立了一個臨時的檔案,這樣一來就可以透過這個檔案然操作,有一點要注意的,可能mode會受到umask的影響,比方說umask為0022在乎叫函數的時候使用0777,ls指令出來的結果會是0755

以上的pipe方式可以看的出來unix like的系統的確把各種實體裝置、虛擬裝置都當成檔案,這樣的設計上當然有好有壞囉,好處是幾乎有統一的介面可以操作;壞處是這樣的特色可能在底層的運作上更麻煩,因為並不是每個裝置的特色都可以符合檔案的模式