[技術] MSN與各家防毒軟體的設定

Written on 10:44 上午 by Yu Lai

一般我們在使用MSN時, 在傳送檔案時,
MSN都會要我們設定防毒軟體或是使用它們自己的LiveCare.
使用LiveCare是也ok, 但每次都要等它更新完才能掃毒實在有夠久的.

但各家防毒軟體的設定單檔掃描的方式也都不同,
以下是在網路上找到的, 有幾個我自己也沒試過, 參考看看吧.

== Avira AntiVir 9.x 小紅傘 ==
"C:\Program Files\Avira\AntiVir Desktop\avscan.exe" /CFG="C:\Program Files\Avira\AntiVir Desktop\Profile.txt" /PATH=%file%

同時需建立一文字檔Profile.txt於安裝目錄下, 內容如下:
[CFG]
GuiMode=2
ExitMode=3

[SEARCH]
Parameter=0x00000002
Parameter=0x00000020
Parameter=0x00000100
Parameter=0x00000400
Parameter=0x00010000
Parameter=0x00000080

[SCANNER]
BootsektorStart=0
Memory=0
ScanRootkits=0

參數說明:
GuiMode=?
1=顯示完整視窗
2=精簡
3=不顯示

ExitMode=3 (掃描後離開)
BootsektorStart=0 (取消開機磁區掃描)
Memory=0 (取消記憶體掃描)
ScanRootkits=0 (取消Rootkit掃描)

== ESET's NOD32 ==
"C:\Program Files\Eset\nod32.exe" /selfcheck+ /list+ /scroll+ /quit+ /pattern+ /heur+ /scanfile+ /scanboot- /scanmbr- /scanmem- /arch+ /sfx+ /pack+ /mailbox- /adware /unsafe /ah /prompt /all

== Symantec AntiVirus ==
"C:\Program Files\Symantec AntiVirus\Rtvscan.exe" /selfcheck+ /list+ /scroll+ /quit+ /pattern+ /heur+ /scanfile+ /scanboot- /scanmbr- /scanmem- /arch+ /sfx+ /pack+ /mailbox- /adware /unsafe /ah /prompt /all

== Norton AntiVirus ==
"C:\Program Files\Norton Internet Security Professional\Norton AntiVirus\ccIMScan.exe"

== Avast ==
"C:\Program Files\Alwil Software\Avast4\ashQuick.exe"

== Kaspersky ==
"C:\Program Files\Kaspersky Lab\Kaspersky Internet Security 6.0\avp.exe" scan %1

== McAfee 2007 ==
"C:\Program Files\McAfee\VirusScan\mcods.exe"

== PC-cillin ==
"C:\Program Files\Trend Micro\Internet Security 2005\PCCVScan.exe"

[閒聊] 馬來西亞出差心得

Written on 10:03 上午 by Yu Lai

這陣子好久沒發佈文章了,
不是沒東西可以發,
只是真的工作上忙了點.
這篇算是去馬來西亞的一些感想與心得吧.

二月底時去了馬來西亞出差,
本來說好的2個禮拜,
結果搞到整整1個月才回來.

在馬來西亞那段時間,
飲時大概是最不習慣的一環了吧.
這段期間也可以說是過的吃香喝辣的日子XD,
每天吃的三餐,
一定有一道菜是雞肉,
外加一道一定是紅色的菜.
而TM(Telcom Malaysia)也很不錯的在他們的Lab裡提供下午茶給我們吃,
但5天裡大概也有4天是紅通通的沒看過的東東,
然後飲料不是甜的要命的咖啡就是色素+糖水 = =.

由於我們是住在離位於Cyber Jaya的TM Lab有一段距離的Subang Jaya.
所以我們有在當地租用2台Van做為移動工具.
但也因為有一段距離(約3x公里),
加上人數眾多(約20人),
所以每天都要安排班次,
過著早出晚歸的日子,
算起來每天的工時比在台灣還誇張.
有時甚至過了半夜12點還在TM Lab. 唉, 真命苦 .__.

另外, 在跟TM的人溝通上用英文是很ok的,
雖然他們的英文也是有點口音,
但基本上還聽得懂,
不像跟印度阿三一樣聽嘸.
而每天早上Hotel會提供報紙給我們,
有華文的也有英文的報紙.
對了, 說到這個,
我們在TM這段期間裡,
有上他們的新聞喔 XD.

最後,
這篇主要是隨便寫寫啦,
會看起來沒什麼內容是因為工作內容不方便透露太多,
加上也有一段時間了,
有些東東也有點忘了,
請多多見諒吧.

[技術] 在Linux User-Space下實做L3 Protocol

Written on 4:01 下午 by Yu Lai

其實這篇應該是要接續上一篇寫的,因為用到的方法是和上一篇相同
的,但由於主題比較不太一樣,所以就分開來寫了。

在Linux中,一般要實做新的L3 protocol,大都是從kernel去下手,
效能較好,能存取的資源也比較多。但在開發embedded system下往
往有專案時間壓力以及軟體彈性的需求,去改kernel來達到這些要求
也就有點不太實際。所以我採用了在上一篇中使用的方法,也就是
Raw Socket與LPF(Linux Packet Filter)來完成一個L3 Protocol的
實做。

和Sniffer一樣的,我們使用了Raw Socket與LPF,比較不同的地方在
於LPF所使用的Filter。由於我們的protocol是定義成採用0x1219的
ether type,所以在配合tcpdump生成BPF code時用了以下的指令。

# tcpdump -dd -s 2048 ether proto 0x1219
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 1, 0x00001219 },
{ 0x6, 0, 0, 0x00000800 },
{ 0x6, 0, 0, 0x00000000 }

以下是部份的實做的程式碼:

#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/filter.h>
#include <linux/sockios.h>


void *mcpV2Handler(void *arg) {

int sock, n;
int rr;
U8 buf[2048];
U8 tmp[8], tmpSlot;
U8 lastBegMac[6];
U32 lastBegTime = 0;
U32 * pGroupKey;
tMcpFrame *frame;
tMcpPacket *packet;
tMcpCardInfo *cardInfo;
pthread_t mcpV2Sender_tid;
pthread_t mcpV2TxRx_tid;
struct sock_fprog filter;

/* Using tcpdump to generate BPF code */
/*
# tcpdump -d -s 2048 ether proto 0x1219
(000) ldh [12]
(001) jeq #0x1219 jt 2 jf 3
(002) ret #2048
(003) ret #0
*/
struct sock_filter bpf_code[]= {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 1, 0x00001219 },
{ 0x6, 0, 0, 0x00000800 },
{ 0x6, 0, 0, 0x00000000 }
};

filter.len = sizeof(bpf_code)/sizeof(bpf_code[0]);
filter.filter = bpf_code;

/* set detached thread */
pthread_detach(pthread_self());

if ((sock=socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL)))<0) {
perror("socket");
exit(1);
}

/* Attach the bpf filter to the socket */
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))<0){
perror("setsockopt");
close(sock);
exit(1);
}

/* ----------- Start implement ----------- */

while(1) {
n = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL);
if(n < 22) { /* 6+6+2+2+4+2+N */
printf("invalid packet\n");
continue;
}

frame = (tMcpFrame *)buf;

if(memcmp(frame->srcAddr, myMac, 6) == 0)
continue;

MCP_LOG("Dump: %02x%02x%02x%02x%02x%02x|"
"%02x%02x%02x%02x%02x%02x|"
"%04x|%04x|%08x|%04x|"
"%02x %02x %02x %02x %02x %02x %02x %02x %02x",
frame->dstAddr[0], frame->dstAddr[1], frame->dstAddr[2],
frame->dstAddr[3], frame->dstAddr[4], frame->dstAddr[5],
frame->srcAddr[0], frame->srcAddr[1], frame->srcAddr[2],
frame->srcAddr[3], frame->srcAddr[4], frame->srcAddr[5],
ntohs(frame->etherType),
ntohs(frame->mcpProtoType),
ntohl(frame->groupKey),
ntohs(frame->dataLength),
frame->data[0], frame->data[1], frame->data[2], frame->data[3],
frame->data[4], frame->data[5], frame->data[6], frame->data[7], frame->data[8]);

if(ntohs(frame->mcpProtoType) == 1 && ntohl(frame->groupKey) == myGroupKey) {
/* blah blah */
/* blah blah */
/* blah blah */
}

}

close(sock);

}

[技術] 在Linux下實作Sniffer

Written on 1:39 下午 by Yu Lai

在這裡先感謝一下黃仁竑老師,因為這篇其實這是之前唸研究所時,
上課所要交的作業。沒想到最近在工作上也用到了,呵呵。

雖然在Linux下有許多好用的Sniffer工具,如: tcpdump 或 libpcap等。
但若了解如何自己實作Sniffer,對於實作網路相關的protocol會有更深的了解。
在實作sniffer之前,在Linux下有幾個東西我們要先了解。

首先是raw socket,透過raw socket,可以讓我們從Layer 2(Ethernet)
的資料開始解讀,而不是已經被核心處理過的tcp/udp payload。

sock=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));

接著是LPF(Linux Packet Filter),在Linux的kernel中,有個LPF的機制
可以預先設定過濾socket讀取到的內容。當然這個在實作sniffer不是必要
的,我們大可在讀取資料後自行filter掉非必要的data。但透過LPF,可以
讓我們專心在實作資料的呈現上。
而LPF的使用,我們可以使用一種pseudo-machine code language叫作BPF。
它是一種用來描述filter的語言,我們可以透過tcpdump這支好用的工具來
產生bpf的sample code。使用方法就是使用tcpdump -d
tcpdump -dd 來生出C使用的code。另外,tcpdump所生成的
sample code預設只會抓取96個字元,所以要再加上-s參數來指定抓取的數量。

tcpdump -d -s 2048 tcp and host 140.123.230.166
(000) ldh [12]
(001) jeq #0x86dd jt 10 jf 2
(002) jeq #0x800 jt 3 jf 10
(003) ldb [23]
(004) jeq #0x6 jt 5 jf 10
(005) ld [26]
(006) jeq #0x8c7be6a6 jt 9 jf 7
(007) ld [30]
(008) jeq #0x8c7be6a6 jt 9 jf 10
(009) ret #2048
(010) ret #0

tcpdump -dd -s 2048 tcp and host 140.123.230.166
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 8, 0, 0x000086dd },
{ 0x15, 0, 7, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 5, 0x00000006 },
{ 0x20, 0, 0, 0x0000001a },
{ 0x15, 2, 0, 0x8c7be6a6 },
{ 0x20, 0, 0, 0x0000001e },
{ 0x15, 0, 1, 0x8c7be6a6 },
{ 0x6, 0, 0, 0x00000800 },
{ 0x6, 0, 0, 0x00000000 }

把Filter設到socket上。
struct sock_filter BPF_code[]= {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 8, 0, 0x000086dd },
{ 0x15, 0, 7, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 5, 0x00000006 },
{ 0x20, 0, 0, 0x0000001a },
{ 0x15, 2, 0, 0x8c7be6a6 },
{ 0x20, 0, 0, 0x0000001e },
{ 0x15, 0, 1, 0x8c7be6a6 },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 }
};
struct sock_fprog Filter;
Filter.len = 11;
Filter.filter = BPF_code;

setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter))

最後是把網卡的promiscuos mode打開,網卡一般會比對dst mac和自己的
Mac Address,若不相同或不是broadcast的封包會被drop掉不處理。
若要實作sniffer,這個mode一定要打開,才能監聽到別人的封包。

strncpy(ethreq.ifr_name,"eth0",IFNAMSIZ);
ioctl(sock,SIOCGIFFLAGS,ðreq);
ethreq.ifr_flags|=IFF_PROMISC;
ioctl(sock,SIOCSIFFLAGS,ðreq);

以下是完整的sample code,不過年代久遠,也沒時間compile測試,
如有錯誤不能compile,請見諒。XD

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <linux/filter.h>
#include <sys/ioctl.h>


int main(int argc, char **argv) {

int sock, sock_server, sock_client, n, i;
char buffer[2048];
unsigned char *iphead, *ethhead, *tcphead;
int addr_len;
struct sockaddr_in sa_cli;
struct ifreq ethreq;
FILE* fPtr;

struct sock_filter BPF_code[]= {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 8, 0, 0x000086dd },
{ 0x15, 0, 7, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 5, 0x00000006 },
{ 0x20, 0, 0, 0x0000001a },
{ 0x15, 2, 0, 0x8c7be6a6 },
{ 0x20, 0, 0, 0x0000001e },
{ 0x15, 0, 1, 0x8c7be6a6 },
{ 0x6, 0, 0, 0x00000800 },
{ 0x6, 0, 0, 0x00000000 }
};

struct sock_fprog Filter;

Filter.len = 11;
Filter.filter = BPF_code;

if ((sock=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)))<0) {
perror("socket");
exit(1);
}

/* Set the network card in promiscuos mode */
strncpy(ethreq.ifr_name,"eth0",IFNAMSIZ);
if (ioctl(sock,SIOCGIFFLAGS,ðreq)==-1) {
perror("ioctl (SIOCGIFCONF) 1");
close(sock);
exit(1);
}
ethreq.ifr_flags|=IFF_PROMISC;
if (ioctl(sock,SIOCSIFFLAGS,ðreq)==-1) {
perror("ioctl (SIOCGIFCONF) 2");
close(sock);
exit(1);
}

/* Attach the filter to the socket */
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter))<0){
int temp=sizeof(Filter);
printf( "%d" , temp);
perror("setsockopt");
close(sock);
exit(1);
}

/* Open the result file. */
if ((fPtr = fopen("dump.txt", "w")) == NULL) {
perror("fopen");
close(sock);
exit(1);
}

while (1) {
n = recvfrom(sock, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);

/* Check to see if the packet contains at least
* complete Ethernet (14), IP (20) and TCP/UDP
* (8) headers.
*/
if (n<42) {
perror("recvfrom():");
printf("Incomplete packet (errno is %d)\n", errno);
close(sock);
exit(0);
}

ethhead = buffer;
printf("Source MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[0], ethhead[1], ethhead[2], ethhead[3], ethhead[4], ethhead[5]);
printf("Destination MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[6], ethhead[7], ethhead[8], ethhead[9], ethhead[10], ethhead[11]);

iphead = buffer+14; /* Skip Ethernet header */
if (*iphead==0x45) { /* Double check for IPv4 and no options present */
printf("Source host %d.%d.%d.%d\n",
iphead[12], iphead[13], iphead[14], iphead[15]);
printf("Dest host %d.%d.%d.%d\n",
iphead[16], iphead[17], iphead[18], iphead[19]);
printf("Source,Dest ports %d,%d\n",
(iphead[20]<<8)+iphead[21], (iphead[22]<<8)+iphead[23]);
printf("Layer-4 protocol %d\n",
iphead[9]);
}

tcphead = iphead+20;
if (iphead[9] == 0x06) {
printf("TCP Sequence Number: %x%x%x%x\n",
tcphead[4], tcphead[5], tcphead[6], tcphead[7]);
printf("TCP Acknowledgement Number: %x%x%x%x\n",
tcphead[8], tcphead[9], tcphead[10], tcphead[11]);
printf("TCP Header Length: %d\n",
tcphead[12]>>4);
printf("TCP Control Bits: %02x (UAPRSF)\n",
tcphead[13]);
printf("TCP Window Size: %d\n",
(tcphead[14]<<8)+tcphead[15]);
for(i=4*(tcphead[12]>>4);i<n-14-20;i++) {
printf("%c", tcphead[i]);
}
printf("\n");
}
}

}


Ref:
http://www.linuxjournal.com/article/4659

[技術] Linux下的Timer

Written on 10:36 上午 by Yu Lai

其實之前就有用到Timer,只是最近又再一次用到,所以把相關的部份整理一下。
在Linux下實做定時器有兩種方法,分別是alarm()和setitimer(),以下分別介紹:

1. alarm()
alarm()可以用來設定信號SIGALRM在指定的秒數後傳到目前的process。
使用起來比起setitimer較為簡單,但由於使用的單位是秒數,
所以如果不要求很精確的話,用alarm()配合signal()就夠了。

unsigned int alarm(unsigned int seconds)

alarm()用來設置信號SIGALRM在經過參數seconds指定的秒數後傳送給目前的process。
如果參數seconds為0,則之前設置的鬧鐘會被取消,並將剩下的時間返回,
如果之前未設鬧鐘則返回0。

void sigalrm_fn(int sig) {

printf("alarm!\n");
alarm(2);

return;

}

int main(void) {

signal(SIGALRM, sigalrm_fn);
alarm(1);
while(1) pause();

}


2. setitimer()
setitimer()比alarm功能強大,支持3種類型的Timer:
ITIMER_REAL : 以系統真實的時間來計算,它送出SIGALRM信號。
ITIMER_VIRTUAL : 以Process在User-Mode下花費的時間來計算,它送出SIGVTALRM信號。
ITIMER_PROF : 以Process在User-Mode下和Kernel-Mode下所費的時間來計算,它送出SIGPROF信號。

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

setitimer()第一個參數which指定定時器類型(上面三種之一);
第二個參數是struct itimerval的一個instance;第三個參數可不做處理。
setitimer()調用成功返回0,否則返回-1。

struct itimerval {
struct timeval it_interval; /* timer interval */
struct timeval it_value; /* current value */
};

itimerval結構中的it_value是減少的時間,當這個值為0的時候就發出相應的信號。
然後再將it_value設置為it_interval值。也就是說如果itimerval.it_interval不為0,
則該定時器將持續有效(每隔一段時間就會發送一個信號)。

下面是關於setitimer的一個簡單示範,在該例子中,
每隔一秒發出一個SIGALRM,每隔0.5秒發出一個SIGVTALRM信號:
int sec;

void sigroutine(int signo) {

switch (signo){
case SIGALRM:
printf("Catch a signal -- SIGALRM \n");
signal(SIGALRM, sigroutine);
break;
case SIGVTALRM:
printf("Catch a signal -- SIGVTALRM \n");
signal(SIGVTALRM, sigroutine);
break;
}
return;

}

int main() {

struct itimerval value, ovalue, value2;
sec = 5;

printf("process id is %d\n", getpid());
signal(SIGALRM, sigroutine);
signal(SIGVTALRM, sigroutine);

value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &value, &ovalue);

value2.it_value.tv_sec = 0;
value2.it_value.tv_usec = 500000;
value2.it_interval.tv_sec = 0;
value2.it_interval.tv_usec = 500000;
setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

for(;;) ;

}


PS:
Linux信號機制基本上是從Unix系統中繼承過來的。
早期Unix系統中的信號機制比較簡單和原始,後來在實踐中暴露出一些問題,
因此,把那些建立在早期機制上的信號叫做"不可靠信號",
信號值小於SIGRTMIN(SIGRTMIN=32,SIGRTMAX=63)的信號都是不可靠信號。
這就是"不可靠信號"的來源。它的主要問題是:Process每次處理信號後,
就將對信號的響應設置為Default動作。在某些情況下,將導致對信號的錯誤處理;
因此,User如果不希望這樣的操作,那麼就要在信號處理函數結尾再一次使用signal(),重新安裝該信號。

[技術] 在C中列出目錄與檔案

Written on 8:50 上午 by Yu Lai

一般在C中,我們可以使用opendir()與readdir()來列出目錄下所有的檔案。
以下是範例程式:

#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

main() {
DIR * dir;
struct dirent * ptr;
int i;
dir =opendir(“/etc/rc.d”);
while((ptr = readdir(dir))!=NULL) {
printf(“d_name: %s\n”,ptr->d_name);
}
closedir(dir);
}

配合struct dirent,定義如下:
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256];
};

d_ino 此目錄進入點的inode
d_off 目錄文件開頭至此目錄進入點的位移
d_reclen d_name的長度,不包含NULL字符
d_type d_name所指的檔案類型
d_name 檔名
其中unsigned cahr d_type;可以來判斷是子目錄或是一般的檔案。
但不知是我使用的uClibC的問題,沒實作到還怎樣,使用上一直有問題。

後來還是找到解決方法,方法有2種,分別如下:
1. 再使用一次readdir()來判斷回傳值,若回傳為NULL,即為檔案。
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

main() {
DIR * dir;
DIR * dir2;
struct dirent * ptr;
int i;
dir =opendir(“/etc/rc.d”);
while((ptr = readdir(dir))!=NULL) {
char pathname[100];
sprintf(pathname,"/etc/rc.d/%s", ptr->d_name);
if((dir2 = opendir(pathname))==NULL) {
printf("%s: file\n", ptr->d_name);
} else {
printf("%s: directory\n", ptr->d_name);
closedir(dir2);
}
}
closedir(dir);
}

2. 使用int stat(const char *file_name, struct stat *buf),
在struct stat其中的 st_mode 可以用來判斷是哪種檔案(也就是上面 d_type的 功用)。
為了方便,POSIX另外有定義幾個MACRO:
S_ISLNK(st_mode) : 是symbolic link
S_ISREG(st_mode) 一般檔案(regular file)
S_ISDIR(st_mode) 目錄(directory)
S_ISCHR(st_mode) 字元設備檔(char device)
S_ISBLK(st_mode) 區塊設備檔(block device)
S_ISSOCK(st_mode) local-domain socket
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

main() {
DIR * dir;
struct dirent * ptr;
int i;
dir =opendir(“/etc/rc.d”);
while((ptr = readdir(dir))!=NULL) {
char pathname[100];
struct stat buf;
sprintf(pathname,"/etc/rc.d/%s", ptr->d_name);
stat(pathname, &buf);
if(S_ISREG(buf.st_mode))
printf("%s: file\n", ptr->d_name);
else
printf("%s: directory\n", ptr->d_name);
}
closedir(dir);
}

[技術] FreeBSD benchmarks software list

Written on 9:41 上午 by Yu Lai

版權宣告:
轉載自yuwen學弟在築夢BBS(cd.twbbs.org)的個人板《P_yuwen》

autobench : Automating the process of benchmarking a web server
bonnie : Performance Test of Filesystem I/O
bonnie++ : Performance Test of Filesystem I/O
bytebench : The BYTE magazine benchmark suite
dbench : A simulation of the Ziff-Davis netbench benchmark
dbs : A distributed network benchmarking system
forkbomb : System stress testing tool
hpl : High Performance Computing Linpack Benchmark
httperf : A tool for measuring webserver performance
iozone : Performance Test of Sequential File I/O
iozone21 : Performance Test of Sequential File I/O (older version)
lmbench : A system performance measurement tool
nbench : BYTE Magazine's native benchmarks
netperf : Network performance benchmarking package
netpipe : A self-scaling network benchmark
nttcp : A client/server program for testing network performance
pipebench : Pipebench shows current throughput/amount of data through a pipe
pnetmark : Benchmarking tool for Common Language Runtime (CLR)
polygraph : A benchmarking tool for Web proxies
postal : Benchmark SMTP/POP servers
postmark : NetApps file system benchmark
pybench : An extensible benchmark suite for Python
rawio : Test performance of low-level storage devices
scimark2 : A Java benchmark for scientific and numerical computing
scimark2c : An ANSI C version of the SciMark2 benchmark
siege : A http regression testing and benchmarking utility
stream : Synthetic benchmark program that measures sustainable memory bandwidth
tcpblast : Measures the throughput of a tcp connection
tmetric : A bandwidth measurement tool
ttcp : Benchmarking tool for analysing TCP and UDP performance
ubench : Unix Benchmark Utility for CPU(s) and memory
webbench : Simple forking web benchmark
xengine : Reciprocating engine for X
himenobench : Himeno bench benchmark, solves Poisson eq. with Jacobi's method
blogbench : Performance Test of Filesystem I/O
dkftpbench : A FTP benchmark program
iperf : A tool to measure maximum TCP and UDP bandwidth
netio : Network benchmark
nqueens : N-queens benchmark
pathchirp : A measurement tool for available bandwidth estimation
pathload : A measurement tool for network path available bandwidth estimation
pathrate : A measurement tool for capacity estimation of network paths
pear-Benchmark : PEAR framework to benchmark PHP scripts or function calls
raidtest : Test performance of storage devices
unixbench : The BYTE magazine's Public Domain benchmark for UNIX
flops : Floating point benchmark to give your MFLOPS rating
libmicro : Set of utilities to benchmark productivity of system calls
thrulay : Network capacity tester
fhourstones : The Fhourstones Benchmark
gsbench : Benchmarking tool for GNUstep
gtkperf : Measure your system's GTK+ performance
imb : Intel MPI Benchmark
mdtest : A filesystem metadata benchmark utility
p5-Benchmark-Forking : Run benchmarks in separate processes
p5-Benchmark-Stopwatch : Simple timing of stages of your code
rubygem-railsbench : Scripts designed for benchmarking of Rails applications
super-smack : A benchmarking, stress testing, and load generation tool for Databases
sysbench : A modular, cross-platform and multi-threaded benchmark tool
tsung : Multi-protocol distributed load testing tool
sipp : SIP testing tool
xdd : Tool for measuring and characterizing disk subsystem I/O

[技術] 用GPIO實做I2C介面(Bit-Banging)

Written on 12:00 上午 by Yu Lai

最近工作上需要去讀寫I2C介面的IC,
是顆用來量測環境溫度的IC-LM75。
I2C是由2支腳-SDA和SCL所組成的並聯介面,
所有I2C的IC都接在這2支腳上,
I2C相關資訊可以自行到Googlewiki找找。

而我們的板子的CPU本身沒有I2C的介面,
它是透過2支GPIO腳來連接LM75,
所以就必須以軟體的方式來控制GPIO來模擬I2C的Signal,
以上的實做也被稱做Bit-Banging。

照著LM75的Datasheet和網路上相關的資料,
還蠻順利的完成整個Bit-Banging的實做。

以下就是相關實做的source code。

#define SCL_PORT  6
#define SDA_PORT 23

#define ADDR_LM75 0x94 /* 1001 010 x */
#define I2C_DELAY_TIME 10 /* us */

#define ACK 1
#define NO_ACK 0

首先是會用到的#define。
SCL腳位是使用GPIO6,SDA是使用GPIO23。
而LM75使用的Address則是固定的1001配上
板子上A2,A1,A0腳位所接的電位的010當前7個bit。
另外,由於I2C算是比較慢的介面,所以要有個delay time。
void i2c_init(void) {

/* Enable SDA & SCL gpio port */
gpio_enable(SDA_PORT);
gpio_enable(SCL_PORT);

/* Set SDA & SCL to High */
gpio_set(SDA_PORT, __HIGH__);
gpio_set(SCL_PORT, __HIGH__);

}

這裡是將GPIO腳位設定啟動,並將SDA和SCL電位設成HIGH,
完成Initial的動作。
void i2c_start(void) {

/* I2C start sequence is defined as
* a High to Low Transition on the data
* line as the CLK pin is high */

gpio_set(SDA_PORT, __HIGH__); /* SDA: High */
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
HAL_DELAY_US(I2C_DELAY_TIME);

gpio_set(SDA_PORT, __LOW__); /* SDA: Low */
gpio_set(SCL_PORT, __LOW__); /* SCL: Low */
HAL_DELAY_US(I2C_DELAY_TIME);

}

void i2c_stop(void) {

/* I2C stop sequence is defined as
* data pin is low, then CLK pin is high,
* finally data pin is high. */

gpio_set(SDA_PORT, __LOW__); /* SDA: Low */
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
gpio_set(SDA_PORT, __HIGH__); /* SDA: High */

}

如source code裡我comment所寫的,
I2C介面溝通的start就是SDA和SCL都是由本來保持的High變成Low所開始。
而stop就是SDA和SCL由High-Low傳遞資料之間變為High持續下去。
void i2c_write(unsigned char data) {

/* An I2C output byte is bits 7-0
* (MSB to LSB). Shift one bit at a time
* to the MDO output, and then clock the
* data to the I2C Slave */

unsigned char i;

/* Write to slave */
for(i = 0; i < 8; i++) {
gpio_set(SDA_PORT, (data&0x80)?1:0); /* Send data bit */
data <<= 1; /* Shift one bit */
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
HAL_DELAY_US(I2C_DELAY_TIME);
gpio_set(SCL_PORT, __LOW__); /* SCL: Low */
HAL_DELAY_US(I2C_DELAY_TIME);
}

/* Read ACK bit from slave */
gpio_get(SDA_PORT);
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
HAL_DELAY_US(I2C_DELAY_TIME);
gpio_set(SCL_PORT, __LOW__); /* SCL: Low */
HAL_DELAY_US(I2C_DELAY_TIME);

}

unsigned char i2c_read(unsigned char send_ack) {

unsigned char i, data;

data = 0x00;

/* Read from slave */
for(i = 0; i < 8; i++) {
data <<= 1; /* Shift one bit */
data |= gpio_get(SDA_PORT); /* Read data bit */
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
HAL_DELAY_US(I2C_DELAY_TIME);
gpio_set(SCL_PORT, __LOW__); /* SCL: Low */
HAL_DELAY_US(I2C_DELAY_TIME);
}

/* Send ACK bit to slave */
if(send_ack)
gpio_set(SDA_PORT, __LOW__); /* SDA: Low */
else
gpio_set(SDA_PORT, __HIGH__); /* SDA: High */
gpio_set(SCL_PORT, __HIGH__); /* SCL: High */
HAL_DELAY_US(I2C_DELAY_TIME);
gpio_set(SCL_PORT, __LOW__); /* SCL: Low */
HAL_DELAY_US(I2C_DELAY_TIME);

return data;

}

接著就是傳送的過程了,
一般I2C都是由高位先寫入(這個不一定,要看Datasheet)。
在寫入時,Master(指CPU)先把SDA設成寫入的bit,
再把SCL依照我們delay的時間來做clock signal的產生(low->high->low->...)。
接著重複上面的動作依序把整個byte都寫入。
寫完整個byte後要讀取一下Slave(指LM75)所回傳的ACK bit。

而在讀取時,一樣先讀入SDA的電位當成data的bit,
再把SCL產生clock signal給Slave,
Slave在收到clock signal後會在SDA上變動電位把資料依序傳出來。
所以同樣的重複上面的動作就可以把組合出整個byte的資料。
當Master讀完byte後也要有回傳ACK的動作來告知是否繼續有下一個byte要讀取。
int get_lm75_temp(void) {

unsigned char msb = 0x00, lsb = 0x00;

i2c_start();
i2c_write(ADDR_LM75); /* Ask LM75 write */
i2c_write(0x00);

i2c_start();

i2c_write(ADDR_LM75+1); /* Ask LM75 read */
msb = i2c_read(ACK);
lsb = i2c_read(NO_ACK);
i2c_stop();

return (msb << 8) | lsb;

}

最後,照著LM75的Datasheet,
Master先傳送address byte給Slave,
Slave在收到address後會先比對自己A2,A1,A0,
若符合再依照address byte的最後一個bit來回應之後的動作,
若為0則是write動作,若為1則是read動作。

所以我們要讀取現在溫度資料時,
CPU先把address byte+0給寫到LM75,告知接下來要寫入register設定,
接著把0x00寫入表示要讀取第0個register,也就是現在的溫度。
再來就是重新開始先寫入address byte+1給LM75,告知要讀取資料。
接著就把溫度資料讀出,共2個byte,所以讀了2次囉。
最後就是把資料組合起來return出去囉。

[技術] 執行檔的檔案格式轉換

Written on 6:04 下午 by Yu Lai

最近為了產生flash的image raw file,
需要將compiler編好的srec格式檔或elf檔式檔進行轉換。
上網找了老半天,原來我們的gnu binutils就有提供這些功能了 ^^。

使用方法如下:
objcopy -I -O

例1: 將srec轉成binary raw file
objcopy -I srec -O binary image.srec image.bin

例2: 將elf32-bigmips轉成binary raw file
objcopy -I elf32-bigmips -O binary image.srec image.bin

[技術] Busybox使用心得

Written on 11:58 上午 by Yu Lai

最近為了產品的新功能以及業務反應的功能,
我重新配置了busybox來達到以上需求。
之前的busybox是由嘉義那邊的同事安裝好打包過來的,
也沒把source code一起帶過來,加上版本也有點舊了,
所以我就安裝新版的當做順便更新囉。

以下是安裝過程中遇到的問題與心得的筆記,
就當做分享與記錄囉。

首先,busybox可以到[http://busybox.net/]下載回來。
然後解開後,如果有需要透過cross-compile來編譯的話,
可以在Makefile裡找到ARCH與CROSS_COMPILE配置它,
另外也可以在Makefile.flags裡直接配置CC、AR和LD等變數。

設定好後直接執行make menuconfig來進行busybox的applet設定囉。
這裡有幾個比較要注意的地方,在Build Options中,我是建議把
Busybox設成Build BusyBox as a static binary (no shared libs)。
雖然比較佔空間,但省下來搞library的時間就夠值得了。
而在設定Login/Password Management Utilities的時候,
為了免去配置glibc的麻煩,最好設置使用busybox自己的password
和shadow文件的功能(Use internal password and group functions
rather than system functions)。
同時要把(login)和(Support for login scripts)打勾,
這樣login才會正常運作。

接著直接使用make和make install就可以把busybox編譯出來啦。
編譯好busybox後並把buxybox copy到rootfs中,
接著要配置好rootfs以配合busybox的運作。
這裡要配置的有etc/inittab、etc/init.d/rcS
以及etc/passwd和etc/shadow(有勾選的話)。

最後就把rootfs包起來燒到target裡就可以啦。

(PS: 以上要配置的檔案可以在網路上找到許多範例,改天再補進來吧)

[技術] Linux的SysRq機制

Written on 1:28 下午 by Yu Lai

最早SysRq是IBM在PC/AT上用來執行低階OS指令的function key。

後來在Linux則是被用來設定kernel提供系統除錯或回復crash的機制。
也就是所謂的"Magic SysRq key"。

以下是透過Linux SysRq機制的操作方法。
首先enable或disable:
# echo 0 > /proc/sys/kernel/sysrq
# echo 1 > /proc/sys/kernel/sysrq

執行magic commands,可以透過echo指令來達成:
# echo b > /proc/sysrq-trigger
以上指令等價於組合鍵Alt + SysRq + B,也就是重新開機。

同理,強制關機可以使用:
# echo o > /proc/sysrq-trigger

[技術] GNU的configure的build、host和target的差別

Written on 2:28 上午 by Yu Lai

相信有編過cross-platform的程式的人,
多多少少會遇到設定這三個參數的時候,
今天正好在編GDB,也就對這3個參數研究了一下。

其實心得可以用一句話來形容這3個:
"讓套件在build下編好,使之在host中執行的target平台版本。"

也就是說:
1. build就是你編這個套件的環境。
通常可以不用設,讓configure自己猜。

2. host就是這個套件的執行環境。
這個通常配cross-compile來編在不同平台執行的套件。
e.g. 要編出在mips-linux下執行的net-snmp套件
./configure --host=mips-linux --prefix=blahblah

3. target是指套件內容的版本或產出物版本。
這個常用於GNU的gcc或binutils等支援不同平台的套件。
e.g. 要編出一個在x86下執行的arm-elf格式的gcc
./configure --host=i686-pc-linux-gnu --target=arm-elf --prefix=blahblah

參考資料: http://www.airs.com/ian/configure/configure_5.html

[技術] C的function call與stack frame心得

Written on 12:00 上午 by Yu Lai

從大二的Program Language中學到stack對於C的function call的實做與功用的概念,
以及各個register的功用,但從未實際地深入了解其中register的變化.
剛好最近T40灌了Ubuntu Linux (x86),就直接寫了些C code,
配合objdump與gdb來trace其中register的變化,於是有了這篇的心得.

首先是複習一下register:
%eip:instruction pointer,用來指到下一個instruction的位置.
%esp:stack pointer,用來指到目前stack的top.
%ebp:Frame pointer,用來指到目前stack frame的開頭.

這次所使用的source code:

#include <stdio.h>
void hi(int a, int b) {
int i = 3;
return;
}
int main(int argc, char *argv[]) {
hi(1, 2);
return 0;
}

我們先透過$ gcc -o test test.c編出test,
然後再透過objdump -d test來觀察disassemble出來的部份:
 08048344 <hi>:
8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
8048347: 83 ec 10 sub $0x10,%esp
804834a: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%ebp)
8048351: c9 leave
8048352: c3 ret

08048353 <main>:
8048353: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048357: 83 e4 f0 and $0xfffffff0,%esp
804835a: ff 71 fc pushl -0x4(%ecx)
804835d: 55 push %ebp
804835e: 89 e5 mov %esp,%ebp
8048360: 51 push %ecx
8048361: 83 ec 08 sub $0x8,%esp
8048364: c7 44 24 04 02 00 00 movl $0x2,0x4(%esp)
804836b: 00
804836c: c7 04 24 01 00 00 00 movl $0x1,(%esp)
8048373: e8 cc ff ff ff call 8048344 <hi>
8048378: b8 00 00 00 00 mov $0x0,%eax
804837d: 83 c4 08 add $0x8,%esp
8048380: 59 pop %ecx
8048381: 5d pop %ebp
8048382: 8d 61 fc lea -0x4(%ecx),%esp
8048385: c3 ret
8048386: 90 nop

從0x0804835d開始,我們可以看到main()在呼叫hi()時的步驟,
首先先把ebp的值塞進stack中,然後把esp的值塞到ebp裡.
接著把esp減8(因為stack是由高位往低位),再分別把0x2和0x1塞入stack中,
這2個其實就是把hi()所需的變數放入stack中,最後就是call 8048344 <hi>.
接著透過gdb設好breakpoint把stack中的值給印出來.
$ gdb -q test
(gdb) b hi
Breakpoint 1 at 0x804834a
(gdb) r
Starting program: /home/lazyf/test

Breakpoint 1, 0x0804834a in hi ()
Current language: auto; currently asm
(gdb) x/32xw $esp
0xbfb9a074: 0x0804953c 0xbfb9a088 0x08048280 0xb7f95ff4
0xbfb9a084: 0xbfb9a098 0x08048378 0x00000001 0x00000002
0xbfb9a094: 0xbfb9a0b0 0xbfb9a108 0xb7e61450 0xb7fc8ce0
0xbfb9a0a4: 0x080483a0 0xbfb9a108 0xb7e61450 0x00000001
0xbfb9a0b4: 0xbfb9a134 0xbfb9a13c 0xb7facb38 0x00000000
0xbfb9a0c4: 0x00000001 0x00000000 0x080481f5 0xb7f95ff4
0xbfb9a0d4: 0xb7fc8ce0 0x00000000 0xbfb9a108 0x67416081
0xbfb9a0e4: 0xd8282a91 0x00000000 0x00000000 0x00000000
(gdb)

從stack內的值我們可以觀察到,其實call指令所做的動作就是把下一筆instruction的
address(eip)給push進stack裡(0x08048378被放入0xbfb9a088中),接著再把call的address
塞到eip再執行它.

接著到了hi()中,和main()一樣的先把ebp塞入stack中,然後把把esp的值塞到ebp裡.
從這裡我們可以知道,一個function開始時,會先把上一個function的ebp放入stack中,
接著馬上設定自己的ebp.從這裡可以用來確保目前所在function的ebp的值的正確性,
以及保存之後要return時上一個function的ebp的值.

在hi()中把ebp設定好後,它先在stack中allocate了16個byte來使用,接著我們看到了
在ebp-4的位置上被填入了0x3的值,也就是我們在程式中宣告的變數int i = 3;的實做.

最後是leave指令和ret指令所實做出來的return;.在這裡leave指令的操作相當於
把ebp的值放到esp中,然後從stack中pop出值來放到ebp裡,而ret指令的操作則相當於從
stack中pop出值來放到eip裡.也就是說除了eip外,esp和ebp都回到呼叫hi()之前的狀況.
完成hi()的呼叫.

另外,如果hi()有值需要被return時,通常會透過eax register來傳遞.
也就是說在$lt;hi>中的leave指令前會加入mov xxx,%eax指令,
在<main>中call <hi>指令的下一個指令會是mov %eax,yyy指令讀出eax放入yyy中
和mov $0x0,%eax指令把eax清空.

以上就是我從gdb與objdump中所觀察到的一個C的function被呼叫的過程.
如內容有所錯誤,煩請有看到的人不吝賜教.Thanks.

[技術] Ubuntu的dash

Written on 4:39 下午 by Yu Lai

這幾天把舊的T40裝了Ubuntu,用一用發現有些怪怪的地方.
原本可以用的script有些怪怪的,後來查了一下才發現是dash在做怪.
Ubuntu為了加速開機,使用了dash來取代bash成為/bin/sh.
但dash實做的有些不完整,自然就被它給婊到了.

解決方法除了使用指令$ sudo dpkg-reconfigure dash外
也可以用ln手動把/bin/sh -> /bin/dash 改回 /bin/sh -> /bin/bash即可.

[技術] Google Code Prettify

Written on 2:41 上午 by Yu Lai

今天在部落格裡加入了google-code-prettify。
http://code.google.com/p/google-code-prettify/
所以現在在文章中的程式碼,只要透過<pre class="prettyprint">...</pre>的方式,即可得到有highlight效果的呈現。以下是demo:

int main() {
printf("Hello World");
return 0;
}

[閒聊] 網誌改版

Written on 7:24 下午 by Yu Lai

買了Dell E228WFP後才發現,
原本的template已經被我改的只能用在1024x768下,
在寬螢幕下顯示都跑掉了.

於是就改版一下囉, 換了個template,
感覺還不錯 ^^

[技術] 使用Linux的mmap心得

Written on 11:40 上午 by Yu Lai

最近的工作有遇到一個用mmap解決的issue,
讓我了解到mmap原來也可以這樣使用.
以下是使用的心得, 寫下來分享一下.

一般我們在Linux中使用mmap不外乎是用來做IPC的實做,
或是配合driver的file node來操控外部的device,
或者是特殊的需求-加速存取or動態載入.

但我這次遇到的問題居然是空間的需求. 在採用Linux來實做
Embedded System時, 往往會使用Ramdisk或ramfs等技術
來implement出file system來. 而這類的file system有個特點-
它佔memory. 所以在存取較大的檔案時, e.g. image raw file.
若採用傳統malloc出空間再讀進此空間進行操作時, e.g. MD5
checksum, 勢必會遇到記憶不夠的情況.
(PS. 還意外知道原來Linux有oom-killer這東東 XD)

此時我採用了mmap來將原本就在memory裡的file另外對映到
其他記憶體空間中, 把這個當成pointer來操作, 而不用額外花費
真實的memory空間. 以下是相關的source code:

int fd;
struct stat fstat;

fd = open(TMPMD5, O_RDONLY);
stat(TMPMD5, &fstat);
image = mmap(NULL, fstat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if(image == MAP_FAILED) {
printf("Error.\n");
close(fd);
return -1;
}

[技術] Linux在x86與non-x86開機程序比較

Written on 1:28 上午 by Yu Lai

感謝jserv在blog中分享, 在IBM developerWorks上的好文章: [Migrating from x86 to PowerPC, Part 2: Anatomy of the Linux boot],探討 GNU/Linux 在不同硬體架構下的開機程序差異,這篇文章有兩張很好的附圖可作為比較:

典型 x86 Linux 啟動程序:



典型 ARM / PowerPC Linux 啟動程序:


[技術] 各家Database分頁實作

Written on 11:25 上午 by Yu Lai

Ref: http://blog.blueshop.com.tw/gpx1981/archive/2007/08/24/52129.aspx

DB2
1.1. SELECT * FROM STUDENT ORDER BY SCORE DESC fetch first 10 rows only
1.2. select * from ( SELECT rownumber() over(ORDER BY SCORE DESC) as row_,
* FROM STUDENT ORDER BY SCORE DESC ) as temp_ where row_ <= 10
2. select * from ( SELECT rownumber() over(ORDER BY SCORE DESC) as row_,
* FROM STUDENT ORDER BY SCORE DESC ) as temp_ where row_ between 11
and 20

Firebird
1. SELECT first 10 * FROM student ORDER BY score DESC
2. SELECT first 10 SKIP 10 * FROM student ORDER BY score DESC
 
HypersonicSQL(HSQL)
1. SELECT TOP 10 * FROM student ORDER BY score DESC
2. SELECT LIMIT 10 10 FROM student ORDER BY score DESC
 
Interbase
1. SELECT * FROM student ORDER BY score DESC ROWS 10
2. SELECT * FROM student ORDER BY score DESC ROWS 10 TO 10
 
MySQL
1. SELECT * FROM student ORDER BY score DESC LIMIT 10
2. SELECT * FROM student ORDER BY score DESC LIMIT 10, 10
 
Oracle
1. select * from ( SELECT * FROM STUDENT ORDER BY SCORE DESC ) where
rownum <= 10
2. select * from ( select err.*, rownum rownum_ from ( SELECT * FROM
errormsg order by seqno) err where rownum <= 20) where rownum_ > 10
 
PostgreSQL
1. SELECT * FROM student ORDER BY score DESC limit 10
2. SELECT * FROM student ORDER BY score DESC limit 10 OFFSET 10
 
SQLServer
1. SELECT top 10 * FROM STUDENT ORDER BY SCORE DESC
 
paged queries not supported
FrontBase, Informix, Ingres, Mckoi, NoArgSQL, Pointbase, Progress, SAPDB,
StandardSQL, Sysbase

[技術] vim的方向鍵問題

Written on 11:25 上午 by Yu Lai

原來我用了那麼久的vi,
今天總算知道怎麼解決ABCD亂跳
與backspace不會刪除的問題。

解決方法:在.vimrc中設定

    set nocompatible
set backspace=2