2009年5月27日 星期三

minicom - 設定

不知道是不是從ubuntu 8.04開始, 用普通使用者使用minicom都會出現
minicom: cannot open /dev/ttyS0: Permission denied
的錯誤。

ok, 我知道是權限不足,那麼要如何解決呢?

原來是必需要加入到uucp這一個群組才可以啊~

修改/etc/group
每一行的格式是這樣的
群組名稱:群組密碼:GID:此群組支援的帳號名稱
「在此群組支援的帳號名稱」加入你的帳號
若要某一個群組支援多個帳號,就必需以「,」做為區隔, 例:
root:x:0:root,dmtsai
root這一個群組支援root與dmtsai這兩個帳號

第一次在使用的時候,可以使用
$ minicom -s
來設定相關的參數,通常只有改兩個地方
1. /dev/ttyS0
2. Bps/Par/Bits

然後, 之後就可以使用
$ minicom
進入minicom的世界啦

若不想要中文介面的話,可以使用
$ export LANG=C
改為英文介面

喔耶,意外發現,若想要只有在使用某一個應用程式時, 需要某一個環境變數,那麼要如何使用哩~
$ LANG=C minicom
這樣就可以只有在執行minicom時,LANG的環境變數值會是C
當然,就可以直接修改$HOME/.bashrc加入
alias minicom='LANG=C minicom'

參考資料:
/etc/group 檔案結構
Minicom: Permission denied

2009年5月26日 星期二

linux指令 - screen

screen是一個對於常常透過putty或pietty連線到工作站的使用者非常有用。當你要多個視窗時,不需要執行多次的putty來達到你的要求,screen這一個指令便可以達到。但是,如果在X11的情況下,終端機分頁就非常好用啦~

轉錄資料:
使用 screen
在命令列下打 screen 就會進入 screen 的天地:
% screen

注意,所有 screen 的指令都是以 Ctrl 鍵加上 a 鍵開始的,在之後以 C-a 代表,C-a c 代表按住 Ctrl 鍵不放再按 a 鍵,然後放開按 c 鍵;而 C-a C-c 代表按住 Ctrl 鍵不放再按 a 鍵,然後放開後再按住 Ctrl 鍵不放按 c 鍵。

開啟,關閉,切換

C-a c 或 C-a C-c 開啟新的視窗,並同時切換到這個新的視窗
C-a n 或 C-a C-n 或 C-a (space) 切換到下一個視窗(0->1 1->2 …)
C-a p 或 C-a C-p 切換到上一個視窗(1->0 2->1 …)
C-a C-a 切換到上一個顯示過的視窗(不是照順序切換)
C-a 0 切換到第 0 個視窗
C-a (1..9) 切換到第 (1..9) 個視窗
C-a w 或 C-a C-w 會列出目前所開啟的視窗
0$ tcsh 1$ tcsh 2*$ tcsh 3$ tcsh

有星號 “*” 的表示目前顯示中的視窗,之後的 tcsh 代表這個視窗的 title ,預設是以開啟時的 shell 名稱
C-a K 關閉所有的視窗並退出 screen
C-a ‘ 或 C-a ” 會出現 “Switch to window:” 字樣,輸入號碼後就可切到該視窗
單一視窗使用中的指令

C-a C 清除目前的視窗內容
C-a d 或 C-a C-d 脫離(detach)目前的 screen ,並放到背景執行(不管開了幾個視窗),下面會再提到
C-a D D 強力脫離,除了放到背景執行外,並自動 logout
C-a C-g 虛擬嗶聲(visual bell)的切換,可以在畫面上顯示訊息代表一般的嗶聲
C-a H 紀錄目前視窗所有顯示過的東西(檔名為 screenlog.n n 為視窗號碼)
C-a i 或 C-a C-i 顯示目前視窗的資訊
(11,24)/(80,24)+1000 +(+)flow -ins -org +wrap +app -log -mon +r G0 [BBBB]

C-a l 或 C-a C-l 重繪視窗,如果有字顯示亂掉了可以用這個指令
C-a m 或 C-a C-m 或 C-a (enter) 可以顯示最近一次顯示過的訊息
C-a t 或 C-a C-t 顯示系統的時間及主機名稱還有負載
C-a v 顯示版本資訊
C-a x 或 C-a C-x 如果你要暫時離開目前位置又不想先 logout ,那可以用這個來鎖住 screen
C-a ? 線上求助畫面
複製/卷軸 模式
按下 C-a [ 就可以進入 複製/卷軸 模式(只有在目前視窗才算,其他視窗照常)基本上跟 vi 很像:

h, j, k, l 分別為向左,向下,向上,向右移動一格(或是一行)
0 移到該行最左邊
^ 與 $ 分別移到該行最左邊及最右邊的非空白字元
w 以字為單位往前移動並移到字首
b 以字為單位往後移動並移到字首
e 以字為單位往前移動並移到字尾
C-b 向上捲一頁
C-f 向下捲一頁
C-u 向上捲半頁
C-d 向下捲半頁
/ 與 ? 向下或向上尋找字串
(space) 第一次按下到第二次按下的區域會被複製到暫存區內
(ESC) 離開 複製/卷軸 模式
接著按下 C-a ] 便可以把剛剛存到暫存區內的內容複製出來。

善用 screen
前面提到當按了 C-a d 脫離了 screen 後,會回到沒有執行 screen 時的狀態,但是同時在之前 screen 裡每個視窗內在跑的 process (不管是前景或背景執行的)仍然繼續執行,即使 logout 也不會有影響。所以你可能接著離開身邊的電腦,然後跑出去喝個水,或者另外找個舒服的地方坐下來再接著剛剛的工作。

好,當你重新登入(login)之後,要怎麼接回剛剛的 screen 呢?重打 screen 只會讓電腦另外又開個 screen 給你,你所要做的事就是加些參數:

screen -ls 顯示目前個人所有的 screen
% screen -ls
There are screens on:
1188.ttyp4.SungSung (Attached)
76920.ttypq.SungSung (Detached)
2 Sockets in /tmp/screens/S-AlanSung.


上面的 Attached 表示你現在連接的 screen ,而 Detached 則表示沒有連接的,最後則是共有多少個 screen 數量
screen -r 就是重新回到(resume)screen 裡,如果你只有開一個 screen ,那只要簡單地打
% screen -r

就沒問題了,但是像上面那個,如果你有了兩個以上的 screen ,這樣就有問題了
% screen -r
There are several screens on:
1188.ttyp4.SungSung (Detached)
76920.ttypq.SungSung (Detached)
Type “screen [-d] -r [pid.]tty.host” to resume one of them.


如它的訊息所述,你可以加上它的 process id 或是使用的 tty 加上主機名來決定要接回那一個 screen 。假設在這裡我們要接回 process id 為 1188 的那一個,就打
% screen -r 1188


% screen -r ttyp4


% screen -r ttyp4.SungSung


% screen -r 1188.ttyp4.SungSung

都可以
screen -d 假設現在自己的電腦突然當機,或是網路突然斷了一時連不上去,等到好了之後,想要接回來原來的 screen 卻發現
% screen -r
There is a screen on:
1188.ttyp4.SungSung (Attached)
There is no screen to be resumed.


這時候 -d 這個參數就派上用場了,讓你可以控制某個 screen 脫離(detach),接著再加上 -r 把這個 screen 接手回來
% screen -d
[1188.ttyp4.SungSung detached.]
% screen -r


或直接
% screen -d -r

screen -wipe
有時候不小心跳電了,這時候重開機後當然也不會有 screen 留著,但是由於 screen 會有紀錄所有的 screen ,因為雖然舊的沒有了,可是還是有紀錄在,因此這個指令就是把廢棄不用的 screen 給”擦拭乾淨”(wipe)
There are screens on:
69103.ttyp5.SungSung (Removed)
529.ttyp0.SungSung (Detached)
1 socket wiped out.
1 Socket in /tmp/screens/S-AlanSung.


會用了上面所介紹的功能,你可以現在進入 bbs ,進入聊天室跟人聊天或是在上面發表文章到一半,發現計中要關門了,你可以從容的 detach ,回家之後再連回來 attach ,繼續剛剛的話題或發表文章,而對方可能根本沒發覺。只要你連線的主機不當機,那電話線或網路再怎麼不穏都不必怕斷線。

如果你需要更多詳細的資料,可以善用線上手冊(manual pages)或是 info 這個指令
% man screen
% info screen


Ctrl-a S 就可以 split,
Ctrl-a tab 就可以切到下面的視窗,
Ctrl-a Ctrl-a 下面的視窗就可以到處切換,
Ctrl-a Q 就將分割的視窗關掉

[2014.04.28 補充]
在建立screen時,
替這一個screen建立一個名為BuildCode的screen
% screen -S BuildCode

設定快速鍵
$HOME/.screenrc
# Start message
startup_message off

# Set hardstatus always on
hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %M %d %0c:%s "

# Set default encoding using utf8
defutf8 on

# Refresh the display when exiting programs
altscreen on

# Dynamic title
shelltitle '$ |bash'

# Disable vbell
vbell off

# Keboard binding
# bind F1 to move to next window
bindkey -k k1 next

# bind F2 to create a new screen
bindkey -k k2 screen

# bind F3 to rename current screen window
bindkey -k k3 title

# bind F4 to kill current screen window
bindkey -k k4 kill

# bind F5 to detach screen session (to background)
bindkey -k k5 detach


[2014.05.26 補充]
原本screen只能讓一個user連到這一個session,
也就是說,
若由家裡連到某一個session,
則公司原本連到這一個session就會被踢掉。
但是,事實上,screen其實可以允許多個user連到某一個session,
只要後面連到seesion的加入-x的參數即可,
而這兩個畫面會同步,
非常有趣

刪除指定的screen section
% screen -X -S [session # you want to kill] kill
參考資料:
Introduction to screen
screen 教學
unix 上 screen 指令用法
Set screen names with GNU screen [closed]
使用 Screen 指令操控 UNIX/Linux 終端機的教學與範例
screen教學(linux終端機有多個分頁)
[Linux] screen教學與bindkey設定用法
進化版 screen - tmux

2009年5月25日 星期一

如何使用Sctp的partial reliability

因為要寫一個handover的網路電話,所以必需要知道目前使用的線路可能快要有問題了, 必需要切換線路,其中一個方式就是使用SCTP_SEND_FAILED的這一個事件。

SCTP_SEND_FAILED的介紹
When a message can't be delivered to a peer, the message is sent back to the user through this notification.
This notification is usually soon followed by an association failure notification.

基本上會出現SCTP_SEND_FAILED只有以下兩個情況
1. In most cases, the only way a message will not be delivered is if the association has failed.
只有當目前的這一個association才會顯示SCTP_SEND_FAILED
2. The only time a message failure will occur without an association failure is when the partial reliability extension of SCTP is being used
當有使用partial reliability時,若沒有在限定的時間(TTL[time to live])內送出去的話, 也會觸發SCTP_SEND_FAILED的事件

研究了好久, 總算知道如何使用partial reliability啦~
這裡使用的是one-to-one 的sctp, 也就是tcp style 的sctp,
one-to-many是不是也是一樣的設定方式,目前還不知道

這裡我們把它分為sender端與receiver端
sender端:
1. 在accept後, 要設定由accept回傳的connfd為SCTP_NODELAY, 因為若沒有設定SCTP_NODELAY的話,那麼程式會等收集到一定的量才送出資料,這個時候就會超過TTL的時間才送出去, 就會觸發SCTP_SEND_FAILED的事件啦, 以下的程式片斷
struct sockaddr_in sd;
int connfd;
int flag=1;
socklen_t sdlen = sizeof(sd);
sockfd = ::socket(AF_INET,SOCK_STREAM,IPPROTO_SCTP);
sctp_sa.sin_family = AF_INET;
sctp_sa.sin_port = htons(1234);
sctp_sa.sin_addr.s_addr = htons("127.0.0.1");

connfd = ::accept(sockfd,(struct sockaddr *) &sd, (socklen_t *)&sdlen);
setsockopt(connfd,IPPROTO_SCTP,SCTP_NODELAY,&flag,sizeof(flag));


2. 在sctp_sendmsg的ttl欄位要加入你要設定的時間, 若是0的話, 則表示沒有限制
ssize_t sctp_sendmsg(int sockfd,const void *msg,size_t msgsz, const struct sockaddr *to,socklen_t tolen,uint32_t ppid, uint32_t flags,uint16_t stream, uint32_t timetolive,uint32_t context);
這裡另外提到,在one-to-one的情況下若to是NULL的話,則會送到目前這一個association的primary address,當to是NULL的話,tolen必需要設定為0

receiver端也有兩點要注意:
1. 要設定要監控sctp_send_failure_event
struct sctp_event_subscribe event;

event.sctp_send_failure_event = 1;
setsockopt(connfd,IPPROTO_SCTP,SCTP_EVENTS,&event,sizeof(event));


2. 由接收到的資料來判斷是否為sctp_send_failure_event事件, 以下是以one-to-one來當作例子
char inputBuffer[1024];
struct sockaddr_in peer,
int msg_flags;
struct sctp_sndrcvinfo sndrcvinfo;
socklen_t peerlen = sizeof(peer);
::sctp_recvmsg(connfd,inputBuffer,sizeof(inputBuffer),(struct sockaddr *) &peer,&peerlen,&sndrcvinfo,&msg_flag);
if (msg_flag & MSG_NOTIFICATION) // 判斷是否為事件, 若成立表示為事件
{
union sctp_notification *snp = (union sctp_notification *) inputBuffer;
switch (snp->sn_header.sn_type)
{
case SCTP_SEND_FAILED:
printf("SCTP_SEND_FAILED\n");
break;
default:
printf("unknow notification\n");
}
}


以上就可以判斷是否有Sendfail的事件啦

2009年5月22日 星期五

手機身份証

今天約學弟一起去吃冰,沒有想到學弟的手機不見了,這個時候跟他們討論起手機身份証。

*#06#

在手機上按下以上的按扭就會出現這一支手機獨有的號碼。

以下是轉錄的資料

手機有「身份證字號」這則謠言在網路流傳已久,關於電信警察究竟會不會依此號碼幫人找回手機也一直有爭議,有人說會,有人說不會--其實,這兩個答案都不對,以下是我們的調查。

在網路上流傳的這則電子郵件說,只要在手機上輸入「*#06#」就能看到手機的身份證字號,這點並沒有錯,這個號碼是手機本身的IMEI序號,每隻手機都是獨一無二的。不過接下來的部分就有待商榷了。

首先是向電信警察局報案。據我們向電信警察隊查詢,他們表示,手機的遺失可以分為失竊與遺失兩種,前者可向警察局報案,至於後者,電信警察隊則做了個有趣的比方:「就像你掉了五百、一千元。」

電信警察隊表示,「理論」上,是可以透過IMEI號碼追查遺失手機。不過,「實際」上卻有很大的困難,最主要的問題還是在經費上。舉例來說,假設今天有人掉了一支手機,為了追查訊號,必須調閱六家電信業者的通聯紀錄,以一天一家120元來計算,光一支手機一天就要花720元的調查經費,如果運氣不好,撿到的人遲遲不使用,一連查個五天,差不多就可以買支新手機了。

不過,要說報案無用,那也不全對。假設你的手機不是失竊,而是被好心人撿到,你又剛好有在警察局備案,那麼,警察就可以根據你留下的IMEI號碼通知你來領回。

至於7日發表的「30分鐘快速維修手機 竟成銷贓最佳管道」一案,為什麼電信警察隊又主動偵辦了呢?

電信警察隊表示,上述案件應該視為「個案」。民眾來報案,他們當然都會受理,不過電信警察最主要的任務並不是找手機,除非是上級指示配合重大案件辦案,否則,一般民眾手機遺失,即使到電信警察隊報案,要找回來,也要看「天時、地利、人和」...簡單的說,就是「看情況」。

參考資料:
[資訊]手機身份證

2009年5月21日 星期四

RGB ,YUV, YCbCr的定義

YUV

視頻編解碼器功能
視頻編碼器要求YUV4:2:0格式的視頻輸入,因此可能根據應用需要進行視頻輸入的預處理,即對YUV4:2:2隔行掃瞄(例如從攝像機)到YUV 4:2:0非隔行掃瞄轉換,僅抽取但不過濾UV分。對視頻解碼器而言,還需要進行後處理,以將解碼的YUV 4:2:0數據轉換為RGB進行顯示,包括:YUV 4:2:0到RGB轉換;16位或12位RGB顯示格式;0到90度旋轉,實現橫向或縱向顯示。此外,視頻編解碼器通常還要求具有以下功能和特性:
支持MPEG-4簡單類 0、1 與 2 級;
兼容H.263與 MPEG-4 編解碼標準;
MPEG-4視頻解碼器支持的可選項有:AC/DC預測、可逆可變長度編碼(RVLC)、再同步標誌(RM)、數據分割(DP)、錯誤隱藏專利技術、支持每個宏塊4個運動矢量(4MV)、自由運動補償、解碼VOS層;
MPEG-4視頻編碼器選項有:RVLC、RM、DP、支持每個宏塊4個運動矢量(4MV)、報頭擴展碼、支持編碼期間碼率改變、支持編碼期間編碼幀率改變、插入或不插入可視對象序列起始碼;
支持編碼期間序列中插入I幀;
支持編碼器自適應幀內刷新(AIR);
支持多編解碼器,可用相同代碼運行多個編解碼器實例。

RGB

紅綠藍(RGB)是計算機顯示的基色,RGB565支持的色深可編程至高達每像素16位,即 RGB565(紅色5位,綠色6位,藍色5位)。

YCbCr

在DVD、攝像機、數字電視等消費類視頻產品中,常用的色彩編碼方案是YCbCr,其中Y是指亮度份量,Cb指藍色色度份量,而Cr指紅色色度份量。人的肉眼對視頻的Y份量更敏感,因此在通過對色度份量進行子採樣來減少色度份量後,肉眼將察覺不到的圖像質量的變化。主要的子採樣格式有YCbCr 4:2:0、YCbCr 4:2:2 和 YCbCr 4:4:4。
4:2:0表示每4個像素有4個亮度份量,2個色度份量(YYYYCbCr),僅採樣奇數掃瞄線,是便攜式視頻設備(MPEG-4)以及電視會議 (H.263)最常用格式;4:2:2表示每4個像素有4個亮度份量,4個色度份量(YYYYCbCrCbCr),是DVD、數字電視、HDTV 以及其它消費類視頻設備的最常用格式;4:4:4表示全像素點陣(YYYYCbCrCbCrCbCrCbCr),用於高質量視頻應用、演播室以及專業視頻產品。

轉換的公式
第一個公式是YUV轉換RGB(範圍0-255)時用的,第二個公式是用在YUV(601)也成為YCbCr轉換RGB(範圍0-255)時用的。

1.
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U

2.
B= 1.164 * (Y - 16) + 2.018 * (U - 128)
G= 1.164 * (Y - 16) - 0.38 * (U - 128) - 0.813 * (V - 128)
R= 1.164 * (Y - 16) + 1.159 * (V - 128)

參考資料:
RGB ,YUV, YCbCr的定義
RGB ,YUV, YCbCr的轉換

2009年5月19日 星期二

如何使用Qt designer

耶,目前還是主要以Qt3在寫程式,所以,先用Qt3的designer來說明吧~
在開發Qt視窗程式時,我們可以使用Qt Designer的所視即所得環境,協助我們進行視窗外觀的設計,並透過指令產生對應的*.h與*.cpp檔案,這邊介紹Qt Designer的一些簡單的使用方法。

首先開啟Qt Designer,執行選單中的[File/New]指令(或按Ctrl+N)新增要使用的視窗類型,如下圖所示:


接下來的畫面與Visual Basic很像,我們在左邊的Toolbox選擇元件,在中間的表單區域以拖拉的方式配置元件,在右邊的Property Editor設定相關屬性,假設我們的元件如下配置:


接下來我們進行簡單的Signals - Slots連結,執行選單中的[Tools/Connect Signal/Slots]指令(或按F3),然後選擇發出Signal的元件,接著會出現以下視窗,在這邊我們簡單的設定按下按鈕後關閉視窗:


您可以執行選單中的[Preview/Preview Form]指令(或按Crtl+T)來預覽配置成果,接下來我們執行[File/Save]指令(或按Ctrl+S),將之儲存為form1.ui檔,這個檔案一堆描述元件屬性的標籤所組成,我們可以使用下面的指令來產生*.h檔:
$ uic -o form1.h form1.ui

然後我們使用下面的指令產生*.cpp檔:
$ uic -i form1.h -o form1.cpp form1.ui

您可以直接開啟這兩個檔案來看看它們的內容,並根據實際需求再作些修改,下面是我們產生的*.h檔內容:
/****************************************************************************
** Form interface generated from reading ui file 'form1.ui'
**
** Created: 二 5月 19 21:37:24 2009
**
** WARNING! All changes made in this file will be lost!
****************************************************************************/


#ifndef FORM1_H
#define FORM1_H

#include <qvariant.h>
#include <qdialog.h>

class QVBoxLayout;
class QHBoxLayout;
class QGridLayout;
class QSpacerItem;
class QLabel;
class QPushButton;

class Form1 : public QDialog
{
Q_OBJECT

public:
Form1( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
~Form1();

QLabel* textLabel1;
QPushButton* pushButton1;

protected:

protected slots:
virtual void languageChange();

};

#endif // FORM1_H



下面是產生的*.cpp內容:
/****************************************************************************
** Form implementation generated from reading ui file 'form1.ui'
**
** Created: 二 5月 19 21:38:40 2009
**
** WARNING! All changes made in this file will be lost!
****************************************************************************/


#include "form1.h"

#include <qvariant.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>

/*
* Constructs a Form1 as a child of 'parent', with the
* name 'name' and widget flags set to 'f'.
*
* The dialog will by default be modeless, unless you set 'modal' to
* TRUE to construct a modal dialog.
*/

Form1::Form1( QWidget* parent, const char* name, bool modal, WFlags fl )
: QDialog( parent, name, modal, fl )
{
if ( !name )
setName( "Form1" );

textLabel1 = new QLabel( this, "textLabel1" );
textLabel1->setGeometry( QRect( 210, 30, 150, 65 ) );

pushButton1 = new QPushButton( this, "pushButton1" );
pushButton1->setGeometry( QRect( 250, 140, 82, 27 ) );
languageChange();
resize( QSize(582, 307).expandedTo(minimumSizeHint()) );
clearWState( WState_Polished );

// signals and slots connections
connect( pushButton1, SIGNAL( clicked() ), this, SLOT( close() ) );
}

/*
* Destroys the object and frees any allocated resources
*/

Form1::~Form1()
{
// no need to delete child widgets, Qt does it all for us
}

/*
* Sets the strings of the subwidgets using the current
* language.
*/

void Form1::languageChange()
{
setCaption( tr( "Form1" ) );
textLabel1->setText( tr( "<h1>Qt Designer</h1>" ) );
pushButton1->setText( tr( "Click me" ) );
}


我們使用下面這個main.cpp程式來測試成果:
#include "form1.h"
#include <qapplication.h>

int main(int argc, char **argv) {
QApplication app(argc, argv);

Form1 *fm = new Form1();
app.setMainWidget(fm);
fm->show();

return app.exec();
}


$ qmake-qt3 -project
$ qmake-qt3
$ make



參考資料:
使用Qt Designer設計視窗

租房子的注意事項

[重要]
1. 水泥隔間,隔音效果比較好
2. 要有對外窗戶(不然,尤其是套房有浴室的,可能會很潮濕,長黴菌之類的, 你不知道現在是什麼時候)
3. 最好要有獨立電表(避免產生糾紛)
4. 最好不要在大馬路旁,會神經衰弱(就算有氣密窗也是一樣,這樣,你就要24小時關窗戶,那跟沒有窗戶是一樣的)
5. 最好的話,房東不要「只」有老婆婆或老公公,東西壞掉可能要己自處理,維修反應會比較慢,跟他講網路也不一定懂
6. 房東不能背景太複雜
7. 訂金給個500-1000就好,不用給太多,若房東不能接受會自己提出來
8. 要有網路

XX. 是否有第四台
XX. 是否有飲水機
XX. 是否有電梯
XX. 是否有陽台(曬衣服的地方)
XX. 冰箱
XX. 電視
XX. 洗衣機
XX. 垃圾怎麼倒
XX. 水費, 瓦斯, 電費租金有內含嗎,若有費用怎麼算

2009年5月18日 星期一

OpenCV - 縮小圖像

#include <stdio.h>
#include <cv.h>
#include <highgui.h>

int main()
{
char FileName[10]="rain.jpg";

// 來源指標
IplImage *src = 0;

// 目的指標
IplImage *dst = 0;

// 縮小倍數
float scale = 0.618;

// 目標圖像的大小
CvSize dst_cvsize;

// 載入圖檔
src = cvLoadImage("rain.jpg",1);

// 設定目標寬為100 pixel
dst_cvsize.width = 100;
// 同比例縮小
dst_cvsize.height = src->height * ((float) dst_cvsize.width/src->width);

// 建構目標圖像
dst = cvCreateImage(dst_cvsize,src->depth,src->nChannels);

// 縮小來源圖到目標圖像
cvResize(src,dst,CV_INTER_LINEAR);

// 列印出原圖與縮小後圖的大小
printf("the original size is %i\n",src->imageSize);
printf("the scaled size is %i\n",dst->imageSize);

cvNamedWindow("src",CV_WINDOW_AUTOSIZE);

cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);

// 顯示來源圖像
cvShowImage("src",src);

// 顯示目標圖像
cvShowImage("dst",dst);

// 等待用戶反應
cvWaitKey(-1);

// 釋放來源圖占用的記憶體
cvReleaseImage(&src);

// 釋放目標圖占用的記憶體
cvReleaseImage(&dst);

return 0;
}


編譯方式:
$ gcc `pkg-config opencv --libs --cflags` main.c -o main

參考資料:
縮放圖片

OpenCV - 如何將IplImage型態的image轉換為unsigned char的形式供後續處理?

// start capturing frames from camera
// 0:autodetect

CvCapture *camera = cvCreateCameraCapture(0);
// 確認camera不為NULL
assert(camera);
IplImage *image = cvQueryFrame(camera);
// 確認camera不會NULL
assert(image);
// 求得image的影像大小資訊
CvSize imgSize;
imgSize = cvGetSize(image);
// 將IplImage型態的 image 轉換為 BYTE的image_rawdata
void *image_rawdata;
cvGetImageRawData( image, ( uchar** )&image_rawdata, 0, &imgSize );
// image 是3個channel (RGB) image_rawdata 的大小為 Height * Width * 3
for(j = 0; j < imgSize.height ; j ++) for(i = 0; i < imgSize.width ; i ++)
{
// 取得第(i,j) pixel 的 R、G、B值
B = image_rawdata[(j * imgSize.width + i) * 3 + 2];
G = image_rawdata[(j * imgSize.width + i) * 3 + 1];
R = image_rawdata[(j * imgSize.width + i) * 3 + 0];
}


參考資料:
OpenCV DIY手冊

RGB32的說明

計算機彩色顯示器顯示色彩的原理與彩色電視機一樣,都是採用R(Red)、G(Green)、B(Blue)相加混色的原理:通過發射出三種不同強度的電子束,使屏幕內側覆蓋的紅、綠、藍磷光材料發光而產生色彩。
這種色彩的表示方法稱為RGB色彩空間表示(它也是多媒體計算機技術中用得最多的一種色彩空間表示方法)。
根據三基色原理,任意一種色光F都可以用不同份量的R、G、B三色相加混合而成。
F = r [ R ] + g [ G ] + b [ B ]
其中,r、g、b分別為三基色參與混合的係數。當三基色份量都為0(最弱)時混合為黑色光;而當三基色份量都為k(最強)時混合為白色光。調整r、g、b三個係數的值,可以混合出介於黑色光和白色光之間的各種各樣的色光。

各種RGB格式
RGB1、RGB4、RGB8都是調色板類型的RGB格式,在描述這些媒體類型的格式細節時,通常會在BITMAPINFOHEADER數據結構後面跟著一個調色板(定義一系列顏色)。它們的圖像數據並不是真正的顏色值,而是當前像素顏色值在調色板中的索引。以RGB1(2色位圖)為例,比如它的調色板中定義的兩種顏色值依次為0x000000(黑色)和0xFFFFFF(白色),那麼圖像數據001101010111…(每個像素用1位表示)表示對應各像素的顏色為:黑黑白白黑白黑白黑白白白…。

RGB565使用16位表示一個像素,這16位中的5位用於R,6位用於G,5位用於B。程序中通常使用一個字(WORD,一個字等於兩個字節)來操作一個像素。當讀出一個像素後,這個字的各個位意義如下:
高字節 低字節
R R R R R G G G G G G B B B B B
可以組合使用屏蔽字和移位操作來得到RGB各份量的值:

#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取值範圍0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取值範圍0-63
B = wPixel & RGB565_MASK_BLUE; // 取值範圍0-31

RGB555是另一種16位的RGB格式,RGB份量都用5位表示(剩下的1位不用)。使用一個字讀出一個像素後,這個字的各個位意義如下:
高字節 低字節
X R R R R G G G G G B B B B B (X表示不用,可以忽略)
可以組合使用屏蔽字和移位操作來得到RGB各份量的值:

#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取值範圍0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取值範圍0-31
B = wPixel & RGB555_MASK_BLUE; // 取值範圍0-31

RGB24使用24位來表示一個像素,RGB份量都用8位表示,取值範圍為0-255。注意在內存中RGB各份量的排列順序為:BGR BGR BGR…。通常可以使用RGBTRIPLE數據結構來操作一個像素,它的定義為:

typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 藍色份量
BYTE rgbtGreen; // 綠色份量
BYTE rgbtRed; // 紅色份量
} RGBTRIPLE;


RGB32使用32位來表示一個像素,RGB份量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是帶Alpha通道的 RGB32。)注意在內存中RGB各份量的排列順序為:BGRA BGRA BGRA…。通常可以使用RGBQUAD數據結構來操作一個像素,它的定義為:

typedef struct tagRGBQUAD {
BYTE rgbBlue; // 藍色份量
BYTE rgbGreen; // 綠色份量
BYTE rgbRed; // 紅色份量
BYTE rgbReserved; // 保留字節(用作Alpha通道或忽略)
} RGBQUAD;

OpenCV相關函式與資料結構

這一個是在opencv上很常用的資料結構

資料結構都放在/usr/include/opencv/cxtypes.h

/****************************************************************************************\
* Image type (IplImage) *
\****************************************************************************************/


#ifndef HAVE_IPL

/*
* The following definitions (until #endif)
* is an extract from IPL headers.
* Copyright (c) 1995 Intel Corporation.
*/

#define IPL_DEPTH_SIGN 0x80000000

#define IPL_DEPTH_1U 1
#define IPL_DEPTH_8U 8
#define IPL_DEPTH_16U 16
#define IPL_DEPTH_32F 32

#define IPL_DEPTH_8S (IPL_DEPTH_SIGN| 8)
#define IPL_DEPTH_16S (IPL_DEPTH_SIGN|16)
#define IPL_DEPTH_32S (IPL_DEPTH_SIGN|32)

#define IPL_DATA_ORDER_PIXEL 0
#define IPL_DATA_ORDER_PLANE 1

#define IPL_ORIGIN_TL 0
#define IPL_ORIGIN_BL 1

#define IPL_ALIGN_4BYTES 4
#define IPL_ALIGN_8BYTES 8
#define IPL_ALIGN_16BYTES 16
#define IPL_ALIGN_32BYTES 32

#define IPL_ALIGN_DWORD IPL_ALIGN_4BYTES
#define IPL_ALIGN_QWORD IPL_ALIGN_8BYTES

#define IPL_BORDER_CONSTANT 0
#define IPL_BORDER_REPLICATE 1
#define IPL_BORDER_REFLECT 2
#define IPL_BORDER_WRAP 3

typedef struct _IplImage
{
int nSize; /* sizeof(IplImage) */
int ID; /* version (=0)*/
int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */
int alphaChannel; /* ignored by OpenCV */
int depth; /* pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported */

char colorModel[4]; /* ignored by OpenCV */
char channelSeq[4]; /* ditto */
int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels.
cvCreateImage can only create interleaved images */

int origin; /* 0 - top-left origin,
1 - bottom-left origin (Windows bitmaps style) */

int align; /* Alignment of image rows (4 or 8).
OpenCV ignores it and uses widthStep instead */

int width; /* image width in pixels */
int height; /* image height in pixels */
struct _IplROI *roi;/* image ROI. if NULL, the whole image is selected */
struct _IplImage *maskROI; /* must be NULL */
void *imageId; /* ditto */
struct _IplTileInfo *tileInfo; /* ditto */
int imageSize; /* image data size in bytes
(==image->height*image->widthStep
in case of interleaved data)*/

char *imageData; /* pointer to aligned image data */
int widthStep; /* size of aligned image row in bytes */
int BorderMode[4]; /* ignored by OpenCV */
int BorderConst[4]; /* ditto */
char *imageDataOrigin; /* pointer to very origin of image data
(not necessarily aligned) -
needed for correct deallocation */

}
IplImage;


函式都放在/usr/include/opencv/cxcore.h中

/* Returns width and height of array in elements */
(CvSize) cvGetSize( const CvArr* arr );

/usr/include/opencv/highgui.h

/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */
(CvCapture*) cvCreateCameraCapture( int index );

/* Returns width and height of array in elements */
CVAPI(CvSize) cvGetSize( const CvArr* arr );

/usr/include/opencv/cxtypes.h
// CvArr就是void
typedef void CvArr;

/* Retrieves raw data of CvMat, IplImage or CvMatND. In the latter case the function raises an error if the array can not be represented as a matrix */
把IplImage轉換成uchar資料陣列
(void) cvGetRawData( const CvArr* arr, uchar** data, int* step CV_DEFAULT(NULL), CvSize* roi_size CV_DEFAULT(NULL));
(void) cvGetImageRawData( const CvArr* arr, uchar** data, int* step CV_DEFAULT(NULL), CvSize* roi_size CV_DEFAULT(NULL));

2009年5月17日 星期日

Flash player 或其他應用程式的中文為亂碼

症狀:觀看 Youtube 影片時只能看見矩形文字,無法正確顯示中文。

最簡單的方法刪除 /etc/fonts/conf.avail/49-sansserif.conf。

如果讀者欲知詳情,中文亂碼來自於 sans-serif 的錯誤設定,不需要刪除 49-sansserif.conf ,轉而修正 /etc/fonts/conf.avail/69-language-selector-zh-tw.conf 也可以解決問題。在 69-language-selector-zh-tw.conf 的段落:

<test qual="any" name="family">
<string>sans-serif</string>
</test>
<edit name="family" mode="prepend" binding="strong">
<string>Bitstream Vera Sans</string>
<string>DejaVu Sans</string>
<string>WenQuanYi Zen Hei</string>
<string>AR PL UMing TW</string>
<string>AR PL ShanHeiSun Uni</string>
<string>WenQuanYi Bitmap Song</string>
<string>AR PL UKai TW</string>
<string>AR PL ZenKai Uni</string>
</edit>


修改如下:

<test qual="any" name="family">
<string>sans-serif</string>
</test>
<edit name="family" mode="prepend" binding="strong">
<string>WenQuanYi Zen Hei</string>
<string>AR PL UMing TW</string>
<string>AR PL ShanHeiSun Uni</string>
<string>WenQuanYi Bitmap Song</string>
<string>Bitstream Vera Sans</string>
<string>DejaVu Sans</string>
<string>AR PL UKai TW</string>
<string>AR PL ZenKai Uni</string>
</edit>


參考資料:
Flash player 或其他應用程式的中文為亂碼

2009年5月15日 星期五

修改IHU的configure檔案

因為要加入一些新的class到project裡面,因此,要重新修改Makefile

而這一個Makefile是由autoconf與automake所建立的,因此要修改使得可以建立新的Makefile,但是,因為我不熟autoconf與automake所以,目前還是失敗的,先列出我目前使用的步驟吧~

1. 複製SctpSocketHandler.cpp與SctpSocketHandler.h到src

2. 修改Makefile.am加入SctpSocketHandler.cpp與SctpSocketHandler.h

3. 在Receiver.hpp與Transmitter.hpp加入#include "SctpSocketHandler.h"

4. autoconf
產生configure檔案

5. aclocal
產生aclocal.m4

6. automake --add-missing
產生Makefile.in

7. LIBS=-lsctp ./configure
產生Makefile

8. make
編譯

[2009.05.26 補充]
要在ihu的專案中加入一個具有Q_OBJECT, slots, signals
必需要依以下步驟...
例如要加入Ren.hpp與Ren.cpp
這裡要注意的是, header file一定是要hpp的副檔名
1. 在Makefile.am的ihu_SOURCES加入src/Ren.hpp src/Ren.cpp

2. 同時在Makefile.am的nodist_ihu_SOURCES加入src/moc_Ren.cpp

3. 在configure.ac的AM_INIT_AUTOMAKE改成AM_INIT_AUTOMAKE(Ihu, 1.0)

4. 然後依以上方式執行autoconf;aclocal;automake --add-missing;LIBS=-lsctp ./configure

5. make

[2009.05.28 補充]
為了避免每一次configure均加上LIBS=-lsctp
我們要修改configure.ac檔案加入
下面這一個是加入一個sctp的library
AC_CHECK_LIB(sctp, sctp_recvmsg,, [AC_MSG_ERROR(You have get sctp to build the IHU)])

而下面這一行是檢查header file巨集
AC_CHECK_HEADER

相關autoconf與automake可以參考
【轉貼】自動產生Makefile - autoconf & automake

2009年5月13日 星期三

QStringList

這一個可以存放QString的容器類別~

#include <qapplication.h>
#include <qstringlist.h>
#include <iostream.h>
using namespace std;

int main(int argc,char **argv)
{
QStringList fonts;
// 加入字串有以下三種用法
fonts.append("Times");
fonts += "Courier";
fonts += "Courier New";
fonts << "Helvetina [Cronyx]" << "Helevtica [Adobe]";

for (QStringList::Iterator it = fonts.begin();it != fonts.end();++it)
{
cout << *it << ":";
}
cout << endl;

return 0;
}


參考資料:
QStringList Class Reference

2009年5月12日 星期二

QBoxLayout與QWidget之間的關係

因為Qt是在設計GUI介面的函式庫,因此在排版的時候,常常會牽扯到QBoxLayout與QWidget之間的關係。
我整理了以下幾種情況

QBoxLayout下面要包一個QWidget則使用
qwidget->addWidget(qboxlayout)

若QBoxLayout(qboxlayout1)下面要包一個QBoxLayout(qboxlayout2)
QBoxLayout *qboxlayout2 = new QBoxLayout(qboxlayout1);

若QWidget下面要包一個QBoxlayout則使用
QBoxLayout *qboxayout = new QBoxLayout(qwidget);

參考資料:
QBoxLayout Class Reference

Wubi - 在windows上安裝ubuntu

想要安裝ubuntu又不想重新分割硬碟也不想使用vmware的人有福啦~

原來可以在 Windows 上安裝 Ubuntu Linux(也可以選擇 Kubuntu 或 Xubuntu)!只需要執行 installer 便會去 download Ubuntu 的檔案來安裝,安裝完成後重開機就會有一個完整的 Ubuntu Linux 可以使用了;而當你不想要 Ubuntu Linux 時,只需要在 Windows 裡的「新增/移除程式」把它移除就可以了。這真是相當酷的一件事呀!

不過,它目前只能安裝在 C 磁碟下(目錄要是 C:\Ubuntu)

參考資料:
使用 Wubi 在 Windows 安裝 Ubuntu/Kubuntu/Xubuntu 9.04 (Jaunty Jackalope)
從 Windows 下安裝 Ubuntu

linux 指令 - tee

這是一個非常好用的指令,當我們在用命令重導向時,會把原本要顯示到螢幕上的資料轉儲到檔案中,例: $ whoami ren 若我們把要顯示到螢幕上的結果導到檔案中 $ whoami > whoami.file 那麼螢幕上不會有任何顯示,而且,此時會多出一個檔案,whoami.file 那麼要如何同時把結果存到檔案中,又可以顯示在螢幕上哩,這個時候就要用到tee這一個指令 $ whoami | tee whoami.file 那如果要把要顯示在螢幕上的再分析一次哩,那請用 $ whoami | tee whoami.file | 分析指令  [2009.05.20 補充] 那麼要如何同時把錯誤顯示在螢幕上, 又可以導到檔案中哩... $ make xyz 2>&1 | tee xyz.log 先看下面這一個例子吧~ $ find /home -name .bashrc > list.file 2>&1 是表示說把正確的訊息與錯誤的訊息寫到同一個檔案中, 也就是list.file這一個檔案啦~ 也就是說&1表示的就是前一個導向的檔案 因為,平常的訊息若沒有特別設定的話,是導到stdout,也因此, $ make xyz 2>&1 | tee xyz.log &1所代表是前一個的導向檔案,所以目前的&1是代表stdout,所以,此時stdout會有正確與錯誤訊息, 再用tee把stdout導到檔案中, 所以檔案中就會有正確與錯誤的訊息啦 也可以用以下指令代替 $ make xyz 2>/dev/stdout | tee xyz.log [2010.01.22 補充] 這裡是說,如何把stdout(正確的訊息)與errout(錯誤的訊息)同時傳送到一個檔案中 以下是把nmake的產出訊息全部傳送到message.txt中 $ nmake > message.txt 2>&1 也可以使用以下方式,不過,以下方式在windows下似乎沒有辦法使用~ $ nmake &> message.txt 參考資料: 鳥哥的私房菜 How to use tee with stdout and stderr?

Ekiga - 網路視訊電話

這一個網路視訊電話的前身是Gnome meeting,是我寄信問之前的「一哥」學長所得知的情報。

當他知道我要把他之前的網路電話加上視訊時,提出了這一個建議,不知道是否用Gnome meeting改成sctp base的會比較快。

看起來是這樣沒有錯,但是,gnome meeting是以gtk來寫介面的,而我之前是使用Qt來寫介面的,很怕到時候會遇到一堆介面上的問題,所以,我還是用IHU來改寫就好了吧~

不過,這裡留下在ubuntu下安裝Ekiga的教學連結
Compile your own SVN version of Ekiga on Ubuntu

2009年5月11日 星期一

中斷的類型

中斷的種類可分為軟體中斷及硬體中斷,而硬體中斷又可分為內部及外部,外部中斷還可分為不可遮罩式(non-maskable interrupt)和可遮罩式(maskable interrupt)兩種。

中斷的類型
1. 軟體中斷
2. 硬體中斷
2.1. 內部
2.2. 外部
2.2.1. 可遮罩式
2.2.2. 不可遮罩式

(1)軟體中斷(software interrupt)

由CPU執行一個中斷指令產生中斷要求,例如80×86CPU的INT ××指令。此種中斷雖然不是偶發性的,是由程式安排而產生,但是執行INT中斷指令時,CPU處理程序與硬體中斷相同,故仍歸類於中斷的類型。軟體中斷主要的用途是為了方便呼叫基本輸入輸出系統(Basic Input Output System, BIOS)和磁碟作業系統(Disk Operating System , DOS)中的公用服務程式,例如鍵盤取字,輸出字元到螢幕,讀取磁區等等。當BIOS版本更新時只要更改中斷向量表中的中斷程式起始位址,您就可不必在意這些程式的位址及內容,只需知道中斷編號××(中斷向量)就可以呼叫得到它們。

(2)硬體中斷(hardware interrupt)

硬體中斷是可以分為內部和外部的,內部的中斷發生於CPU演算時產生錯誤,例如除法時分母為零或宣告了溢位中斷服務等,內部的中斷也發生於除錯程式中的單步執行和中斷位址(中斷點)的設定(請參考3.1-3節,TF旗標的功能),這些中斷均由CPU內部硬體電路的狀態而產生。而外部的中斷是經由CPU的接腳輸入產生的,包括了重置(reset)輸入線、不可遮罩式中斷(non-maskable interrupt)和可遮罩式中斷(maskable interrupt)等輸入線。

參考資料:
中斷的類型

2009年5月10日 星期日

Ubuntu如何遠端登入GUI

在ubuntu中,內建就可以讓別人使用vnc登入系統,但是,其有一個缺點,就是本地端必需要先登入一次後,別人才可以由外部連進來。

學弟說有找到一個替代方案,那就是先透過ssh連進來一次後,就可以用vnc連進來了。

基本上我之前都是用ssh來遠端連線,但是,學弟問這一個問題,讓我想要研究一下,如何由外部直接透過vnc連到主機,網路上找了一下資料,有以下幾個方式:

A. 設定開機後,主機不需要設定密碼,就可以直接登入
    1. 開機直接自動登入系統畫面
    在桌面左上角的 系統 →管理 → 登入畫面點選 "安全性"標籤將 "啟用自動登入" 勾選然後在 "使用者" 欄位輸入你的登入帳號重新開機然後會要求輸入密碼這樣以後開機就會自動登入到桌面了.(重開機後輸入密碼,以後開機就會自動登入)
    2. 遠端登入設定
    System → Preferences → Remote Desktop
    將下列幾項打勾:
    a.允許其他使用者觀看您的桌面
    b.允許其他使用者控制您的桌面
    c.使用者需要輸入密碼 (設定認證密碼)
    2-2.登入:
    VNCVeiw → 輸入ServerIP:0 → 輸入登入密碼


B. 遠端桌面 by XDMCP
    開啟 XDMCP:

    「系統」→「管理」→「登入畫面」,切換到「遠端」的Tab,將「風格」改成「當成本地端」。

    如果你不想依賴 GUI:

    1. 編輯「/etc/gdm/gdm.conf」和「/etc/gdm/gdm.conf-custom」

    2. 找到 [daemon] 下面的「RemoteGreeter」,將前面的 # 拿掉。

    3. 找到 [xdmcp],將下面的「Enable=false」改成「Enable = true」。

    最後,重開 gdm:

    # sudo /etc/init.d/gdm restart

    就可以了。

    登入:

    在 Linux 下面有滿方便的工具 - tsclient,可以用。它可以連到 RDP(Windows 的遠端登入協定)、VNC、XDMCP、ICA 等。當然 Ubuntu 下面預設就安裝了,不過可能有用過的人會發現 XDMCP 是灰色的,無法選擇,因為他還需要安裝 xnest:

    # sudo apt-get install xnest

    這樣就可以使用了。

Linux Bonding (合併網卡) 實作

這是之前找到的資料,是透過兩張網卡,合併成一個ip,假設其中一個網路斷線,仍然可以傳送資料到網路上,資料是找了,但是還是沒有時間看,先把聯結留著吧。

參考資料:
Linux Bonding (合併網卡) 實作
聯成電腦講師專欄: 使用 BONDING 網路功能 by 小州老師

在舊的系統安裝firefox3

這是之前在安裝舊的系統時,因預設是安裝firefox2,而想要改到firefox3所找到的資料。

Installing Firefox 3 on older Linux systems

Linux 終端機警告音

在終端機中,有一個很好用的功能,那就是命令補齊。

假設你要執行acroread的指令,打到acror時,再按tab鍵,若這個系統只有acror那系統會幫你補成acroread。

但是,若沒有以acror為開頭的指令,那系統每當你按tab,它會出現嗶嗶聲告知沒有這一個開頭的指令,但是,對我來說,我不想要這一個功能嗶嗶聲。

好像有兩個辦法
1. [ Terminal→ Edit→ Current Profile → general→ terminal bell 不勾選 ]

2. 把 /etc/inputrc中的set bell-style none
的註解拿走就ok了

參考資料:
VMWare/Linux 終端機警告音
關畢linux 按TAB 出現BB 叫

人格測驗

九型人格分析
我看完之後,覺得應該加一個若沒有填完,會是什麼人格,因為我沒有填完。
東邪島 - 九型人格分析(原創)

2009年5月8日 星期五

VisualSVN Server & TortoiseSVN

SVN(Subversion)是一個版本控制的軟體,因為之前為了方便控制程式碼的版本,所以,server是使用google code,而client端在windows下就是使用TortoiseSVN的圖形化介面,在Linux下就使用subversion的文字化介面,目前使用的感覺非常之好。

因為,之前我的資料均是由網路上找來的,再加上我自己寫的程式碼,我個人覺得除了我之外,應該是對其它人沒有什麼價值,所以,把資料放在google那裡,我並沒有覺得有什麼不妥,直到前幾天,學弟跟我說,他在找資料時,意外找到我放在google code的程式碼,喔耶~google在search果然不會放過自己的資料庫。

本來我是打算說,若到時候進入公司,再自己架一台svn server起來,但是,目前應該用不到。今天下午跟老弟說完之後,他非常的有興趣,好吧,那就在windows下架來試試看吧。

同樣的,在windows下安裝非常的容易。
已經成功了,詳細的以後再記錄,先把參考的資料先記錄下來吧~


Server
1. VisualSVN Server就是svn的server版,可以直在到這裡下載

2. 只有要使用指令模式才要,把SVN加入到環境變數PATH中,如C:\Program Files\Subversion\bin\

3. 選一個目錄,專門用來放許多案子用的,假設為D:\version_control_server,請在安裝的時候,選擇D:\version_control_server
而安裝目錄我還是設定在C:\Program Files\VisualSVN Server\


4. 安裝完Server後,建立你現在要產生的專案repository, 比如要建own-renyang專案
指令是用
$ svnadmin create D:\version_control_server\own-renyang
也可以使用圖形模式加入own-renyang專案,像是下圖



5. 建立使用者帳號與密碼


到E:\version_control_server\own-renyang\conf裡,修改passwd
a. 在[users]裡,加上你們案子要用的帳號和密碼
如: padsmember = padspassword

b. 修改svnserve.conf,如果你不想讓任意路人甲都可以看到你的程式,在[General]中找到一個anon-access,把它改成none
anon-access = none

c. 找到一行 password-db = passwd,把前面的井號去掉,這樣前面修改的passwd檔才會有啟用


6. 啟動SVN Server
指令模式
D:\>svnserve -d -r d:\Projects --listen-port 8443
圖形模式:
這個軟體有提供一個按扭可以直接啟動啦!


Client
好啦,安裝完Server端後,再來就是安裝Client端啦~
所有要參與計畫的人,都裝上TortoiseSVN(就一直下一步啦~),安裝完後,會被要求重新開機。

要注意的是,若Server裡面沒有任何資料,那麼一定要有人先上傳第一筆資料,這個時候要用
import
先找到你要版本控制的資料夾,裡面的資料是你要當作初始資料的上傳上去Server


這裡要注意,這個時候這一個資料夾只是把資料上傳到Server而以,並還沒有跟資料庫作連結,什麼叫與資料庫作聯結哩,當出現


那麼要如何與資料庫作聯結哩,請用
checkout

通常用來建立checkout的目錄一開始最好是空的。


其中那一個DOMAIN就是你Server的ip位置,若client與server在同一台器機上的話,改成127.0.0.1就沒有錯了啦~

當作完任何修改之後,就使用commit來提交,他會顯示你有做的任何修改!


[進階]
被版本控制的資料夾中,均會多一個隱藏檔.svn
若要把檔案給客戶的時候,不可能把這一堆.svn也同樣傳給客戶吧,也不可能要一個一個去刪啊,這個時候就要用export
請建立一個空資料夾,然後使用對那一個資料夾按右鍵,再export


建立一個空目錄,用來抓SVN Server上已經有寫的程式 (別人可能之前先傳上去的)
checkout,把URL of repository的protocol改成SVN
如: svn://qoo-home-800:8443/own-renyang


在windows上架svn server就是這麼簡單,那麼要如何由client來存取server哩~
我先試了在linux下試試看
[Linux]
1. 當然,要先裝subversion啦~debian請用apt-get而redhat請用yum
2. 若是第一次建立專案的話,先把第一個版本的檔案丟上去吧,也就是import
$ svn import project_directory https://DOMAIN:8443/svn/own-renyang/trunk
3. 事實上呢,上面那一個步驟只是把檔案丟上去而以,本地端的資料夾並沒有跟server端作聯結,必需要透過checkout, 第二個own-renyang是表示在本地端svn的最上層目錄
$ svn checkout https://DOMAIN:8443/svn/own-renyang/trunk own-renyang

剩下的部份請參考程式設計的版本控制 - SVN的基本功能介紹

以後再弄...
否則也可以參考Subversion也很清楚

[2009.07.07 補充]
TortoiseSVN 安裝好之後,預設 Checkout 出來的目錄中都會加上 .svn 隱藏目錄,裡面儲存了關於此目錄中所有檔案的版本資訊與變更狀態,就從網路上的文件中得知「建議」將預設的 .svn 修改成 _svn

最近開始將整個專案導入 Subversion 管理後,在其中一台開發主機就出問題了,載入專案時出現【Refreshing the project failed. Unable to retrieve folder information from the server.】的錯誤訊息,如下圖示:


然後用此訊息查了網路上的資訊後,終於確認只要目錄種出現任何 . (小數點) 開頭的目錄或檔案,就會導致這個問題發生,所以我必須要將所有的 .svn 目錄都改成 _svn 才行,並且修改 TortoiseSVN 的設定。

因此,我們修改 TortoiseSVN 的設定


[2010.03.13 補充]
在windows下,使用TortoiseSVN,因為,會有一個執行檔,TSVNcache.exe它會一直去掃整台電腦有SVN的資料夾,這樣會一直拖累電腦的速度~
可以使用下列的設定:
到Icon Overlays的頁面
1. 預設是「Default」選擇「Shell」會比較省資源,但是因為更新圖示的時機變成點選目錄後才更新,因此當階層目錄下最底層有更新的時候,你必須要進到最後底層才會看到紅色驚嘆號,所以你無法知道子目錄是否有異動。
如果是選擇「Default」系統會有一個常駐程式(TSVNcache.exe)即時的監控與更新圖示狀態,這樣子會比較耗用系統資源。如果你決定要選擇「Default」那建議也可以把「Unversioned files mark parent folder as modified」打勾就可以監控子目錄的異動了。
2. 這是監控的排除目錄與監控目錄,預設之下沒有任何設定,所以全部的資料都會掃,建議先將 所有的硬碟都設定成例外,然後再逐一設定專案放置的目錄(通常所有專案都會先放在一個目錄內對吧)


[2010.07.08 補充]
如何在FreeCommander可以使用svn的功能!
最近一直在使用FreeCommander來當作我的檔案管理器!
但是,透過FreeCommander確沒有辦法按右鍵對SVN的資料夾使用svn的功能!
最後發現原因竟然是把「Show overlays and context menu only in explorer」勾選起來的,就變的只能在Explorer去瀏覽資料夾時,才會產生svn的圖示和可以使用svn的功能!

參考資料:
VisualSVN Server
Subversion
SVN SERVER 安裝
How to setup SVN server
SVN (Subversion 、TortoiseSVN)設定大全
Version Control with Subversion(中文)
如何快速變更 Subversion 專用的隱藏目錄從 .svn 改成 _svn
如何優化調整 TortoiseSVN 加快執行效能
如何不被 TortoiseSVN 拖慢系統效率

2009年5月7日 星期四

sctp的one-to-one與one-to-many的不同

A-to-B
A是表示socket
B是表示association
one-to-one就是一個socket控制一個association
one-to-many就是一個socket控制多個association

在SCTP有兩個連線型態,一種是one-to-one也稱作TCP-stype
另一種是one-to-many也稱作UDP-stype

[不同點]
one-to-one:每一個socket只能有一個association→one-to-many:每一個socket可以有多個association

[相同點]
每一個association的endpoint均有multi-homing的特性
每一個association均有multi-stream的特性

2009年5月6日 星期三

解決Socket連續Bind同一個Port的問題

在IHU的程式碼中, 在建立UDP時, 看到了以下的部分
int on=1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));

這樣的設定是可以讓不同的應用程式在同時間(應該是關掉之後馬上開的情況, 請參考下面解說)使用相同的port並且執行成功…

其使用方式,
只需要在建立一個Socket之後,
使用setsockopt function就可以達到,
短時間內連續bind同一個port的功能了!

另外一提的是,如果udp, 與tcp使用相同的port,是不需要使用這一個功能的,因為tcp, udp的協定本來就不同,所以不會產生衝突哩

1、當有一個有相同本地地址和port的socket1處於TIME_WAIT狀態時,而你啟動的程序的socket2要佔用該地址和端口,你的程序就要用到該選項。
2、SO_REUSEADDR允許同一port上啟動同一服務器的多個實例(多個進程)。但每個實例綁定的IP地址是不能相同的。在有多塊網卡或用IP Alias技術的機器可以測試這種情況。
3、SO_REUSEADDR允許單個進程綁定相同的端口到多個socket上,但每個socket綁定的ip地址不同。這和2很相似,區別請看UNPv1。
4、SO_REUSEADDR允許完全相同的地址和端口的重複綁定。但這只用於UDP的多播,不用於TCP(應該也包含SCTP)。

參考資料:
解決Socket連續Bind同一個Port的問題
socket編程:SO_REUSEADDR例解

gksu - 在前景使用root的權限執行指令

在ubuntu在一般不能使用root權限登入視窗介面,只能用一般使用者的權限登入。

因此,像我要使用wireshark去監控網路的封包,就一定要用root的權限去執行,那麼就只有二個辦法,第一個是用sudo去執行,第二個辦法是在終端機直接切換成root的權限去執行,但是,這兩個都有一個缺點,就是那一個終端機必需要一直開在那裡。

那就使用捷徑吧,可是在捷徑中好像不能用[sudo 指令]

查了一下,原來是要用gksu啊,在捷徑的圖示中就使用
$ gksu -u root /usr/bin/wireshark

如下圖所示


若要呼叫有root權限的檔案瀏覽器
請建立以下結徑,其中用到的指令是
$ sudo nautilus
請參考以下圖示

參考資料:
Ubuntu - 建立 [具有 root 權限的檔案瀏覽器] 捷徑

2009年5月5日 星期二

安裝舊版的sctp

在ubuntu 7.10下所安裝的sctp可以穿透ip分享器...
但是, ubuntu 8.04之後的就沒有辦穿透ip分享器...
這裡所謂的穿透是server架在實體ip上面, 而client端是在ip分享器裡面...由client連到server端建立連線...
然後,基本上這個時候clinet端跟server端均可以互送訊息...
但是,確沒有辦法, 若不行的話,也就算了,我可以不要用ip分享器, 但是, 這個時候就又發現, wireshark不能偵測到sctp的封包, 這個時候我就受不了啦~看能不能把之前的sctp安裝起來吧~

先到lksctp 2.6.16-1.0.6
下載回來編譯...

解壓縮
$ tar -zxvf lksctp-tools-1.0.6.tar.gz
進入資料夾
$ cd lksctp-tools-1.0.6/
建立configure檔
$ ./bootstrap

若找不到libtoolize,請安裝libtool
$ sudo apt-get install libtool
檢查環境, 並建立Makefile
$ ./configure
編譯
$ make
安裝
$ sudo make install
若要移除的話
$ sudo make uninstall

編譯sctp測式程式之後,要執行檔案時,系統會說找不到libsctp.so.1
那是因為新增的sctp lib沒有放在預設的search路徑
libsctp.so.1是放在/usr/local/lib
這個時候要參考ldconfig
加入新的search lib的目錄
在/etc/ld.so.conf中, 它include
/etc/ld.so.conf.d/*.conf
所以,我們只要在/etc/ld.so.sonf.d/下新增一個sctp.conf
內容為
sctp.conf
# SCTP support
/usr/local/lib


然後再以ldconfig重新建立/etc/ld.so.cache 即可!
$ sudo ldconfig

2009年5月4日 星期一

Linux - 硬體資訊的收集

* hdparm:觀察硬碟的種種資訊;
* lspci:檢查整個系統 PCI 介面的各項裝置!很有用的指令;
* dmesg:觀察核心運作過程當中所顯示的各項訊息記錄;
* iostat:檢查整個 CPU 與周邊設備的 Input/Output 狀態。

詳情請參考鳥哥的私房菜

2009年5月1日 星期五

socket的通用函式

int getpeername(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);
socket代表在本地端代表對方的socket file descriptor
restrict是用來儲存對方的sockaddr結構的資料
address_len表示sockaddr的長度

#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *addr);

把字串形式的ip轉換成網路network address

struct hostent *gethostbyname(const char *name);
struct hostent {
char FAR* h_name;
char FAR* FAR* h_aliases;
short h_addrtype;
short h_length;
char FAR* FAR* h_addr_list;
};

name="tw.yahoo.com"把它轉換成struct hostent裡面有ip的相關資料

ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len);
有限定資料一定是由address傳送過來的

#include <sys/socket.h>
int getsockname(int socket, struct sockaddr *address, socklen_t *address_len);

如果我們不在呼本地端ip及port 號,可以將本地的op位址填入 INADDR_ANY ,port number 填入 0 ,socket 會自動使用任何一個可以使用的位址,並且填入一個1024~5000的值。

如何得知 socket 幫我們設定的 IP and PORT號~~~~可使用 getsockname()。

參考資料:
UNIX on Windows, Windows X Server, UNIX Porting - Terminal Emulation Software

qmake教學

在寫Unix程式時,需要透過Makefile使得在改寫程式碼時,要重新編譯會比較容易。
但是,好的Makefile確是非常難寫。
是的,Qt提供了qmake可以產生Makefile,而基本上,我們只要學會如何寫*.pro檔就可以很容易產生Makefile啦~

一個項目文件是用來告訴qmake關於為這個應用程序建立makefile所需要的細節。例如,一個*.cpp和*.h的列表、任何應用程序特定配置、例如一個必需要連接的函式庫、或者一個額外的包含路徑,都應該放到項目文件中。

#」註釋

你可以為項目文件添加註釋。註釋由「#」符號開始,一直到這一行的結束。

TEMPLATE」模板

模板變數告訴qmake為這個應用程序生成哪種makefile。下面是可供使用的選擇:
app - 建立一個應用程序的makefile。這是預設值,所以如果TEMPLATE沒有被指定,這個將被使用。
lib - 建立一個函式庫的makefile。
vcapp - 建立一個應用程序的Visual Studio項目文件。
vclib - 建立一個函式庫的Visual Studio項目文件。
subdirs - 這是一個特殊的模板,它可以建立一個能夠進入特定目錄並且為一個項目文件生成makefile並且為它調用make的makefile。

app」模板

「app」模板告訴qmake為建立一個應用程序生成一個makefile。當使用這個模板時,下面這些qmake系統變量是被承認的。你應該在你的.pro文件中使用它們來為你的應用程序指定特定信息。

HEADERS - 應用程序中的所有*.h的列表。
SOURCES - 應用程序中的所有*.cpp的列表。
FORMS - 應用程序中的所有.ui文件(由Qt設計器生成)的列表。
LEXSOURCES - 應用程序中的所有lex源文件的列表。
YACCSOURCES - 應用程序中的所有yacc源文件的列表。
TARGET - 可執行應用程序的名稱。默認值為項目文件的名稱。(如果需要擴展名,會被自動加上。)
DESTDIR - 放置可執行程序目標的目錄。
DEFINES - 應用程序所需的額外的預處理程序定義的列表。(就好像gcc中的 -D)
INCLUDEPATH - 應用程序所需的額外的包含路徑的列表。
DEPENDPATH - 應用程序所依賴的搜索路徑。
VPATH - 尋找補充文件的搜索路徑。
DEF_FILE - 只有Windows需要:應用程序所要連接的.def文件。
RC_FILE - 只有Windows需要:應用程序的資源文件。
RES_FILE - 只有Windows需要:應用程序所要連接的資源文件。

你只需要使用那些你已經有值的系統變量,例如,如果你不需要任何額外的INCLUDEPATH,那麼你就不需要指定它,qmake會為所需的提供默認值。例如,一個實例項目文件也許就像這樣:

TEMPLATE = app
DESTDIR = c:\helloapp
HEADERS += hello.h
SOURCES += hello.cpp
SOURCES += main.cpp
DEFINES += QT_DLL
CONFIG += qt warn_on release

如果條目是單值的,比如template或者目的目錄,我們是用「=」,但如果是多值條目,我們使用「+=」來為這個類型添加現有的條目。使用「=」會用新值替換原有的值,例如,如果我們寫了DEFINES=QT_DLL,其它所有的定義都將被刪除。

lib」模板

「lib」模板告訴qmake為建立一個庫而生成makefile。當使用這個模板時,除了「app」模板中提到系統變量,還有一個VERSION是被支持的。你需要在為庫指定特定信息的.pro文件中使用它們。
VERSION - 目標庫的版本號,比如,2.3.1。

subdirs」模板

「subdirs」模板告訴qmake生成一個makefile,它可以進入到特定子目錄並為這個目錄中的項目文件生成makefile並且為它調用make。

在這個模板中只有一個系統變量SUBDIRS可以被識別。這個變量中包含了所要處理的含有項目文件的子目錄的列表。這個項目文件的名稱是和子目錄同名的,這樣qmake就可以發現它。例如,如果子目裡是「myapp」,那麼在這個目錄中的項目文件應該被叫做myapp.pro。

CONFIG變量

配置變量指定了編譯器所要使用的選項和所需要被連接的函式庫。配置變量中可以添加任何東西,但只有下面這些選項可以被qmake識別。

下面這些選項控制著使用哪些編譯器標誌:
release - 應用程序將以release模式連編。如果「debug」被指定,它將被忽略。
debug - 應用程序將以debug模式連編。
warn_on - 編譯器會輸出儘可能多的警告信息。如果「warn_off」被指定,它將被忽略。
warn_off - 編譯器會輸出儘可能少的警告信息。

下面這些選項定義了所要連編的庫/應用程序的類型:
qt - 應用程序是一個Qt應用程序,並且Qt庫將會被連接。
thread - 應用程序是一個多線程應用程序。
x11 - 應用程序是一個X11應用程序或庫。
windows - 只用於「app」模板:應用程序是一個Windows下的窗口應用程序。
console - 只用於「app」模板:應用程序是一個Windows下的控制台應用程序。
dll - 只用於「lib」模板:庫是一個共享庫(dll)。
staticlib - 只用於「lib」模板:庫是一個靜態庫。
plugin - 只用於「lib」模板:庫是一個插件,這將會使dll選項生效。

例如,如果你的應用程序使用Qt庫,並且你想把它連編為一個可調試的多線程的應用程序,你的項目文件應該會有下面這行:

CONFIG += qt thread debug

注意,你必須使用「+=」,不要使用「=」,否則qmake就不能正確使用連編Qt的設置了,比如沒法獲得所編譯的Qt庫的類型了。

如果要使用Qt的網路以及多線程函式庫,可以指定
QT += network

在非 Qt 程序中使用 qmake
事實上,qmake非常好用,我們甚至想在非Qt程序中使用它。這也很容易。只要加入
CONFIG -= qt
那麼qmake就不會添加任何和Qt函式庫相關的header file以及lib之類的進來了。

參考資料:
qmake概念
qmake Command Reference