摘錄於Version Control with Subversion (for Subversion 1.5)之電子書
針對在svn常見的名詞 "changesets", 提供了清楚的定義
Changesets
Before we proceed further, we should warn you that there's going to be a lot of discussion of “changes” in the pages ahead. A lot of people experienced with version control systems use the terms “change” and “changeset” interchangeably, and we should clarify what Subversion understands as a changeset.
Everyone seems to have a slightly different definition of changeset, or at least a different expectation of what it means for a version control system to have one. For our purposes, let's say that a changeset is just a collection of changes with a unique name. The changes might include textual edits to file contents, modifications to tree structure, or tweaks to metadata. In more common speak, a changeset is just a patch with a name you can refer to.
In Subversion, a global revision number N names a tree in the repository: it's the way the repository looked after the Nth commit. It's also the name of an implicit changeset: if you compare tree N with tree N−1, you can derive the exact patch that was committed. For this reason, it's easy to think of revision N as not just a tree, but a changeset as well. If you use an issue tracker to manage bugs, you can use the revision numbers to refer to particular patches that fix bugs—for example, “this issue was fixed by r9238.” Somebody can then run svn log -r 9238 to read about the exact changeset that fixed the bug, and run svn diff -c 9238 to see the patch itself. And (as you'll see shortly) Subversion's svn merge command is able to use revision numbers. You can merge specific changesets from one branch to another by naming them in the merge arguments: passing -c 9238 to svn merge would merge changeset r9238 into your working copy.
簡要說明: "changesets"在svn中, 真正代表的意義是, 在commit時, 此時間點下, 異動到的檔案, 皆可視為"changesets", 而使用者可以藉由svn log -r9238, 或svn diff -r9238, 清楚得知該次異動到檔案
衍生說明: 同一時間點內, 儘可能增修一個bug, 一個fuction , 一個procedure, 隨即進行一次commit, 極力不建議增修多個bug, 多個fuction, 多個procedure, 才進行一次的commit
舉例說明: user A增加一個fuction CallPhone(), 也修改一個function SetRing(), 實際上2個function是不相干的, CallPhone()是新增需求, SetRing()是修改流程, 卻同時進行commit, 當日後user B發現CallPhone()有問題, 卻很難將之移除, 須額外花費時間判斷哪些部份的程式碼是因應Call Phone而增修的, 造成極大的困擾及風險
2011年9月11日 星期日
2010年12月5日 星期日
core dump 命名設定
往往每一發現core dump產生, 系統預設產生檔名為core.pid, 還得由log去查看是哪支程式的pid, 實在很不直覺化
首先, linux針對code dump的命名設定, 參考於/proc/sys/kernel/core_pattern
預設值為"core", 可使用的命名變數如下:
個人習慣core dump可以得知哪支程式產生, 所以命名式為 "core.%e.%p"
以上大功告成!!
首先, linux針對code dump的命名設定, 參考於/proc/sys/kernel/core_pattern
$> more /proc/sys/kernel/core_pattern
預設值為"core", 可使用的命名變數如下:
%p : pid
%% : output one %
%u : uid
%g : gid
%s : signal number
%t : time of dump
%h : host name
%e : executable filename
%: % is dropped
%: both are dropped
個人習慣core dump可以得知哪支程式產生, 所以命名式為 "core.%e.%p"
$> echo "core.%e.%p" > /proc/sys/kernel/core_pattern
或
$> vi /etc/sysctl.conf
kernel.core_pattern = core.%e.%p
以上大功告成!!
2010年12月4日 星期六
connect() raise No route to host and recv() raise Resource temporarily unavailable
當client socket 與 server 正常連線下, 中繼switch的網路線被短暫拔插時..
(1) close client socket
正常程序client socket當send(), 會偵測到網路已斷開, 此時須close()
(2) try to connect to server
正常程序client socket會試著建立新連線, 但由於switch須一段時間才會恢復,
connect()會引發ENETUNREACH (No route to host), 表示無法順利連線,
此時建議sleep()數秒, 再試著重新connect(), 直到成功建立連線
(3)send alive mssage and recv ack
正常程序client socket成功建立連線後, 會試著send() alive massage,
並recv() ack, 以表示雙方ap已確立建立連線..
若recv() with non-block, 猜測server此時重新binding socket,
recv()會引發EAGAIN (Resource temporarily unavailable),
表示sokcet無任何資料可以讀取, 建議捨棄此次alive massge作業,
sleep()數秒, 再進行一次send() alive message,
亦或是, sleep()1秒, 再進行recv() ack, 若重覆3次, 依舊無資料可讀取,
捨棄此次alive massage作業, sleep()數秒, 再進行一次send() alive message
man recv ::
If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)), in which case the value -1 is returned and the external variable errno set to EAGAIN. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.
(1) close client socket
正常程序client socket當send(), 會偵測到網路已斷開, 此時須close()
(2) try to connect to server
正常程序client socket會試著建立新連線, 但由於switch須一段時間才會恢復,
connect()會引發ENETUNREACH (No route to host), 表示無法順利連線,
此時建議sleep()數秒, 再試著重新connect(), 直到成功建立連線
(3)send alive mssage and recv ack
正常程序client socket成功建立連線後, 會試著send() alive massage,
並recv() ack, 以表示雙方ap已確立建立連線..
若recv() with non-block, 猜測server此時重新binding socket,
recv()會引發EAGAIN (Resource temporarily unavailable),
表示sokcet無任何資料可以讀取, 建議捨棄此次alive massge作業,
sleep()數秒, 再進行一次send() alive message,
亦或是, sleep()1秒, 再進行recv() ack, 若重覆3次, 依舊無資料可讀取,
捨棄此次alive massage作業, sleep()數秒, 再進行一次send() alive message
man recv ::
If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)), in which case the value -1 is returned and the external variable errno set to EAGAIN. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.
2010年2月18日 星期四
當VMWare出現"The Virtual Machine appears to be in use..."
當執行VMware時, 偶發一次發生出現這樣的訊息, "The Virtual Machine appears to be in use..."
其guest os再也無法開機, 原來它會建立lock file or lock path,
一旦偵測有其lock file path存在, 便不會讓相同的guest os重覆執行, 是種保護機制,
所以依照下述步驟, 便可解除這樣的問題:
1. 進入virtual machine安裝guest os的資料夾
2. 將*.lck的資料夾, 重新更名為其它名稱, 亦或者將它們刪除
3. 重新啟動guest os
其guest os再也無法開機, 原來它會建立lock file or lock path,
一旦偵測有其lock file path存在, 便不會讓相同的guest os重覆執行, 是種保護機制,
所以依照下述步驟, 便可解除這樣的問題:
1. 進入virtual machine安裝guest os的資料夾
2. 將*.lck的資料夾, 重新更名為其它名稱, 亦或者將它們刪除
3. 重新啟動guest os
2010年2月13日 星期六
調整TCP TIME_WAIT, 快速釋放連線資料
在參閱TCP TIME_WAIT的釋義一文後,
了解到系統須等待2MSL時間, 才進入CLOSED狀態, 關閉連線
在linux RedHat AS4中, 執行$>netstat -tnao, 會發現到,
主動斷線端處理TIME_WAIT後, 須等待60秒, 才會真正關閉連線
哪有什麼方式可以縮短TIME_WAIT的等待時間呢??
方法一.
$> vi /etc/sysctl.conf
## 表示開啟重用機制, 允許socket在TIME_WAIT狀態下, 重新bind新的socket
net.ipv4.tcp_tw_reuse = 1
## 表示開啟回收機制, 允許socket在TIME_WAIT狀態下, 被快速回收, 毋須等待2MSL
net.ipv4.tcp_tw_recycle = 1
$> /sbin/sysctl -p ## 使上述設定生效
方法二.
## 查看系統預設TIME_WAIT時間
$> more /proc/sys/net/ipv4/tcp_fin_timeout
## 修改系統預設TIME_WAIT時間
$> echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
方法三.
在setsockopt()時, 設置SO_LINGER之屬性,
linger.l_onoff 表示開啟延遲功能
linger.l_linger 表示延遲時間為0秒
了解到系統須等待2MSL時間, 才進入CLOSED狀態, 關閉連線
在linux RedHat AS4中, 執行$>netstat -tnao, 會發現到,
主動斷線端處理TIME_WAIT後, 須等待60秒, 才會真正關閉連線
哪有什麼方式可以縮短TIME_WAIT的等待時間呢??
方法一.
$> vi /etc/sysctl.conf
## 表示開啟重用機制, 允許socket在TIME_WAIT狀態下, 重新bind新的socket
net.ipv4.tcp_tw_reuse = 1
## 表示開啟回收機制, 允許socket在TIME_WAIT狀態下, 被快速回收, 毋須等待2MSL
net.ipv4.tcp_tw_recycle = 1
$> /sbin/sysctl -p ## 使上述設定生效
方法二.
## 查看系統預設TIME_WAIT時間
$> more /proc/sys/net/ipv4/tcp_fin_timeout
## 修改系統預設TIME_WAIT時間
$> echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
方法三.
在setsockopt()時, 設置SO_LINGER之屬性,
linger.l_onoff 表示開啟延遲功能
linger.l_linger 表示延遲時間為0秒
struct linger opt_linger = { 0,0 };
opt_linger.l_onoff = 1;
opt_linger.l_linger = 0;
if (::setsockopt(SSock, SOL_SOCKET, SO_LINGER, (const char *)&opt_linger, sizeof(linger)) == -1) {
ap_log (ERROR, "setsockopt(LINGER) fail");
return false;
}
2009年8月26日 星期三
如何防止彊屍程序(zombie)的產生??
當執行program ex1程式片段後, 試著以kill prog1的方式終止prog1之程序,
結果查詢目前各程序執行狀況(ps -ef), 發現出現[prog1],
接下來無論怎麼kill prog1, 都無法將其消滅, 唯有中止main(), 它才會消失...
原來它就是僵屍程序(zombie), 何謂僵屍程序呢??
補救辦法是殺死僵屍程序的父程序(僵屍程序的父程序必然存在),
僵屍程序成為"孤兒程序",過繼給pid=1的程序init,init始終會自行負責清理僵屍進程。
僵屍程序之範例:
解決一.
在父程序設置SIGCHLD信號的處理函式, 使其父程序自動忽略子程序的狀態變更,
但長期常駐程式, 可能不適用, 難保不會出現系統資源耗用的現象
解決二.
在父程序設置SIGCHLD信號的處理函式, 並呼叫waitpid(), 等待捕獲子程序的返回狀態
解決三.
呼叫2次fork(), 父程序呼叫fork(第一次)產生子程序, 子程序再呼叫fork(第二次)產生孫程序,
隨即子程序終結死亡, 此時孫程序變為"孤兒程序",init程序會接管孫程序, 變成它的父程序,
而init程序會自行負責處理SIGCHLD信號
結果查詢目前各程序執行狀況(ps -ef), 發現出現[prog1]
接下來無論怎麼kill prog1, 都無法將其消滅, 唯有中止main(), 它才會消失...
原來它就是僵屍程序(zombie), 何謂僵屍程序呢??
在fork()/execve()過程中,假設子程序結束時父程序仍存在,
而父程序fork()之前既沒設置SIGCHLD信號處理函數調用waitpid()等待子進程結束,
又沒有設置忽略該信號,則子程序成為僵屍程序,無法正常結束,
即使是root身份kill -9也不能殺死僵屍程序。
補救辦法是殺死僵屍程序的父程序(僵屍程序的父程序必然存在),
僵屍程序成為"孤兒程序",過繼給pid=1的程序init,init始終會自行負責清理僵屍進程。
僵屍程序之範例:
int main (int argc, char *argv[])
{
char *prog_list = {"prog1","prog2", "prog3"};
for (int i=0; i<3; i++) {
char *arg_list = {prog_list[i], NULL};
forkExecProc (prog_list[i], arg_list);
}
while (true) {
sleep (2);
}
return 0;
}
int forkExecProc (char *prog, char **arg_list)
{
pid_t child;
/* check if fork fail that first child is not created */
if ((child = fork ())< 0) {
fprintf (stderr, "fork error");
} else if (child == 0) { /* run into first child */
fprintf (stdout, "fork to execute : [%s]\n", arg_list);
/* replaces the current process image with a new process image */
execvp(prog, arg_list);
/* if execvp() is return, mean that on error */
fprintf(stderr, "execvp error");
exit(0);
}
return child;
}
解決一.
在父程序設置SIGCHLD信號的處理函式, 使其父程序自動忽略子程序的狀態變更,
但長期常駐程式, 可能不適用, 難保不會出現系統資源耗用的現象
int main (int argc, char *argv[])
{
signal (SIGCHLD,SIG_IGN); //設置SIGCHLD
char *prog_list = {"prog1","prog2", "prog3"};
for (int i=0; i<3; i++) {
char *arg_list = {prog_list[i], NULL};
forkExecProc (prog_list[i], arg_list);
}
while (true) {
sleep (2);
}
return 0;
}
int forkExecProc (char *prog, char **arg_list)
{
...
}
解決二.
在父程序設置SIGCHLD信號的處理函式, 並呼叫waitpid(), 等待捕獲子程序的返回狀態
void sig_fork(int signo)
{
pid_t pid;
int stat;
// 呼叫waitpid(),等待子程序返回, 若無子程序返回, 也不一直等待
pid=waitpid(0,&stat,WNOHANG);
return;
}
int main (int argc, char *argv[])
{
signal (SIGCHLD, sig_fork); // 設置SIGCHLD, 並呼叫waitpid(), 捕獲子程序的返回狀態
char *prog_list = {"prog1","prog2", "prog3"};
...
return 0;
}
int forkExecProc (char *prog, char **arg_list)
{
pid_t child;
/* check if fork fail that first child is not created */
if ((child = fork ())< 0) {
fprintf (stderr, "fork error");
} else if (child == 0) { /* run into first child */
fprintf (stdout, "fork to execute : [%s]\n", arg_list);
/* replaces the current process image with a new process image */
execvp(prog, arg_list);
/* if execvp() is return, mean that on error */
fprintf(stderr, "execvp error");
exit(0);
}
/* no block to wait for first child chang state */
/* must be use signal (SIGCHLD, xxx) to fetch child change state */
waitpid (-1, NULL, WNOHANG); // 父程序呼叫waitpid(),不阻塞等待子程序的返回狀態, 待引發SIGCHLD
return child;
}
解決三.
呼叫2次fork(), 父程序呼叫fork(第一次)產生子程序, 子程序再呼叫fork(第二次)產生孫程序,
隨即子程序終結死亡, 此時孫程序變為"孤兒程序",init程序會接管孫程序, 變成它的父程序,
而init程序會自行負責處理SIGCHLD信號
int main (int argc, char *argv[])
{
char *prog_list = {"prog1","prog2", "prog3"};
for (int i=0; i<3; i++) {
char *arg_list = {prog_list[i], NULL};
forkExecProc (prog_list[i], arg_list);
}
while (true) {
sleep (2);
}
return 0;
}
int TaskHandler::forkExecProc (char *prog, char **arg_list)
{
pid_t child;
/* check if fork fail that first child is not created */
if ((child = fork ())< 0) { // 產生子程序
fprintf (stderr, "fork error");
} else if (child == 0) { /* run into first child */
/* check if fork fail that second child is not created */
if ((child = fork ())< 0) { // 產生孫程序
fprintf (stderr, "fork error");
}
else if (child > 0) { /* run into parent of second child whick is first child */
/* terminate the first child, in order that second child's parent becomes init */
exit(0); // 子程序自行終結, 此時孫程序被init接管為它的父程序
}
else { /* run into second child */
// 孫程序繼續執行下列步驟
fprintf (stdout, "fork to execute : [%s]\n", arg_list);
/* replaces the current process image with a new process image */
execvp(prog, arg_list);
/* if execvp() is return, mean that on error */
fprintf(stderr, "execvp error");
exit(0);
}
}
/* wait for first child chang status */
waitpid (child, NULL, 0); // 父程序呼叫waitpid(), 等待子程序終結,並捕獲返回狀態
return child;
}
2009年7月5日 星期日
dblink of postgresql
現今在承接南部第一大鋼鐵廠的資訊系統工程後, 遭遇到必須連線至遠端的postgresql,
擷取所需的資料, 並不透過Tcp/Ip Socket進行訊息封包的傳送
便回想當初在第一家電子公司當小小MIS, 便曾使用過Oracle其一功能, 簡稱db link,
不必在ap上, 另外多建立一個資料庫連線, 可利用原資料庫連線擷取另遠端資料庫的功能
於是上網google, 果不其然postgresql也支援著類似的功能, 不愧是自由軟體界資料庫第一把交椅,
而安裝動作也很簡單, 整理如下所述:
## 安裝 (至存放原始安裝檔之路徑)
$> cd contrib/dblink
$> make
$> make install
## dblink相關函式安裝 (至postgresql安裝目錄之路徑)
## 此時會新增兩個檔案 pgsql/lib/dblink.so(函式庫) & pgsql/share/contrib/dblink.sql(語法安裝)
$> su - postgres
$> cat dblink.sql psql
參考網址: db link sql
擷取所需的資料, 並不透過Tcp/Ip Socket進行訊息封包的傳送
便回想當初在第一家電子公司當小小MIS, 便曾使用過Oracle其一功能, 簡稱db link,
不必在ap上, 另外多建立一個資料庫連線, 可利用原資料庫連線擷取另遠端資料庫的功能
於是上網google, 果不其然postgresql也支援著類似的功能, 不愧是自由軟體界資料庫第一把交椅,
而安裝動作也很簡單, 整理如下所述:
## 安裝 (至存放原始安裝檔之路徑)
$> cd contrib/dblink
$> make
$> make install
## dblink相關函式安裝 (至postgresql安裝目錄之路徑)
## 此時會新增兩個檔案 pgsql/lib/dblink.so(函式庫) & pgsql/share/contrib/dblink.sql(語法安裝)
$> su - postgres
$> cat dblink.sql psql
參考網址: db link sql
2009年5月23日 星期六
Difference between Big Endian and Little Endian
Difference between Big Endian and Little Endian
原文釋意:
"Little Endian" means that the low-order byte of the number is stored in memory at the lowest address, and the high-order byte at the highest address. (The little end comes first address.)
"Big Endian" means that the high-order byte of the number is stored in memory at the lowest address, and the low-order byte at the highest address. (The big end comes first address.)
中文釋意:
為什麼叫『大頭』派?因為電腦把『大』的位數放在『前面』 (記憶體編號小的就是前面)。就好像我們寫十進制數字 123 的意思一百二十三 (100 + 20 + 3),也就是最大位--百位,寫在前面。
相反地,如果把『小』的位數放在『前面』,那就是『小頭』派了。如果有一個民族的文字,把 123 解釋成三百二十一 (1 + 20 + 300),那他們就是『小頭派』。
阿拉伯文的文字書寫,是從右向左橫寫,但是遇到數字的時候,卻是跟我們一樣從左向右寫。如果阿拉伯人讀文字與數字的時候,都是從右向左讀,則他們會先讀到數字的最小位。在這個意義之下,阿拉伯人是『小頭派』。
int i = 2562 + 2x256 + 3 = 00000000 00000001 00000010 00000011 位元排列方式 = 0 1 2 3 無號整數方式
CPU 一定會配給連續四個記憶體給 i,但是這四個記憶體,卻有兩種放置四個 byte 的可能順序。如果我們一律按照記憶體位址從小到大的順序來講,則四個記憶體放置的字元可能是先 00000000 然後 00000001 然後 00000010 最後 00000011
Lo-------------->Hi (Big Endian)
+-+-+-+-+-+-+-+-+-
00 01 02 03
+-+-+-+-+-+-+-+-+-
Hi<--------------Lo (Little Endian)
原文釋意:
"Little Endian" means that the low-order byte of the number is stored in memory at the lowest address, and the high-order byte at the highest address. (The little end comes first address.)
"Big Endian" means that the high-order byte of the number is stored in memory at the lowest address, and the low-order byte at the highest address. (The big end comes first address.)
中文釋意:
為什麼叫『大頭』派?因為電腦把『大』的位數放在『前面』 (記憶體編號小的就是前面)。就好像我們寫十進制數字 123 的意思一百二十三 (100 + 20 + 3),也就是最大位--百位,寫在前面。
相反地,如果把『小』的位數放在『前面』,那就是『小頭』派了。如果有一個民族的文字,把 123 解釋成三百二十一 (1 + 20 + 300),那他們就是『小頭派』。
阿拉伯文的文字書寫,是從右向左橫寫,但是遇到數字的時候,卻是跟我們一樣從左向右寫。如果阿拉伯人讀文字與數字的時候,都是從右向左讀,則他們會先讀到數字的最小位。在這個意義之下,阿拉伯人是『小頭派』。
int i = 2562 + 2x256 + 3 = 00000000 00000001 00000010 00000011 位元排列方式 = 0 1 2 3 無號整數方式
CPU 一定會配給連續四個記憶體給 i,但是這四個記憶體,卻有兩種放置四個 byte 的可能順序。如果我們一律按照記憶體位址從小到大的順序來講,則四個記憶體放置的字元可能是先 00000000 然後 00000001 然後 00000010 最後 00000011
Lo-------------->Hi (Big Endian)
+-+-+-+-+-+-+-+-+-
00 01 02 03
+-+-+-+-+-+-+-+-+-
Hi<--------------Lo (Little Endian)
2009年4月22日 星期三
How to read .ini file by using glib
在Windows API中, 提供相當方便的函式庫, 可以簡單地讀取.ini檔案,
但在c++ standard library中, 卻不見著任何蹤跡,雖說自己很喜歡coding, "蛋"不是這麼搞的啦!!
google search提供了一個相當不錯的工具 -- glib
不免俗地要介紹一下本文主角- glib 。
gnome是基於gtk+開發的一套桌面環境,gnome和KDE作為兩大最流行的桌面環境,在全世界廣泛使用。 只要是在Linux下工作的開發人員,對於gtk+一定不陌生。 而對於glib,這個gtk+下的無名英雄,其功能強大卻鮮為人知。
glib不是glibc,儘管兩者都是基於GPL的開源軟體。但這一字之差卻誤之千里,glibc是GNU實現的一套標準C的庫函數,而glib是gtk+的一套函數庫。
在linux平臺上,像其他任何軟體一樣,glib依賴於glibc。glib不是一個學院派的東西,也不是憑空想出來的,完全是在開發gtk+的過程中,慢慢總結和完善的結果。
如果你是一個工作3年以上的C語言程式師,現在讓你講講寫程式的苦惱,你可能有很多話要說,但如果你有時間研究一下glib,你會發現,很多苦惱已不再成其為苦惱,glib裏很多東西正是你期望已經久的。
gobject是glib的精粹,glib是用C實現的,但在很大程式是基於面向物件思想設計的,gobject是所有類的基類。signal在其中也是一大特色,signal與作業系統中的signal並不一樣,它是類似消息一樣的東西,讓消息在各個物件間傳遞,但儘量降低物件間的耦合。
1. setup the glib
$> ./configure2. include glib header files and library to compile
$> make
$> make install
##顯示glib include的路徑
$> pkg-config --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
##顯示glib library的路徑
$> pkg-config --libs glib-2.0
-L/usr/lib -lm -lglib-.20
並在程式的標頭檔加入下列文字
#include "glib.h"
完成上述兩個簡單的步驟, 就可以親身去體會glib的強大之處囉!!
參考來源::
GLib Reference ManualWiki GLib
2009年4月14日 星期二
指標的指標 (pointer to pointer)
int **iptr;
上面是宣告了一個指標指向另一int的指標, 很饒舌對吧!簡單說, 就是指標的指標 (pointer to pointer)
何以需要這樣的用法?在網路上拜讀了某位前輩的文章的範例, 突然間茅塞頓開...
上述例子, 印出來的數值仍為1, 因為changePtr的pInt是localPtr的複本, 對pInt做變更, 其實並不會影響到localPtr本身
使用call by pointer (or address)來傳遞參數, 被呼叫的函式只是複製pointer的值過去罷了!
所以當我們想在函式內改變外來的pointer的值(非pointer所指向的變數), 且函式外部能使用其改變的pointer的值, 此刻就是call by pointer to pointer登場的最佳機會!
下述例子, 印出來的數值變為gint的0, changePtr()的pInt是&localPtr的複本, 對其做任何變更, 並不會去影響到localPtr本身, 但在changePtr(), 我們是對pInt所指向的內容(就是localPtr)做變更, 由原本存放local_int的address, 變更為存放gind的address
上面是宣告了一個指標指向另一int的指標, 很饒舌對吧!簡單說, 就是指標的指標 (pointer to pointer)
何以需要這樣的用法?在網路上拜讀了某位前輩的文章的範例, 突然間茅塞頓開...
int gint = 0;
void changePtr (int *pInt)
{
pInt = &gint;
}
void main ()
{
int local_int = 1;
int *localPtr = &local_int;
changePtr (localPtr);
printf ("%d\n", *localPtr);
}
上述例子, 印出來的數值仍為1, 因為changePtr的pInt是localPtr的複本, 對pInt做變更, 其實並不會影響到localPtr本身
使用call by pointer (or address)來傳遞參數, 被呼叫的函式只是複製pointer的值過去罷了!
所以當我們想在函式內改變外來的pointer的值(非pointer所指向的變數), 且函式外部能使用其改變的pointer的值, 此刻就是call by pointer to pointer登場的最佳機會!
下述例子, 印出來的數值變為gint的0, changePtr()的pInt是&localPtr的複本, 對其做任何變更, 並不會去影響到localPtr本身, 但在changePtr(), 我們是對pInt所指向的內容(就是localPtr)做變更, 由原本存放local_int的address, 變更為存放gind的address
int gint = 0;
void changePtr (int **pInt)
{
*pInt = &gint;
}
void main ()
{
int local_int = 1;
int *localPtr = &local_int;
changePtr (&localPtr);
printf ("%d\n", *localPtr);
}
2009年3月22日 星期日
如何在vim支援doxygen彩色語法
若在vim中, 可以支援doxygen的 彩色語法, 一定可以大大增加可讀性
沒想到, 這是真的, 這下子在註解時, 更可以把doxygen發揮到極限
其實步驟非常簡單:
參考來源:
Doxygen syntax coloring in vim
沒想到, 這是真的, 這下子在註解時, 更可以把doxygen發揮到極限
其實步驟非常簡單:
- 於home directory下, 建立.vim/after/syntax的目錄
- 下載doxygen.zip (v1.15)
- 解壓縮上述檔案, 將doxygen.vim & doxygen.txt複製至~/.vim/after/syntax
- 針對每一個想到支援doxygen syntax coloring的檔案類型, 建立soft link
$> cd ~/.vim/after/syntax
ln -s doxygen.vim c.vim
ln -s doxygen.vim cpp.vim
ln -s doxygen.vim java.vim
參考來源:
Doxygen syntax coloring in vim
2009年3月14日 星期六
What is Twitter??
Twitter是在中山大學學分班課程中, 黃慶祥教授提及的名詞,
只是想不到全班30來人的資訊人, 知道這個名詞的人竟是小熊兩三隻,
想當然爾我是隻小狗, 而不是小熊!!
查了一下譯典通, Twitter = 吱吱喳喳 = 三姑六婆 = 閒話家常
google search 該字詞, 文字解釋不少, 但我喜歡以下這段影片以生動的情境描述,
Twitter可以在你我的日常生活中, 扮演著什麼樣的功能角色??
影片中, 一開場就說了句很關鍵的話, "What are you doing?" (你在做什麼呢??)
在日常生活中, 只是一句很直覺的關心語句, 但在網路上卻無法很直覺地回答朋友們,
又或者是, 想輕鬆簡單地分享一則資訊, 例如"今日的天空很湛藍",
也許有人會說, 透過e-mail、blog、msn...等等, 但這會不會太小題大作了呢??
我收e-mail最不喜愛看到一些無關要緊的信件,
而blog也不希望記錄下這毫無參考價值的訊息,
在msn要告訴大家, 就得一個一個開啟視窗, 一個一個地訊息傳送..
哇..這麼簡單的小事, 卻要歷經這麼繁瑣的過程, 這會不會本末倒置了!!
Twitter就是可以讓你輕易分享你的生活小事給周遭的朋友知道,
在一個頁面上, 就可以分享交流彼此朋友的生活點滴, 而且每則消息不超過140個字,
例如"我在高雄明誠星巴克享受午后咖啡時光", 透過Twitter分享,
你的朋友隨即可以知悉你最新的動態、心情、作息,
或許他也正巧在左營附近, 就可以順道前往與你共享一杯咖啡的悠閑時光
參考資料
只是想不到全班30來人的資訊人, 知道這個名詞的人竟是小熊兩三隻,
想當然爾我是隻小狗, 而不是小熊!!
查了一下譯典通, Twitter = 吱吱喳喳 = 三姑六婆 = 閒話家常
google search 該字詞, 文字解釋不少, 但我喜歡以下這段影片以生動的情境描述,
Twitter可以在你我的日常生活中, 扮演著什麼樣的功能角色??
影片中, 一開場就說了句很關鍵的話, "What are you doing?" (你在做什麼呢??)
在日常生活中, 只是一句很直覺的關心語句, 但在網路上卻無法很直覺地回答朋友們,
又或者是, 想輕鬆簡單地分享一則資訊, 例如"今日的天空很湛藍",
也許有人會說, 透過e-mail、blog、msn...等等, 但這會不會太小題大作了呢??
我收e-mail最不喜愛看到一些無關要緊的信件,
而blog也不希望記錄下這毫無參考價值的訊息,
在msn要告訴大家, 就得一個一個開啟視窗, 一個一個地訊息傳送..
哇..這麼簡單的小事, 卻要歷經這麼繁瑣的過程, 這會不會本末倒置了!!
Twitter就是可以讓你輕易分享你的生活小事給周遭的朋友知道,
在一個頁面上, 就可以分享交流彼此朋友的生活點滴, 而且每則消息不超過140個字,
例如"我在高雄明誠星巴克享受午后咖啡時光", 透過Twitter分享,
你的朋友隨即可以知悉你最新的動態、心情、作息,
或許他也正巧在左營附近, 就可以順道前往與你共享一杯咖啡的悠閑時光
參考資料
2009年3月13日 星期五
How to format date and time by using C lib
在Linux中, 如何有效快速地格式化時間為字串格式呢??
原來有個系統函式可以簡易地達到這樣的目的,
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);
s : 存放日期時間轉換為字串格式的buffer
max : 上述s的最大長度
format : 格式化符號
tm : 日期時間結構
example:
則會輸出以下字串
出乎意料地簡單吧!!
原來有個系統函式可以簡易地達到這樣的目的,
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);
s : 存放日期時間轉換為字串格式的buffer
max : 上述s的最大長度
format : 格式化符號
tm : 日期時間結構
example:
int main () {
char msg[256];
time_t now;
struct tm *timestr;
time (&now);
timestr = localtime (&now);
strftime (msg, sizeof(msg),"%Y%m%d%H%M%S", timestr);
printf ("the datetime is %s \n", msg);
}
則會輸出以下字串
the datetime is 20090315093045
出乎意料地簡單吧!!
2009年3月1日 星期日
TCP TIME_WAIT的釋義
在實務中, 許多情況下, 可能是Server Socket出現了問題, 勢必採取關閉原有的Sever Socket, 再隨即重新啟動新建的Server Socket. 但此刻會發生一個問題, 就是相隔時間過短, 在新建的Sever Socket進行bind()的程序時, 系統會出現一錯誤訊息"the address already in use".
照一般想法, Server Socket都已Close, 理應已釋放出該IP Address之資源, 怎會出現這個令人莫名的訊息呢??
關鍵在於TCP建立於多次的握手協定的基礎上, 以達到保證訊息傳遞的完整性.
由於TPC是全雙工傳輸, 換言之, 雙向的傳輸必須單獨進行關閉, 原則上主動請求關閉的一方A, 藉由發送FIN來請求終止這個方向的連接. 被動關閉的一方B, 收到FIN表示A-->B的方向已無資料進行傳送, 此時B-->A仍是可以進行資料傳送, 待B執行被動關閉.
簡言之, A欲進行關閉傳輸時, 必須通知B並確認, 而B欲進行關閉傳輸時, 也必須通知A並確認.

關閉連線:(如上圖所示)
(1) 當處於ESTABLISHED狀態時, TCP B欲主動關閉連線, 發送FIN至TCP A, 進入到FIN-WAIT-1狀態, 等待TCP A回應ACK, 表示等待確認TCP A得知TCP B要關閉連線
(2) 當TCP A收到TCP B的FIN時, 立即回應ACK給TCP B, 進入到CLOSE-WAIT狀態, 表示須等到應用程序沒有任何資料要傳送給TCP B, TCP A才決定關閉連線
(3) TCP B收到TCP A回應的ACK, 表示確認TCP A得知TCP B要關閉連線, 此刻等待TCP A發送FIN
(4) TCP A決定關閉連線, 發送FIN至TCP B, 進入到LAST-ACK狀態, 等待TCP B回應ACK, 表示等待確認TCP B得知TCP A要關閉連線
(5) TCP B收到TCP A的FIN後, 隨即回應ACK, 進入TIME_WAIT狀態, 表示TCP B得知TCP A要關閉連線, 且等待2MSL時間, 以防TCP A再次發送FIN
(6) TCP A收到TCP B回應的ACK後, 進入CLOSED狀態, 表示TCP A已確認TCP B已得知它要關閉連線, 才進行關閉連線
(7) TCP B等待2MSL時間, 才進入CLOSED狀態, 關閉連線, 並自連線表中移除
在上述的第(5),(7)點, 此刻TIME-WAIT的用意在於, 雖TCP B已確認TCP A要關閉連線, 且回應了ACK給TCP A, 但不保證TCP A會收到ACK, 一旦ACK遺漏, TCP A會再次發送FIN給TCP B, 再次進行確認, 所以TCP B須進入TIME-WAIT狀態, 等待2MSL時間, 預防TCP A會再次發送FIN, 進行連線關閉的確認
different states of a TCP connection:
LISTEN : awaiting a connection request from client (監聽客戶端的連線請求)
SYN-SENT : a SYN has been sent to server, and client is awaiting the ACK of SYN (發送SYN, 並等待服務端回應SYN的ACK)
SYN-RECEIVED : a SYN has been received from client, a SYN with ACK has been sent to client, and server is awaiting the ACK of SYN (接收客戶端的SYN, 另傳送SYN+ACK(SYN)給客戶端, 並等待客戶端回應SYN的ACK)
ESTABLISHED : the three-way handshake has been completed, and established the connection (完成握手協定, 並建立連線)
FIN-WAIT-1 : the local AP has issued a close. active TCP has sent a FIN to passive TCP, and is awaiting an ACK of FIN (主動端發出FIN至被動端, 並等待被動端回應FIN的ACK)
FIN-WAIT-2 : a previous FIN has been sent to passiveTCP, and received an ACK of FIN from passive TCP. active TCP is awaiting a FIN from the passive TCP (成功接收到先前傳送至被動端FIN的ACK, 此刻等待被動端傳送FIN)
CLOSE-WAIT : passive TCP has received a FIN from active TCP, and has sent an ACK of FIN to active TCP. passive TCP is awaiting a close request from remote AP before sending a FIN (被動端已接收主動端的FIN, 並傳送FIN的ACK至主動端, 此刻等待AP要求關閉連線)
LAST-ACK : previously a FIN has been received from active TCP, and an ACK of FIN has been sent to active TCP, and a FIN has been sent to active TCP. passive TCP is awaiting an ACK of FIN (先前收到主動端的FIN, 且傳送FIN的ACK給主動端, 另被動端傳送FIN給主動端, 此刻被動端等待主動端回應FIN的ACK)
TIME-WAIT : FINs have been received and ACK has been sent passive TCP. active TCP is waiting 2MSLs to remove the connection from the connection table (收到被動端的FIN, 並傳送ACK至被動端, 此刻主動端會等待2MSL的時間才將連線關閉)
CLOSED : a connection has been removed from the connection table (連線不存在於連線表)
參考資料:
Transmission Control Protocol
TCP State Diagram
TCP Connection Termination
Socket FAQ -- 2.7 please explain the TIME_WAIT state
照一般想法, Server Socket都已Close, 理應已釋放出該IP Address之資源, 怎會出現這個令人莫名的訊息呢??
關鍵在於TCP建立於多次的握手協定的基礎上, 以達到保證訊息傳遞的完整性.
由於TPC是全雙工傳輸, 換言之, 雙向的傳輸必須單獨進行關閉, 原則上主動請求關閉的一方A, 藉由發送FIN來請求終止這個方向的連接. 被動關閉的一方B, 收到FIN表示A-->B的方向已無資料進行傳送, 此時B-->A仍是可以進行資料傳送, 待B執行被動關閉.
簡言之, A欲進行關閉傳輸時, 必須通知B並確認, 而B欲進行關閉傳輸時, 也必須通知A並確認.

關閉連線:(如上圖所示)
(1) 當處於ESTABLISHED狀態時, TCP B欲主動關閉連線, 發送FIN至TCP A, 進入到FIN-WAIT-1狀態, 等待TCP A回應ACK, 表示等待確認TCP A得知TCP B要關閉連線
(2) 當TCP A收到TCP B的FIN時, 立即回應ACK給TCP B, 進入到CLOSE-WAIT狀態, 表示須等到應用程序沒有任何資料要傳送給TCP B, TCP A才決定關閉連線
(3) TCP B收到TCP A回應的ACK, 表示確認TCP A得知TCP B要關閉連線, 此刻等待TCP A發送FIN
(4) TCP A決定關閉連線, 發送FIN至TCP B, 進入到LAST-ACK狀態, 等待TCP B回應ACK, 表示等待確認TCP B得知TCP A要關閉連線
(5) TCP B收到TCP A的FIN後, 隨即回應ACK, 進入TIME_WAIT狀態, 表示TCP B得知TCP A要關閉連線, 且等待2MSL時間, 以防TCP A再次發送FIN
(6) TCP A收到TCP B回應的ACK後, 進入CLOSED狀態, 表示TCP A已確認TCP B已得知它要關閉連線, 才進行關閉連線
(7) TCP B等待2MSL時間, 才進入CLOSED狀態, 關閉連線, 並自連線表中移除
在上述的第(5),(7)點, 此刻TIME-WAIT的用意在於, 雖TCP B已確認TCP A要關閉連線, 且回應了ACK給TCP A, 但不保證TCP A會收到ACK, 一旦ACK遺漏, TCP A會再次發送FIN給TCP B, 再次進行確認, 所以TCP B須進入TIME-WAIT狀態, 等待2MSL時間, 預防TCP A會再次發送FIN, 進行連線關閉的確認
different states of a TCP connection:
LISTEN : awaiting a connection request from client (監聽客戶端的連線請求)
SYN-SENT : a SYN has been sent to server, and client is awaiting the ACK of SYN (發送SYN, 並等待服務端回應SYN的ACK)
SYN-RECEIVED : a SYN has been received from client, a SYN with ACK has been sent to client, and server is awaiting the ACK of SYN (接收客戶端的SYN, 另傳送SYN+ACK(SYN)給客戶端, 並等待客戶端回應SYN的ACK)
ESTABLISHED : the three-way handshake has been completed, and established the connection (完成握手協定, 並建立連線)
FIN-WAIT-1 : the local AP has issued a close. active TCP has sent a FIN to passive TCP, and is awaiting an ACK of FIN (主動端發出FIN至被動端, 並等待被動端回應FIN的ACK)
FIN-WAIT-2 : a previous FIN has been sent to passiveTCP, and received an ACK of FIN from passive TCP. active TCP is awaiting a FIN from the passive TCP (成功接收到先前傳送至被動端FIN的ACK, 此刻等待被動端傳送FIN)
CLOSE-WAIT : passive TCP has received a FIN from active TCP, and has sent an ACK of FIN to active TCP. passive TCP is awaiting a close request from remote AP before sending a FIN (被動端已接收主動端的FIN, 並傳送FIN的ACK至主動端, 此刻等待AP要求關閉連線)
LAST-ACK : previously a FIN has been received from active TCP, and an ACK of FIN has been sent to active TCP, and a FIN has been sent to active TCP. passive TCP is awaiting an ACK of FIN (先前收到主動端的FIN, 且傳送FIN的ACK給主動端, 另被動端傳送FIN給主動端, 此刻被動端等待主動端回應FIN的ACK)
TIME-WAIT : FINs have been received and ACK has been sent passive TCP. active TCP is waiting 2MSLs to remove the connection from the connection table (收到被動端的FIN, 並傳送ACK至被動端, 此刻主動端會等待2MSL的時間才將連線關閉)
CLOSED : a connection has been removed from the connection table (連線不存在於連線表)
參考資料:
Transmission Control Protocol
TCP State Diagram
TCP Connection Termination
Socket FAQ -- 2.7 please explain the TIME_WAIT state
2009年1月8日 星期四
使用SVN進行版本控制 - 相關參考資源
#####官方網站#####
TortoiseSVN -- 常見的SVN Client 軟體
http://tortoisesvn.net/
Subversion線上電子書 -- 繁體中文
http://twpug.net/docs/Subversion/
Subversion線上電子書 -- 簡體中文
http://svnbook.red-bean.com/
#####教學討論#####
簡體中文SVN的技術論壇, 資源非常豐富
http://www.svn8.com/
國內Blog, 有著圖文並茂的介紹及教學, 值得前往
http://i.repeat.tw/blog/category/107765
國內邱茂森前輩的簡報
http://www.csie.ntut.edu.tw/sdrc/files/course/20061201/VersionControlWithSVN.pdf
#####常見問題#####
Total Commander也可以看到SVN的系統圖示唷!!
http://www.dotblogs.com.tw/chhuang/archive/2008/10/12/5662.aspx
在選定一目錄Show log時, 某些版本只顯示版本號碼與 no date, 看不見其訊息, 為什麼??
http://doc.iusesvn.com/show-33-1.html
SVN是否可以控制中文目錄的訪問權限
http://doc.iusesvn.com/show-31-1.html
Client端連線至檔案庫時, 出現右列錯誤訊息 " svnserve.conf : 12 : Option expected "
http://doc.iusesvn.com/show-28-1.html
在Redhat AS4 的安裝與設定
http://doc.iusesvn.com/show-15-1.html
svnserve的權限設定
http://doc.iusesvn.com/show-8-1.html
Redhat AS4 安裝 apache2.2.3 + svn1.4 + 郵件自動通知
http://doc.iusesvn.com/show-7-1.html
詳盡介紹多層次目錄權限控制設定
http://doc.iusesvn.com/show-1-1.html
TortoiseSVN -- 常見的SVN Client 軟體
http://tortoisesvn.net/
Subversion線上電子書 -- 繁體中文
http://twpug.net/docs/Subversion/
Subversion線上電子書 -- 簡體中文
http://svnbook.red-bean.com/
#####教學討論#####
簡體中文SVN的技術論壇, 資源非常豐富
http://www.svn8.com/
國內Blog, 有著圖文並茂的介紹及教學, 值得前往
http://i.repeat.tw/blog/category/107765
國內邱茂森前輩的簡報
http://www.csie.ntut.edu.tw/sdrc/files/course/20061201/VersionControlWithSVN.pdf
#####常見問題#####
Total Commander也可以看到SVN的系統圖示唷!!
http://www.dotblogs.com.tw/chhuang/archive/2008/10/12/5662.aspx
在選定一目錄Show log時, 某些版本只顯示版本號碼與 no date, 看不見其訊息, 為什麼??
http://doc.iusesvn.com/show-33-1.html
SVN是否可以控制中文目錄的訪問權限
http://doc.iusesvn.com/show-31-1.html
Client端連線至檔案庫時, 出現右列錯誤訊息 " svnserve.conf : 12 : Option expected "
http://doc.iusesvn.com/show-28-1.html
在Redhat AS4 的安裝與設定
http://doc.iusesvn.com/show-15-1.html
svnserve的權限設定
http://doc.iusesvn.com/show-8-1.html
Redhat AS4 安裝 apache2.2.3 + svn1.4 + 郵件自動通知
http://doc.iusesvn.com/show-7-1.html
詳盡介紹多層次目錄權限控制設定
http://doc.iusesvn.com/show-1-1.html
2009年1月7日 星期三
使用SVN進行版本控制 - (五)TortoiseSVN 的基本操作與使用
TortoiseSVN是在Windows平台上使用的Subversion Client, 它是免費的, 重要的是它把Subversion Client具備的功能全部整合於右鍵的功能選單內, 使用起來相當便利, 省去了下達Command的麻煩。

以系統圖示表達目前檔案的狀態
提供不同的圖示, 各代表著不同的意義, 非常直覺化, 一目瞭然!!

瀏覽檔案庫的內容
任意地按下滑鼠右鍵, 點選『TortoiseSVN』-> 『Repo-browser』, 鍵入"svn://svnserver/repository", 瀏覽SVN Server的檔案庫內容。


導出檔案庫副本
為了取得檔案庫的副本, 必須進行Check Out的操作。
選擇欲存放檔案庫副本的資料夾, 按下滑鼠右鍵, 點選『TortoiseSVN』-> 『SVN Checkout..』, 指定欲導出(check out)檔案庫的來源路徑, 再指定存放檔案庫副本的目的路徑。在此, Head Revision表示導出最新版本, 隨即導出檔案庫副本。


提交異動至檔案庫
在提交異動之前, 必須確認目前檔案庫副本是否仍為最新版本(表示這期間無人進行修改), 選擇存放檔案庫副本的資料夾, 按下滑鼠右鍵, 點選『TortoiseSVN』-> 『SVN Update』。

若本機異動的檔案, 在這段期間沒有他人進行修改, 則點選 『TortoiseSVN』-> 『SVN Commit』, 鍵入詳細的異動資料, 異動檔案, 異動人員...等等, 以利往後回溯至需要的版本。

若本機異動的檔案, 在這段期間已有他人進行修改, 並且先行提交異動至SVN Server, 此時會蹦現出警告視窗, 提醒該檔案已提交較新的版本, 也顯示其較新版本的Log。遭遇此一情況時, 必須使用『TortoiseSVN』-> 『Diff』, 進行檔案內容的差異化比較, 待與他人協調並確認檔案內容之後, 再提交經確認異動的檔案至SVN Server。


以系統圖示表達目前檔案的狀態
提供不同的圖示, 各代表著不同的意義, 非常直覺化, 一目瞭然!!

瀏覽檔案庫的內容
任意地按下滑鼠右鍵, 點選『TortoiseSVN』-> 『Repo-browser』, 鍵入"svn://svnserver/repository", 瀏覽SVN Server的檔案庫內容。


導出檔案庫副本
為了取得檔案庫的副本, 必須進行Check Out的操作。
選擇欲存放檔案庫副本的資料夾, 按下滑鼠右鍵, 點選『TortoiseSVN』-> 『SVN Checkout..』, 指定欲導出(check out)檔案庫的來源路徑, 再指定存放檔案庫副本的目的路徑。在此, Head Revision表示導出最新版本, 隨即導出檔案庫副本。


提交異動至檔案庫
在提交異動之前, 必須確認目前檔案庫副本是否仍為最新版本(表示這期間無人進行修改), 選擇存放檔案庫副本的資料夾, 按下滑鼠右鍵, 點選『TortoiseSVN』-> 『SVN Update』。

若本機異動的檔案, 在這段期間沒有他人進行修改, 則點選 『TortoiseSVN』-> 『SVN Commit』, 鍵入詳細的異動資料, 異動檔案, 異動人員...等等, 以利往後回溯至需要的版本。

若本機異動的檔案, 在這段期間已有他人進行修改, 並且先行提交異動至SVN Server, 此時會蹦現出警告視窗, 提醒該檔案已提交較新的版本, 也顯示其較新版本的Log。遭遇此一情況時, 必須使用『TortoiseSVN』-> 『Diff』, 進行檔案內容的差異化比較, 待與他人協調並確認檔案內容之後, 再提交經確認異動的檔案至SVN Server。

2008年12月28日 星期日
使用SVN進行版本控制 - (四) 如何使用SVN??
SVN應用實例
小張是位在軟體公司任職的專案經理,某天,察覺到當成員愈多時,在版本控制上,更形困難,每每版本混亂造成的影響,總要花上些許多時間。因此,小張決定試著採用Subversion來做版本管理。
首先,將原有的程式碼及相關文件,利用svn import匯入檔案庫(repository)。
svn import porject_directory file:///svn/proj
接著,將兩個模組分別交給小李及小陳兩位工程師進行開發,分別利用svn checkout下載最新的程式碼。
svn checkout file:///svn/proj /local_project
小李的任務是撰寫一個math模組,於是新增一個math目錄,有著math.h及math.cpp兩個檔案,利用svn add將整個math目錄列入提交清單。
svn add math
當math模組開發完成後,使利用svn commit提交math目錄。
svn commit
而小陳必須引用math函式進行另項模組修改,所以必須利用svn update將更新至最新的程式碼。
svn update file:///svn/proj
當程式碼修正完畢後,也利用svn commit進行提交。
svn commit
這時,小李又針對math模組進行修改測試,卻發現無法正常編譯,但上一版是正常的,因此小李利用svn diff比對,找出程式錯誤的地方,再次修正即可正常編譯。
svn diff -r01:02
終於要釋出完整版本,於是利用svn export輸出一份不含任何版本控制資訊的程式碼。
svn export file:///svn/proj /projR1
小張是位在軟體公司任職的專案經理,某天,察覺到當成員愈多時,在版本控制上,更形困難,每每版本混亂造成的影響,總要花上些許多時間。因此,小張決定試著採用Subversion來做版本管理。
首先,將原有的程式碼及相關文件,利用svn import匯入檔案庫(repository)。
svn import porject_directory file:///svn/proj
接著,將兩個模組分別交給小李及小陳兩位工程師進行開發,分別利用svn checkout下載最新的程式碼。
svn checkout file:///svn/proj /local_project
小李的任務是撰寫一個math模組,於是新增一個math目錄,有著math.h及math.cpp兩個檔案,利用svn add將整個math目錄列入提交清單。
svn add math
當math模組開發完成後,使利用svn commit提交math目錄。
svn commit
而小陳必須引用math函式進行另項模組修改,所以必須利用svn update將更新至最新的程式碼。
svn update file:///svn/proj
當程式碼修正完畢後,也利用svn commit進行提交。
svn commit
這時,小李又針對math模組進行修改測試,卻發現無法正常編譯,但上一版是正常的,因此小李利用svn diff比對,找出程式錯誤的地方,再次修正即可正常編譯。
svn diff -r01:02
終於要釋出完整版本,於是利用svn export輸出一份不含任何版本控制資訊的程式碼。
svn export file:///svn/proj /projR1
2008年12月25日 星期四
使用SVN進行版本控制 - (三) 建立檔案庫及導入
Create Reposiroty (建立版本庫)
$>mkdir /svnImport Project (匯入專案)
$>chwon -R nobody /svn
$>svnadmin create /svn/test
$>ls /svn/test
#如果ls /repository/test/出現了下面的內容,就說明subversion安裝成功了
conf dav db format hooks locks README.txt
$>svn import gt;svn import gt;svn import gt;svn import gt;svn import gt;svn import projectdir file:///svn/test/ -m "initial import"
##出現下列訊息, 即表示成功匯入專案
Adding projectdir/foo.c
Adding projectdir/bar.c
Adding projectdir/subdir
Adding projectdir/subdir/quux.h
Committed revision 1.
於IE的網址列, 鍵入http://localhost/svn/test/, 如下圖結果
2008年12月24日 星期三
使用SVN進行版本控制 - (二) 設定配置
啟動Subversion服務提供下列三種方式:
1. svnserver, a custom server
svnserver是一種較為不耗費資源的service, 建立於TCP/IP的基礎通訊協定上,client side可透過svn://來進行溝通。
常見的有兩種模式啟動svnserver:(1) as stand alone, (2) as daemon
(1) as stand alone (/etc/init.d)
2. apache, a http server
apache是一種較為耗費資源的service, 建立於WebDav的基礎通訊協定上,client side可透過http://來進行溝通。
- svnserver
- svnserver + ssh
- apache
1. svnserver, a custom server
svnserver是一種較為不耗費資源的service, 建立於TCP/IP的基礎通訊協定上,client side可透過svn://來進行溝通。
常見的有兩種模式啟動svnserver:(1) as stand alone, (2) as daemon
(1) as stand alone (/etc/init.d)
$> svnserver -d -r /svn(2) as daemon (/etc/xinetd.d)
# -d : 以daemon方式執行
# -r : 虛擬根目錄, 限制只能在此目錄底下的瀏覽
$> lsof -i :3690
# 可以查看svnserver是否已正常啟動
$> vi /etc/xinetd.d/svnserve1.1 svnserve.conf (配置設定)
##新增以下文字內容
service svnserve
{
disable = no
socket_type = stream
wait = no
user = apache
server = /usr/local/subversion/bin/svnserve
server_args = -i
}
$> vi /etc/services
##確認有無以下文字內容, 若不存在, 請新增於檔案內容中
svnserve 3690/tcp #Subversion svnserve
svnserve 3690/udp #Subversion svnserve
[general]1.2 passwd (使用者帳號)
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
# realm = My First Repository
[users]1.3 authz (授權管理)
## username = password
admin = admin
yardmgr = yardmgr
[groups]
administrators = admin
developer_team = mills
[/]
* =
@administrators = rw
[/svn/yard:/]
@developer_team = rw
[/svn/test:/]
@developer_team = rw
2. apache, a http server
apache是一種較為耗費資源的service, 建立於WebDav的基礎通訊協定上,client side可透過http://來進行溝通。
(1) Apache2 Config (I) -- Add SVN Modules
$>vi /usr/local/apache2/conf/httpd.conf
##確認有無以下內容, 若不存在, 請新增貼上
##若沒有mod_dav_svn模組, SVN則無法以http方式運作
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modles/mod_authz_svn.so
(2) Apache2 Config (I) -- Add SVN Path
$>vi /usr/local/apache2/conf/httpd.conf
##確認有無以下內容, 若不存在, 請新增貼上
<Location>
DAV svn
SVNPath /svn/test
# our access control policy, below (4)
AuthzSVNAccessFile /svn/svn-authz
AuthType Basic
AuthName "Version Control System"
# how to authenticate a user, below (3)
AuthUserFile /svn/svn-auth-file
# only authenticated users may access the repository
Require valid-user
</Location>
(3) Setting up http authentication (建立認證帳號)
$>htpasswd -c -m /svn/svn-auth-file admin
# 輸入第1個使用者帳號, 第1次建立才加 -c
# -c : 建立新檔
# -m : 採以MD5編碼
$>htpasswd -m /svn/svn-auth-file yardmgr
# 輸入第2個使用者帳號
(4) Setting up svn authorization (建立授權管理)
$> vi /svn/svn-authz
# 新增以下文字內容
[groups]
administrators = admin
developer_team = yardmgr
[/]
* =
@administrators = rw
[/svn/test:/]
@developer_team = rw
2008年12月20日 星期六
使用SVN 進行版本控制 - (一) 安裝
what is SVN??
Apache2 Installation
Version Control with Subversion (繁體中文) -- http://twpug.net/docs/Subversion/
Install Subversion at RedHat Linux AS4 -- http://www.svn8.com/svnpz/20080316/339.html
(引述官方文件的簡介)功能列表
Subversion 是一個自由/開放源碼的版本控制系統, 也就是說 Subversion 管理著隨時間改變的檔案. 這些檔案放置在一個中央 檔案庫 (repository) 中. 這個檔案庫 很像一個尋常的檔案伺服器, 不過它會記住每一次檔案的變動. 這樣你就可以把檔案回復到舊的版本, 或是瀏覽檔案的變動歷程. 許多人會把版本控制系統想像成某種 “時光機器”.
某些版本控制系統也是 software configuration management (SCM) 系統. 這些系統是特別設計來管理大量程式碼的, 而且具有許多功能, 專門用在軟體發展之用 — 像是可完全了解程式語言, 或是提供編譯軟體的工作. 不過 Subversion 並不是這樣的系統; 它是一個泛用系統, 可用來管理任何 類型的檔案, 其中包括了程式源碼.
- 目錄版本控制
- CVS 只能追蹤單獨檔案的歷史, 不過 Subversion 實作了一個 “虛擬” 的版本控管檔案系統, 能夠依時間追蹤整個目錄的更動. 目錄和檔案都被納入版本控管. 最後, 用戶端有真正可用的 move (移動) 與 copy 指令.
- 不可分割的送交
- 一個送交動作, 不是導致所有更動都送入檔案庫, 就是完全不會送入. 這讓發展人員以邏輯區段建立更動, 並送交更動.
- 納入版本控管的描述資料 (Meta-data)
- 每一個檔案與目錄都附有一組隱形 “性質 (property)”. 你可以自己發明, 並儲存任何你想要的鍵值對. 性質是隨著時間來作版本控管的, 就像檔案內容一樣.
- 選擇不同的網路層
- Subversion 有抽象的檔案庫存取概念, 可以讓人很容易地實作新的網路機制. Subversion “先進” 的網路伺服器, 是 Apache 網頁伺服器的一個模組, 它以稱為 WebDAV/DeltaV 的 HTTP 變體協定與外界溝通. 這對 Subversion 的穩定性與互通性有很大的幫助, 而且額外提供了許多重要功能: 舉例來說, 有身份認證, 授權, 線上壓縮, 以及檔案庫瀏覽. 另外也有小而獨立的 Subversion 伺服器程式, 使用的是自訂的通訊協定, 可以很容易地透過 ssh 以 tunnel 方式使用.
- 一致的資料處理方式
- Subversion 使用二進制差異運算法, 來表示檔案的差異, 它對文字 (人類可理解的) 與二進制檔案 (人類無法理解) 兩類的檔案都一視同仁. 這兩類的檔案都同樣地以壓縮形態儲存在檔案庫中, 而且檔案差異是以兩個方向在網路上傳送的.
- 更有效率的分支 (branch) 與標記 (tag)
- 分支與標記的花費並不必一定要與計畫大小成正比. Subversion 建立分支與標記的方法, 就只是複製該計畫, 使用的方法就像 hard-link 一樣. 所以這些動作只會花費很小, 而且是固定的時間.
- Hackability
- Subversion 沒有任何的歷史包袱; 它主要是一群共用的 C 程式庫, 具有定義完善的 API. 這使得 Subversion 便於維護, 並且可被其它應用程式與程式語言使用.
SVN提供了三種Server配置的方式,(1) svnserver (2) svnserver+ ssh (3) apache + mod_dav_svn
(1) svnserver : 一個更小,輕型的服務器程序,同客戶端使用自定義的協議。因為協議是為Subversion專門設計的,並且是有狀態的(不像HTTP),它提供了更快的 網絡操作—但也有一些代價。它只理解CRAM-MD5的認證,然而它非常易於配置,是開始使用Subversion的小團隊的最佳選擇。
(2) svnserver + ssh : 儘管依然使用svnserve,它與傳統的svnserve部署非常不同,SSH在多所有的通訊中使用加密方式,SSH也使用排他的認證,所以在服務器主機(svnserve與之不同,它包含了自己的私有用戶帳號)上必須要有真實的系統帳戶。最後,因為這些配置需要每個用戶發起一個私有的臨時svnserve進程,這與允許一組本地用戶通過file://協議訪問等同(從訪問許可的視點)。因此路徑為基礎的訪問控制變得沒有意義,因為每個用戶都可以直接訪問版本庫。
(3) apache : Apache是最流行的web服務器,通過使用mod_dav_svn模塊,Apache可以訪問版本庫,並且可以使客戶端使用HTTP的擴展協議WebDAV/DeltaV進行訪問,因為Apache是一個非常易於擴展的web服務器,它提供了許多「易於獲取的」特性,例如加密的SSL通訊,日誌和與第三方工具的集成,以及內置的版本庫web瀏覽功能。
註: 參考官方說明文件第6章
Apache2 Installation
##請至官網下載必備套件SVN Installation
Apache官網:http://httpd.apache.org/
Apache 套件:http://ftp.tcc.edu.tw/pub/Apache/httpd/httpd-2.0.63.tar.gz
##解壓縮 httpd-2.x.x.xxtar.gz
$>mv httpd-2.x.x.xxtar.gz /usr/src/
$>tar -xvzf httd-2.x.xx.tar.gz
$>cd httpd-2.x.xx
##安裝apr (Apache Portable Runtime) & apr-util (APR Utility)
$>cd httpd-2.x.xx/srclib/apr
$>./buildconf
$>./configure --prefix=/usr/local/apr
$>make
$>make install
$>cd httpd-2.x.xx/srclib/apr-util
$>./buildconf
$>./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr
$>make
$>make install
##安裝apache2
$>cd httpd-2.x.xx
$>./configure --enable-dav --prefix=/usr/local/apache2 --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr --enable-cgi --enable-modules=so --enable-rewrite
$>make && make install
##請至官網下載必備套件Reference by follow website
SVN官網:http://subversion.tigris.org/
SVN套件:http://subversion.tigris.org/downloads/subversion-1.5.4.tar.gz
$>./configure --prefix=/usr/local/subversion --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr --with-apxs=/usr/local/apache2/bin/apxs --with-ssl
$>make
$>make install
Version Control with Subversion (繁體中文) -- http://twpug.net/docs/Subversion/
Install Subversion at RedHat Linux AS4 -- http://www.svn8.com/svnpz/20080316/339.html
訂閱:
文章 (Atom)
