2010年5月29日 星期六

TCL Basic Syntax


這一篇是研究所時候寫的,幸好還找的到,所以把它貼出來。

TCL (Tool Command Language),TCL念做"tickle",TCL本身不支援物件導向,但是可以和其他物件導向語言結合。

顯示字串到console用puts

variable

設定變數用set:

set varName? value?

set a 10
puts $a

事實上在Tcl中,沒有字串與數字的區分。也就是說:

        set Lab good

        set Lab “good”

這兩行指令會是一樣的結果。

 

comment

Tcl的注解必須以#開頭,而Tcl以換行(\n)和分號 (;)為命令的結束,所以如果想在命令後面做註解,就必須寫成 ;#。

puts "test only" ;# test only

 

data type

Tcl和shell script一樣並不需要是先宣告任何資料型態,其資料型態會隨其給的值變動。

 

Quotes and Curly braces

雙引號把引號內的文字串成字串,變數還是會被解譯(substitutions)。

set a "Hello World!"

 

"{", "}" curly braces,和雙引號一樣,只是變數不會被解釋。

set a "Hello World!"
puts "$a"
puts {$a}

 

"[", "]"就像shell中的`會把括號內的文字當成指令執行,而執行結果則會取代整個[]。

set x 5
set y 10
set z "$x + $y is [expr $x + $y]"

 

另外backslash "\",會讓substitutions失效,如同其他language一樣,tcl也有提供Backslash Sequence。

String Output
\b   Backspace
\f   clear screen
\n   New Line
\r   Carriage Return
\t   Tab
\v   Vertical Tab

 

Control

if  {expr1} {body1} elseif {expr2} {body2} else {body}

set x 1
 
if {$x == 2} {
       puts "$x is 2"
} else {
       puts "$x is not 2"
}
 
if {$x != 1} {
       puts "$x is != 1"
} else {
       puts "$x is 1"
}

 

switch

Evaluate one of several scripts, depending on a given value

switch ?option? string {body}

% set x 1
1
% switch $x {
1 {puts "match 1"}
2 {puts "match 2"}
default {puts "no match"}
}
;# match 1  --> result

 

% set x 10
10
% switch $x {
1 {puts "match 1"}
2 {puts "match 2"}
default {puts "no match"}
}
# no match ---> result
% switch -regexp $x {
1 {puts "match 1"}
2 {puts "match 2"}
default {puts "no match"}
}
# match 1 ---> result

 

loop

while {test} {body}

set x 0
while {$x < 5} {
     set x [expr $x + 1]
     if {$x > 7} break
     if "$x > 3" continue
     puts "x is $x"
}

 

for {start} {test} {next} {body}

for {set x 1} {$x < 10} {incr x 2} {
     puts "x = $x"
}

 

新增命令 -- procedure

TCL可以使用proc建立一個新的命令,其格式如下。

proc name { args }  {
     body
}

proc會建立一個名為name的命令,並且攜帶參數args,以及程式碼body。如果最後一個參數名稱為args,那就類似C的不定參數"..."。

範例:

proc sum {arg1 arg2} {
    set x [expr {$arg1 + $arg2}];
    return $x
}

proc printall {args} {
    foreach j $args {
        puts "$j"
    }
}

proc x {a {b 2}} { #give default vaule for b
    puts $a
    puts $b
}

 

Associative Array

associative array其實就是hash table,給一個Key(Tcl稱為element)會傳回一個value。其範例如下:

set A(1) "one"
set A(2) "two"
set A(Three) "three"
array set B { 1 "one" 2 "two" 3 "three" }
 
array names A
foreach thing [array names A] {
   puts "$A($thing)"
}

 

array set arrayName list

建立陣列,list 必須以 key value形式組成。

 

array size arrayName

傳回陣列大小。

 

array names arrayName ?mode? ?pattern?

 如果只有array names arrayName將會回傳所有的key,否則您也可以用正規表示式搜尋key是否存在。

 

array unset arrayName ?pattern?

如果沒有指明pattern,會將整個array註銷,否則會比對pattern和key是否相同,如果有會註銷該元素 (key),否則會回傳空字串(empty string)。

 

array exists arrayName

如果陣列存在會回傳1,否則會回傳0。

 

array get arrayName ?pattern?

如果沒有指明pattern會將array整個以key value的形式傳回。如果有指明pattern則會搜尋是否有符合的key,有的話會一樣以key value傳回,否則傳回空字串。

 

array statistics arrayName

會將array的資訊顯示出來(distribution of data within the hash table)。

 

array startsearch arrayName

這是用來初始化搜尋的指令,會回傳search-ID,可用於array nextelementarray donesearch指令。

 

array nextelement arrayName searchId

傳回array的key。如果array被新增或刪除,則Tcl會自動呼叫array donesearch終止目前的搜尋。

 

array donesearch arrayName searchId

終止array的搜尋,並且註銷array的search-ID。

 

array anymore arrayName searchId

 

 

更多的tcl tutorial(tcl8.5)

 


學貴專精


今天看到一篇文章寫的不錯把他轉錄過來。

很久以前,有一個年輕人,立志要成為一個武林高手。於是就到了少林寺拜師,學了一年後,他覺得已經學好了少林武功,便離開了少林,急著要下山找人比武。在山下遇到了一個武當的弟子,打了幾回合後,他輸了。於是心裡面想著,好像是武當派比較厲害,便又到了武當學武。

過了一年,武當武功他又懂了點門道,心想我不會輸了,下山跟峨嵋派打,還是輸了……。就這樣過了好幾年,他覺得他什麼門派的武功都會了,但為什麼還是無法成為武林高手?

於是他對於人生絕望,走到河邊,要跳下去時,被過去教他少林武功的老和尚抓了一把。年輕人心酸的把他這幾年學武所受到的挫折一五一十的告訴老和尚。老和尚抓了抓他的鬍子,問年輕人說:「孩子,你這幾年學了這麼多武功,有沒有一種是你覺得綀起來最順手的呢?」 年輕人說:「有啊,每當我一使出少林棍法的時侯,就覺得特別有力道。
可是我心裡面想像的武林高手,應該是要精通各 門派的武功才能算是高手吧!」老和尚告訴他,既然你對於少林棍法特別有把握,那麼你就應該要忘了其它門派的武功,因為它並不適合你。

年輕人說:「可是我看別人在使他們自已門派的武功時,都好厲害。」只見老和尚笑了笑說:「如果真的有一個高手能將所有門派的武功都發揮到極致,那麼幾百年來,就不會有那麼多個門派立足了。
如果你想成為高手,就要把適合你的武功綀好,而不是天下的武功都想綀。」於是年輕人改變了他的想法,開始專注於綀他所熟悉的少林棍法。直到有一天,他成 為了少林的老和尚……

http://sites.google.com/site/tradersland/turtle-farm/trading-phycology

我的心得是:以前我常常覺得要學會很多,才叫做厲害,後來其實發現我們要學的是態度以及方法,執著的態度和做事情的方法,把一件事情最到最好,自然就會成為這個領域中的佼佼者。說到這個,又讓我想到樂天董事長說過一句話「每天改善1%,一年後強大37倍」。


install ns2


NS2是研究所時候玩的一個Network Simulator,今天忽然心血來潮的回味一下,下載網址

我下載了ns-allinone-2.35-RC4,解開後執行裡面的install即可。安裝過程中,我只有遇到can't find X includes
checking for X11 header files
can't find X includes
otcl-1.14 configuration failed! Exiting ...
Please check http://www.isi.edu/nsnam/ns/ns-problems.html
for common problems and bug fixes.
透過安裝libsx-dev即可解決
sudo apt-get install libsx-dev


安裝成功後應該會出現一些重要的訊息,包含將執行目錄加到您的PATH中:
Please put ns-allinone-2.35/bin:ns-allinone-2.35/tcl8.5.8/unix:ns-allinone-2.35/tk8.5.8/unix
into your PATH environment; so that you'll be able to run itm/tclsh/wish/xgraph.

IMPORTANT NOTICES:

(1) You MUST put ns-allinone-2.35/otcl-1.14, ns-allinone-2.35/lib, 
    into your LD_LIBRARY_PATH environment variable.
    If it complains about X libraries, add path to your X libraries 
    into LD_LIBRARY_PATH.
    If you are using csh, you can set it like:
                setenv LD_LIBRARY_PATH <paths>
    If you are using sh, you can set it like:
                export LD_LIBRARY_PATH=<paths>

(2) You MUST put ns-allinone-2.35/tcl8.5.8/library into your TCL_LIBRARY environmental
    variable. Otherwise ns/nam will complain during startup.

After these steps, you can now run the ns validation suite with
cd ns-2.35; ./validate

For trouble shooting, please first read ns problems page 
http://www.isi.edu/nsnam/ns/ns-problems.html. Also search the ns mailing list archive
for related posts.

接下來就是執行一下ns2內建的一些tcl檔:
brook@ubuntu:~/src/ns2$ PATH=/home/brook/src/ns2/ns-allinone-2.35/bin:/home/brook/src/ns2/ns-allinone-2.35/tcl8.5.8/unix:/home/brook/src/ns2/ns-allinone-2.35/tk8.5.8/unix:$PATH
brook@ubuntu:~/src/ns2$ ns ns-allinone-2.35/ns-2.35/tcl/ex/simple.tcl 
210
0.0037499999999999999
running nam...




2010年5月22日 星期六

Netlink introduction


Netlink被用來當作kernel和user space之間溝通資訊的方式之一,使用標準的socket介面來作為Netlink的API,其address family必須填AF_NETLINK,而socket type為SOCK_RAW或SOCK_DGRAM,protocol則根據不同的netlink group不同而有所不同,如NETLINK_ROUTE或NETLINK_GENERIC等等(詳細資訊可以man 7 netlink)。

socket = socket(AF_NETLINK, SOCK_RAW, netlink_family);

Netlink Socket Address Structure

如同一般的socket,Netlink也需要socket address,其socket address為:
struct sockaddr_nl {
    sa_family_t     nl_family;  /* AF_NETLINK */
    unsigned short  nl_pad;     /* Zero. */
    pid_t           nl_pid;     /* Process ID. */
    __u32           nl_groups;  /* Multicast groups mask. */
};
如果傳送的對象是kernel或者以multicast傳送,則nl_pid設為0。如果是kernel傳送給user-space上面的application時(multicast),就會填入正確的pid,然而nl_pid實際的意義並不是指PID,而只是用於識別一個netlink socket而已,對於application在建立一個netlink socket時,可以將nl_pid設為0,然後bind(),kernel會自動將PID填入。而nl_groups是用multicast,採用bit mask方式,所以每個netlink family有32個multicast group。

Netlink Format

Netlink message包含一個或多個struct nlmsghdr,主要用於辨識後面的payload內容為何。
struct nlmsghdr {
    __u32 nlmsg_len;    /* Length of message including header. */
    __u16 nlmsg_type;   /* Type of message content. */
    __u16 nlmsg_flags;  /* Additional flags. */
    __u32 nlmsg_seq;    /* Sequence number. */
    __u32 nlmsg_pid;    /* PID of the sending process. */
};

所以常見的讀取netlink message形式如下:
  int len;
  char buf[4096];
  struct iovec iov = { buf, sizeof(buf) };
  struct sockaddr_nl sa;
  struct msghdr msg;
  struct nlmsghdr *nh;

  msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
  len = recvmsg(fd, &msg, 0);
  for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
    nh = NLMSG_NEXT (nh, len)) {
    /* The end of multipart message. */
    if (nh->nlmsg_type == NLMSG_DONE)
      return;
    if (nh->nlmsg_type == NLMSG_ERROR)
      /* Do some error handling. */
      ...
    /* Continue with parsing payload. */
    ...
  }


Macro

Netlink也提供一些macro來操作這些netlink datagram,因為kernel和user-space溝通會有align的問題,所以不論是在組packet或者parse packet,都請用這些macro。
#define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN  ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len)  ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
      (struct nlmsghdr*)(((char*)(nlh)) + \
                                 NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
      (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
      (nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
NLMSG_ALIGN()很明顯的就是在做align。
NLMSG_HDRLEN()回傳struct nlmsghdr所占的大小。
NLMSG_LENGTH()回傳len + struct nlmsghdr所占的大小,通常用於填struct nlmsghdr的nlmsg_len用。
NLMSG_SPACE()回傳len + struct nlmsghdr再取align的大小,也就是netlink message的大小。
NLMSG_DATA()回傳nlh往後一個struct nlmsghdr所占的大小,就是取struct nlmsghdr後面跟著的資料。
NLMSG_NEXT()取得下一個struct nlmsghdr,並且將len減去原本的nlmsg_len,就等同在算剩餘大小。
NLMSG_OK()先算剩餘長度是否大於等於一個struct nlmsghdr,再算這個nlmsg_len是否大於等於一個struct nlmsghdr,而且nlmsg_len還要小於剩餘長度(len),如果都符合,就算是一個OK的struct nlmsghdr。

各macro與netlink message之間的關係。

Common API

基於netlink family基本上都是大同小異,所以參考Document/accounting/getdelays.c寫了一些API來用。
static int create_nl_socket(int proto)
{
    int sock;
    struct sockaddr_nl addr;

    if ((sock = socket(AF_NETLINK, SOCK_RAW, proto)) < 0) {
        fprintf(stderr, "open sock failed.(%s)\n", strerror(errno));
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;

    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        fprintf(stderr, "bind failed.(%s)\n", strerror(errno));
        goto bind_err;
    }

    return sock;

bind_err:
    close(sock);
    return -1;
}


這個章節單純的只對netlink提供一些overview,後面會針對各個netlink family有更詳細的描述。



2010年5月19日 星期三

word不能存檔問題


這兩天電腦的word忽然都不能存檔,即便是另存新檔也不行,最後都只能放棄修改檔案,即便重新安裝過或者更新成2007也都不能存檔,最後就乖乖的google一下,原來是暫存的資料夾不存在,按照以下方式就可以解決了。
資料來源: word 2003不能存檔問題

編輯機碼的(regedit)
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Cache改成存在的暫存目錄就好了。