2009年2月28日 星期六

C與C++的差異

Incompatibilities Between ISO C and ISO C++
就記錄一下吧!!

C++ - 重載運算子

基本上運算子只有用在基本的變數型態,像是int、double、float...
而若建立的物件要加入運算的功能的話,就要在另外宣告類別中的運算子的定義

可以參考
良葛格學習筆記 - 重載運算子
良葛格學習筆記 - 使用 friend 函式重載運算子

同時,有時候會使用到return 的傳值、傳參考,所以,此篇文章也必需要參考到!

另外,必需注意的一點是若要重載ostream的<<或是>>運算子時,必需有一定的格式,我現在還不是很清楚,以後,有空再確認一下。

ostream &operator<<(ostream &s, class-name ob) {
// 實作
return s;
}

以下有一個我寫的例子
main.cpp
#include <iostream>
using namespace std;

class Foo
{
public:
Foo() {
// do nothing
}
void operator<<(const int value) const {
cout << "Hello World!!" << endl;
}
};

int main()
{
Foo foo;
// 會印出Hello World!!
foo<<2;
return 0;
}

2009年2月26日 星期四

socket using c++

參考資料:
A Stream Socket API for C++

2009年2月25日 星期三

資料救援

因為學長的程式在Ubuntu 8.04編譯不會過,
沒有時間研究在Ubuntu 8.04下如何解決這一個問題,
再加上電腦的資料也該整理一下了,
所以,就準備重灌實驗室的桌機。

但是,因為BIOS的關係,在灌的時候系統常會出現out of cylinder
試了好幾種排列方式,最後,以下的方式對我的主機版是可以的。
Ubuntu 7.10 - 20G
Ubuntu 8.04 - 20G
XP - 40G
swap 2G

好啦,因為我的主機版上面有兩顆硬碟,而linux的grub的硬碟順序跟進入系統後的硬碟順序又不一樣,所以,我在灌grub時,常常會指定錯的路徑,結果當我灌好系統之後,有一些磁區的分割表被我的grub蓋過去。
所以,灌好系統之後,我必需recovery我的資料。

一開始找到TeskDisk聽說可以救分割表,但是,感覺好像是不行。

又找到FinalData/R-Studio,就用R-Studio來試的結果,可以耶~
資料完全救回來了~喔耶~

參考資料:
使用 TestDisk 來進行磁碟救援!
使用 SPFDisk 來進行磁碟救援!
刪除檔案復原 FinalData

2009年2月23日 星期一

[醫學] 電腦族每天必喝的四杯茶

面對電腦時間長了不好,那該怎麼辦?
其實每天四杯茶,不但可以對抗輻射的侵害,還可保護眼睛。

一、上午一杯綠茶:綠茶中含強效的抗氧化劑以及維生素C,不但可以清除體內的自由基,還能分泌出對抗緊張壓力的荷爾蒙。

綠茶中所含的少量咖啡因可以刺激中樞神經,振奮精神。

不過最好在白天飲用,以免影響睡眠。

二、下午一杯菊花茶:菊花有明目清肝的作用,有些人就乾脆用菊花加上枸杞一起泡來喝,或是在菊花茶中加入蜂蜜,都對解鬱有幫助。

三、疲勞了一杯枸杞茶:枸杞子含有豐富的β胡蘿蔔素、維生素B1、維生素C、鈣、鐵,具有補肝、益腎、明目的用。
其本身具有甜味,可以泡茶也可以像葡萄乾一樣作零食,對解決“電腦族”眼睛澀、疲勞都有功效。

四、晚間一杯決明茶: 決明子 有清熱、明目、補腦髓、鎮肝氣、益筋骨的作用。

參考資料:
[醫學] 電腦族每天必喝的四杯茶

2009年2月22日 星期日

設定QVFb

為了可以減少把在板子上的程式每一次寫好之後,傳到板子上執行。
有了QVFb的這一個程式可以模仿板子上的lcd,以便節省開發的時間。

要成功在QVFb要先依序安裝完
qt-x11-free-3.3.8
qt-embedded-free-3.3.8

1跟2是在同一個終端機中完成!!

1. 安裝qt-x11-free-3.3.8
1.1 下載qt-x11-free-3.3.8
1.2 改變/opt的權限
$ sudo chown ren:ren /opt
1.3 解壓縮qt-x11-free-3.3.8
$ tar -zxvf qt-x11-free-3.3.8.tar.gz -C /opt
1.4 設定環境變數
$ cd /opt
$ mv qt-x11-free-3.3.8 qtx
$ cd qtx
$ export QTDIR=/opt/qtx
$ export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
$ export PATH=$QTDIR/bin:$PATH

1.5 產生Makefile
$ ./configure -thread
1.6 編譯程式
$ make

2. 編譯qvfb
2.1 接上面的繼續下去,進入qvfb的資料夾
$ cd $QTDIR/tools/qvfb
2.2 編譯,會產生qvfb的可執行檔
$ make
2.3 為了以後方便,複製qvfb到QTDIR/bin中
$ cp qvfb $QTDIR/bin
2.4 執行qvfb
$ $QTDIR/bin/qvfb

重新開啟一個終端機
3. 安裝qt-embedded-free-3.3.8
3.1 下載qt-embedded-free-3.3.8
3.2 解壓縮到/opt中
$ tar -zxvf qt-embedded-free-3.3.8.tar.gz -C /opt
3.3 設定環境變數
$ cd /opt
$ mv qt-embedded-free-3.3.8 qte
$ cd qte
$ export QTDIR=/opt/qte
$ export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
$ export PATH=$QTDIR/bin:$PATH

3.4 把qtx產生出來的uic與moc執行檔copy到/opt/qte/bin中
$ cp /opt/qtx/bin/uic /opt/qte/bin
$ cp /opt/qtx/bin/moc /opt/qte/bin

3.5 產生Makefile
$ cd /opt/qte
$ ./configure –qvfb

3.6 編譯
$ make

在這一個步驟要開啟兩個終端機
4. 在qvfb上執行程式
第一個終端機
4.1 設定環境變數
$ export QTDIR=/opt/qtx
$ export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
$ export PATH=$QTDIR/bin:$PATH

4.2 執行qvfb
$ qvfb
第二個終端機
4.3 設定環境變數
$ export QTDIR=/opt/qte
$ export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
$ export PATH=$QTDIR/bin:$PATH

4.4 編譯examples
$ cd /opt/qte/examples/hello
$ qmake
$ make

4.5 執行hello
$ ./hello -qws
如此就可以看到hello出現在qvfb上啦


參考資料:
Qt/嵌入式的虛擬幀緩衝
Embedded QT 開發環境的建立
Qt/Embedded Virtual Framebuffer
Qt/Embedded 中文處理實戰
qt4.4-embedded在x86上的模擬運行及qvfb編譯 - 嵌入式 Linux - EZConnect-讓你的硬件和軟件連接更簡單!
安裝與建立 Qt 桌面開發運行環境
linux上qvfb的安裝及應用

透過yahoo輸入法設定嘸蝦米

參考資料:
yahoo輸入法設定裝嘸蝦米

2009年2月21日 星期六

建立壓縮檔的script

假設目錄下有100個檔案,要建立多個壓縮檔,
通常之前要一個目錄一個目錄產生壓縮檔。

在windows下有bat,而在linux下有script都可以幫我們完成以下的任務

[Linux下]
comic.sh

#/bin/bash

for sitenu in $(seq -f '%03g' 1 100)
do
zip -r $sitenu.zip $sitenu
done

如此一來可以幫我們壓縮001.zip;002.zip-...-100.zip

[Windows下]
應該要透過7-zip的指令模式,有空再研究吧~
在這之前,為了要讓7z指令在每一個目錄下均可以使用,必需把在PATH中加入7-zip的資料夾。
在「我的電腦」按名鍵,選內容-進階-環境變數-系統變數-中的PATH在後面用分號分隔,再加入7-zip的執行檔位置,這樣在任何一個地方均可以執行7-zip啦~
7z.exe的命令語法如下:

7z 命令 [選項] 壓縮檔名 要處理的檔名列
命令:有a,d,e,l,t,u, x等幾個命令

aAdd將檔名列中的檔案加入壓縮檔-i (Include)
-m (Method)
-p (Set Password)
-r (Recurse)
-sfx (create SFX)
-si (use StdIn)
-so (use StdOut)
-t (Type of archive)
-u (Update)
-v (Volumes)
-w (Working Dir)
-x (Exclude)
dDelete將指定檔名由壓縮檔內移除

-i (Include)
-m (Method)
-p (Set Password)
-r (Recurse)
-u (Update)
-w (Working Dir)
-x (Exclude)

eExtract將指定檔名由壓縮檔中擷取出來

-ai (Include archives)
-an (Disable parsing of archive_name)
-ao (Overwrite mode)
-ai (Exclude archives)
-i (Include)
-o (Set Output Directory)
-p (Set Password)
-r (Recurse)
-so (use StdOut)
-x (Exclude)
-y (Assume Yes on all queries)

lList顯示壓縮檔案內的檔案資訊

-ai (Include archives)
-an (Disable parsing of archive_name)
-ai (Exclude archives)
-i (Include)
-p (Set Password)
-r (Recurse)
-x (Exclude)

tTest, 測試壓縮檔的完整性

-ai (Include archives)
-an (Disable parsing of archive_name)
-ai (Exclude archives)
-i (Include)
-p (Set Password)
-r (Recurse)
-x (Exclude)

uUpdate, 用較新的同名檔案更新壓縮檔內較舊的檔案

-i (Include)
-m (Method)
-p (Set Password)
-r (Recurse)
-sfx (create SFX)
-si (use StdIn)
-so (use StdOut)
-t (Type of archive)
-u (Update)
-w (Working Dir)
-x (Exclude)

xeXtract with full paths以完整路徑的格式解出檔案

-ai (Include archives)
-an (Disable parsing of archive_name)
-ao (Overwrite mode)
-ai (Exclude archives)
-i (Include)
-o (Set Output Directory)
-p (Set Password)
-r (Recurse)
-so (use StdOut)
-x (Exclude)
-y (Assume Yes on all queries)



範例:

* 壓縮檔案:
$ 7z a -tzip archive.zip test1.txt test2.txt test3.txt
* 刪除檔案:
$ 7z d archive.zip *.bak
* 解壓縮到目前資料夾:
$ 7z e archive.zip
* 解壓縮所有的.cpp檔案案件到指定資料夾:
$ 7z e archive.zip -oc:\soft *.cpp
* 顯示壓縮檔內的資訊:
$ 7z l archive.zip
* 依壓縮檔內的檔案路徑解壓縮到指定資料夾:
$ 7z x archive.zip -oc:\soft *.cpp

更詳細的內容直接看到7-zip.chm即可。

7-Zip 4.65  Copyright (c) 1999-2009 Igor Pavlov  2009-02-03

Usage: 7z <command> [<switches>...] <archive_name> [<file_names>...]
[<@listfiles...>]

<Commands>
a: Add files to archive
b: Benchmark
d: Delete files from archive
e: Extract files from archive (without using directory names)
l: List contents of archive
t: Test integrity of archive
u: Update files to archive
x: eXtract files with full paths
<Switches>
-ai[r[-|0]]{@listfile|!wildcard}: Include archives
-ax[r[-|0]]{@listfile|!wildcard}: eXclude archives
-bd: Disable percentage indicator
-i[r[-|0]]{@listfile|!wildcard}: Include filenames
-m{Parameters}: set compression Method
-o{Directory}: set Output directory
-p{Password}: set Password
-r[-|0]: Recurse subdirectories
-scs{UTF-8 | WIN | DOS}: set charset for list files
-sfx[{name}]: Create SFX archive
-si[{name}]: read data from stdin
-slt: show technical information for l (List) command
-so: write data to stdout
-ssc[-]: set sensitive case mode
-ssw: compress shared files
-t{Type}: Set type of archive
-v{Size}[b|k|m|g]: Create volumes
-u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options
-w[{path}]: assign Work directory. Empty path means a temporary directory
-x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames
-y: assume Yes on all queries


[2009.08.05 補充]
若對指令不熟,可以直接到dos檔詢問,例如想要使用for指令,請使用以下指令
for /?

透過for壓縮1-69個資料夾到各別的zip檔案中
FOR /L %%a IN (1,1,69) DO 7z a "美味大挑戰 (%%a).zip" "美味大挑戰 (%%a)"

[2010.02.09 補充]
透過7z建立zip檔,並且排除eXclude這一個資料夾
% 7z a -tzip file.zip * -xr0!eXclude

參考資料:
[Tools] 7-Zip的命令列指令

2009年2月18日 星期三

在linux下執行ie

還沒有成功,不過,先把資料留下來吧!

參考資料:
ies4linux 和 wine 的字型設定
[Linux] IEs4Linux 2.99.0 安裝問題
簡單好用的 IE for Linux安裝軟體問世

OpenCV

example01
讀取圖片
main.c

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

int main()
{
char FileName[10]="rain.jpg";
IplImage *Image1 = cvLoadImage(FileName,1);
cvNamedWindow("Show Image",0);
cvResizeWindow("Show Image",300,400);
cvShowImage("Show Image",Image1);
cvWaitKey(0);
cvDestroyWindow("Show Image");
cvReleaseImage(&Image1);
}

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

example02
讀取webcam
main.c
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main()
{
CvCapture *capture;
IplImage *frame;
capture =cvCaptureFromCAM(0) ;
cvNamedWindow("Webcam",0);
while(1)
{
frame = cvQueryFrame(capture);
cvShowImage("Webcam",frame);
if(cvWaitKey(10)>=0)
{
break;
}
}
cvReleaseCapture(&capture);
cvDestroyWindow("Webcam");
}

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

參考資料:
OpenCV中文網站
HighGUI Reference Manual
opencv教學網頁
HighGUI參考手冊
Introduction to programming with OpenCV

其它資料:
cvGetRawData()的奇怪問題
ArtificialWistom: OpenCV
opencv編程入門4

2009年2月17日 星期二

c - 讀取系統的時間

讀取系統的時間

#include <stdio.h>
#include <string.h>
#include <time.h>

void main( void )
{
struct tm *newtime;
char am_pm[] = "AM";
time_t long_time;
time( &long_time ); /* Get time as long integer. */
newtime = localtime( &long_time ); /* Convert to local time. */

if( newtime->tm_hour > 12 ) /* Set up extension. */
strcpy( am_pm, "PM" );
if( newtime->tm_hour > 12 ) /* Convert from 24-hour */
newtime->tm_hour -= 12; /* to 12-hour clock. */
if( newtime->tm_hour == 0 ) /*Set hour to 12 if midnight. */
newtime->tm_hour = 12;
printf( "%.19s %s\n", asctime( newtime ), am_pm );
}


參考資料:
請問c語言有什麼函數可以讀取系統時間呢

2009年2月16日 星期一

c - fflush

int fflush(FILE *stream);

#include <stdio.h>

int main(int argc,char *argv[])
{
int i;
for (i=0;i<10;i++)
{
printf("%d",i);
// fflush(stdout); // 把註解刪掉看看
sleep(1);
}
return 0;
}


會把stdout的內容值直接輸出

當在用printf時,在判斷是否要送出去時,是以'\n'換行符號來表示。
若有換行符號的話,會馬上把printf內的資料清空,若沒有換行符號的話,則不會馬上把資料印在版面上。

c - Assert

有些時候,您預期程式中應該會處於何種狀態,例如某些情況下某個值必然是多少,這稱之為一種斷言(Assertion),斷言有兩種情況:成立或不成立。當預期結果與實際執行相同時,斷言成立,否則斷言失敗。

void assert (int expression);
expression如果為true,則什麼事都不會發生,如果為false,則會發生則會在stderr寫出錯誤訊息,且程序會立刻跳出

main.c

/* assert example */
#include <stdio.h>
#include <assert.h>

int main ()
{
FILE * datafile;
datafile=fopen ("file.dat","r");
assert (datafile);

fclose (datafile);

return 0;
}


另外, 若在程式執行前, 有定義NDEBUG的話, 就不會執行assert
在linux下就用以去指令去編譯
$ gcc main.c -DNDEBUG

錯誤訊息的格式會是像下面這樣
Assertion failed: expression, file filename, line line number

參考資料:
斷言(Assertion)
assert
assert - C++ Reference

c - select

在網絡程序中,一個進程同時處理多個文件描述符是很常見的情況。select()系統調用可以使進程檢測同時等待的多個I/O設備,當沒有設備準備好時,select()阻塞,其中任一設備準備好時,select()就返回。

select 呼叫及伴隨它所引發的巨集共用 fd_set. fd_set 則是一個位元陣列, 而其中每一個位元代表一個有效的檔案敘述結構. select 呼叫接受一個有效的檔案敘述結構並傳回 fd_set 位元陣列, 而該位元陣列中若有某一個位元為 1, 就表示相對映的檔案敘述結構的檔案發生了輸入, 輸出或有例外事件. 而這些巨集提供了所有處理 fd_set 的功能,而我們必需透過FD_ISSET()去判斷是哪一個fd產生變化

select()的調用形式為:
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout);

maxfd:表示所有的file descripter的最大值還要再加1
readfds:指定了被讀監控的file descripter set
writefds:指定了被寫監控的file descripter set
exceptfds:指定了被例外條件監控的file descripter set
timeout:時間到了之後,無論是否有資料進來,select()必需返回。
回傳值為所有readfds, writefds,exceptfds內的個數

參數timeout起了定時器的作用:到了指定的時間,無論是否有設備準備好,都返回調用。timeval的結構定義如下:

struct timeval{
long tv_sec; //表示幾秒
long tv_usec; //表示幾微妙
}

timeout取不同的值,該調用就表現不同的性質:
1.timeout為0,調用立即返回;
2.timeout為NULL,select()調用就阻塞,直到知道有file descripter就緒;
3.timeout為正整數,就是一般的定時器。

select調用返回時,除了那些已經就緒的描述符外,select將清除readfds、writefds和exceptfds中的所有沒有就緒的描述符。select的返回值有如下情況:
1.正常情況下返回就緒的文件描述符個數;
2.經過了timeout時長後仍無設備準備好,返回值為0;
3.如果select被某個信號中斷,它將返回-1並設置errno為EINTR。
4.如果出錯,返回-1並設置相應的errno。

假設執行如下程序後
fd_set readset;
FD_ZERO(&readset);
FD_SET(5, &readset);
FD_SET(33, &readset);

以下表示1組file set,表示fd=5與fd=32是在這一個file set中

再執行如下程序後:
FD_CLR(5, &readset);
則文件描述符集readset對應於文件描述符6的相應位被置為0,如圖2所示:


通常,操作系統通過巨集FD_SETSIZE來聲明在一個進程中select所能操作的文件描述符的最大數目。

系統提供了4個巨集對描述符集進行操作:
#include <sys/select.h>
#include <sys/time.h>
void FD_SET(int fd, fd_set *fdset); // 把fd這一file descripter加入fd set中
void FD_CLR(int fd, fd_set *fdset); // 把fd由fd set中除去
int FD_ISSET(int fd, fd_set *fdset); // 判斷fd是否在這一個fd set中
void FD_ZERO(fd_set *fdset); // 設定這一個fd set沒有含fd

主要參考資料:
Select()系統調用及文件描述符集fd_set的應用

其它參考資料:
等待來自多個訊號來源的輸入
fd_isset(3) - Linux man page
Socket編程中select()的妙用
Linux網絡編程--9. 服務器模型
特殊的 select 函式

C - malloc()、free()、calloc() 與 realloc()

void * malloc ( size_t size );
宣告記憶體空間為size大小的記憶體空間。
回傳為此空間的第一個記憶體位址

void free ( void * ptr );
用malloc或是calloc宣告空間的話,必需用free釋放記憶體空間。

void * calloc ( size_t num, size_t size );
取得記憶體大小為size,數量為num的空間
且內容值均為0
回傳值為第一個元素的記憶體空間

void * realloc ( void * ptr, size_t size );
重新分配記憶體空間,但是,回傳的記憶體空間的第一個位置不一定跟原先的位址相同。
且不必對ptr做free的動作了。

#include <stdlib.h>
void *memalign(size_t boundary, size_t size);
配置size大小的空間,回傳的起始位址(記憶體位址)必定是boundary的倍數,其中boundary必定是2的n次方

參考資料:
C Gossip: malloc()、free()、calloc() 與 realloc()
Linux / Unix Command: memalign

2009年2月15日 星期日

The Video4Linux2 API

參考資料:
The Video4Linux2 API
Video for Linux Two API Specification

VBI 概述

類比顯示器顯示一張畫面的方式:由畫面的左上角開始以交錯的方式最後掃瞄至畫面的右下角. 這樣就完成了一張畫面的顯示, 然後電子束移回去左上角. 以進行下一張畫面的顯示.
而電子束的移動是需要時間的, 所以在影像訊號上會有所謂的vertical blank interval(VBI).
在VBI的這段時間裡頭, 不會顯示影像, 影像訊號也不會被顯示器給刪除.
所以在處理影像訊號的時候, VBI很適合用來做資料傳輸, 因為空間還不小.
在VBI的時候, 原本是水平線資料的部份取代成要傳送的資料.
常利用VBI傳送資料的就是 closed caption service, 拿來做text subtitle用.

Raw data : 硬體接收到VBI data後只是把收到的data放一起, 這些資料就是raw data了
Sliced data: 有的硬體內含VBI的功能來解析VBI data. 比如說有內建可以將VBI raw轉成 closed caption character或data packet.

標準的解析VBI資料的硬體會支援Raw data與Sliced data兩個方式.
Sliced模式是比較好的選擇, 因為諸如data extraction, error correction等低階的動作均可透過硬體來做. Raw data通常用於非標準的VBI data.

如NTSC, VBI包含21條線, 1~9條保留給電視時間訊號使用. 10~21條可用來傳輸資料. 第21條廣泛地被使用於closed caption. 所以共有11條可用來傳輸資料.

每個VBI line可傳輸最多 288 bits.

參考資料:
VBI 概述

mmap 和 VMA

lseek - move the read/write file offset
off_t lseek(int fildes, off_t offset, int whence);
參考網址

由 user process 角度來說明的話,VMA 是 user process 裡一段 virtual address space 區塊;virtual address space 是連續的記憶體空間,當然 VMA 也會是連續的空間。VMA 對 Linux 的主要好處是,可以記憶體的使用更有效率,並且更容易管理 user process address space。

要在AP中直接設定裝置或者直接存取實體記憶體位址,
在作業系統的保護下,通常要透過ioctl或read/write方法。

但是對於大量資料進出,比如video或streaming這樣的方法就顯的效能很低,所以Linux提供了另外一套機制叫做mmap。
透過mmap可以把檔案映射到使用者虛擬位址空間,透過這個指標就可以存取檔案。
那檔案怎麼支援mmap呢?答案是要實做mmap這個方法,把上層的mmap請求,
轉換成實際的動作。

那怎麼利用mmap做實體記憶體的應用呢?
AP要利用/dev/mem這支檔案,它可以映射到實際的記憶體。
DRIVER端則要用ioremap把實體記憶體轉換成核心虛擬位址,之後就讀寫這個記憶體指標。

最後簡單圖解如下:
AP->開啟/dev/mem->mmap到實體記憶體位址->AP快樂的存取
DRIVER->module_init時做ioremap->取得記憶體指標->DRIVER快樂的存取

從另一個觀念來看,VMA 可以讓 Linux kernel 以 process 的角度來管理 virtual address space。Process 的 VMA 對映,可以由 /proc/<pid>/maps 檔案查詢

int open(const char *pathname, int flags, mode_t mode)
flags:當檔案打開時,可以做的動作write,read,execute
mode:當檔案建立時,可以對於owner,user,group的權限
參考網址

void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);
start指定記憶體位置,通常都是用NULL。start anywhere
offset指定檔案要在那裡開始對映,通常都是用0。
protections:權限:PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE
flags:MAP_FIXED,MAP_PRIVATE,MAP_SHARED,MAP_ANONYMOUS,MAP_DENYWRITE,MAP_GROWSDOWN
MAP_LOCKED

------------------------------------------------
munmap關閉記憶體對映。
int msync(const void *start, size_t length, int flags);
如果開啟記憶體對映是希望寫入檔案中,那麼修改過的記憶體會在一段時間內與檔案稍稍有點不同。如果您希望立即將資料寫入檔案中,可使用msync。

start為記憶體開始位置,length為長度。

flags則有三個:
MS_ASYNC : 請Kernel快將資料寫入。
MS_SYNC : 在msync結束返回前,將資料寫入。
MS_INVALIDATE : 讓核心自行決定是否寫入,僅在特殊狀況下使用。
網址

參考資料:
Linux 的 Virtual Memory Areas(VMA):基本概念介紹
實體記憶體映射技術:mmap ioremap
Linux 的 Virtual Memory Areas(VMA):基本概念介紹-2
小談 mmap() 與 VMA
Linux程式設計-13.記憶體對映mmap

libgphoto2

libgphoto2 is a library that can be used by applications to access various digital cameras

在linux下安裝usb webcam的驅動程式
主網頁

2009年2月14日 星期六

pkg-config

安裝GTK開發套件libgtk2.0-dev
$ sudo apt-get install libgtk2.0-dev

使用pkg-config查看一下GTK的相關編譯環境資訊:
$ pkg-config --cflags --libs gtk+-2.0

在預設的情況下,編譯器只會使用/lib和/usr/lib這兩個目錄下的library
pkg-config會讀取GTK附帶的.pc檔來取得相關編譯資訊,--cflags會列出include目錄,--libs列出所連結的函式庫及其所在目錄
*.pc通常是放在/usr/lib/pkgconfig/的目錄下
$ pkg-config --cflags --libs gtk+-2.0
-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pixman-1 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0


可以分開執行比較清楚,例如:
$ pkg-config --cflags gtk+-2.0
-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pixman-1
$ pkg-config --libs gtk+-2.0
-lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0


參考資料:
Ubuntu 下安裝 GTK
Library 編譯參數免煩惱~好用的 pkg-config!
pkg-config學習

No such file or directory SDL/SDL.h

請安裝套件
$ sudo apt-get install libsdl-image1.2-dev

c - ioctl

ioctl(io control)是應用程式用來和驅動程式溝通的API
讓應用程式可以對某個裝置下命令
你想要用ioctl做什麼事呢?

在unix環境中, 裝置的存取和檔案是一樣的
一般會先用open函式來取得對裝置的一個控制權
open會傳回一個handle值
一般用法 ioctl(handle, command, ...)
前面兩個參數是必須的, 後面的參數則視情況而定
handle就是open函式傳回來的值
command就是一個command code
command code每個值所代表的命令會因裝置而異
完全由驅動程式來解釋command code的意義
有的command code還需要傳進額外的參數時, 就會使用第3, 第4...個參數了

所以你要使用ioctl之前, 要先看你是要對那個裝置下命令
再去查那個裝置的驅動程式支援那些command code讓應用程式使用
應用程式呼叫 ioctl時, 相對應的驅動程式會有一個callback function被呼叫到
這個callback function專門用來處理 ioctl command code
你呼叫ioctl時可以傳那些command code, 還有要傳那些參數都和此callback有關


timepf=open("/dev/RTC",O_RDWR);
ioctl(timefd,1,&tm_time);
例子, 你要去查 rtc driver支援那些command code
如果你找不到現成的document介紹 rtc driver支援那些 ioctl command code
可以直接去查 linux rtc driver 的source code, 看 command code 1代表什麼


/usr/src/linux/drivers/char/rtc.c 是 rtc driver的code
我不確定你linux kernel 的source code path是否和我一樣
如果不一樣, 就搜尋一下 rtc.c
搜尋其中函式名稱有包含ioctl的函式, 就是rtc driver處理 ioctl的函式
我看到的函式名稱叫 rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
函式名稱可能會因linux kernel版本不同而異
參數 cmd 就是你傳進來的 command code, 你是傳 1 進來

參數 arg 就是另外一個參數, 就是你傳的 &m_time
你可以看看當你傳 command code = 1進來, 它做了那些事
你可以看到在函式裏面會把傳進來的cmd和一些常數比對
比如說, RTC_AIE_OFF, RTC_AIE_ON, RTC_PIE_OFF.....
一般會把command code在 .h檔定義成一些看得懂的常數

所以你要去查同一個目錄中的 rtc.h
裏面就可以發現 rtc driver到底支援了那些 command code
對照 .h定義的常數和涵式內對每個command code的處理
就可以知道有那些command code可以下, 該下怎樣的參數給 rtc driver
在此可以發現是RTC_AIE_ON定義成 1
函式裏面收到 RTC_AIE_ON的程式碼註解是Allow alarm interrupts.
意思是將時間的interrupt啟動
應該是你如果要使用time函式之前, 必須先將timer的interrupt啟動才有作用
在此可以發現另一個參數arg在cmd=RTC_AIE_ON並不會用到
只不過因為這個函式在cmd為其它值時會需要用到
所以函式在宣告時必須要宣告參數arg
你另外傳的那個參數 &tm_time在此時是沒有什麼作用的
你的呼叫式最好改成 ioctl(timefd, RTC_AIE_ON, &tm_time)會比較容易讓人看懂

===============================================================
錯誤號碼定義在/usr/include/asm-generic/errno-base.h

#define EPERM            1      /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

=================================================================
errno在每一個thread都會有一個數值,每一個thread並不會影響到其它thread的值。
一開始值會是0,只有當system call發生錯誤時,errno的值才會被更改。
透過perror()可以顯示錯誤訊息
errno變量問題
錯誤:UNIX 程序中的錯誤代碼


參考資料:
C/C 函式 ioctl
Linux 驅動程式的 I/O, #4: fops->ioctl 實作

安裝V4L2-1.0

Library for using Video For Linux 2 (V4L2) in combination with the Philip WebCam (PWC) driver.
就是webcam的函式庫

1. 下載V4L2.tar.gz主程式
2. 解壓縮
3. 建立Makefile
$ ./configure
出現以下錯誤:
checking for linux/videodev2.h... yes
checking pwc-ioctl.h usability... no
checking pwc-ioctl.h presence... no
checking for pwc-ioctl.h... no
configure: error: 'pwc-ioctl.h missing, please install the Philips WebCam library available here: http://www.saillard.org/linux/pwc/'

4. 下載pwc的library
下載到此V4L2目錄
5. 解壓縮,並且進入libpwc-20060101目錄,且編譯出執行檔
$ make
6. 到上一層目錄V4L2,重新產生Makefile,並且加入額外的header路徑
$ ./configure --with-parse-incdir=/home/ren/Desktop/V4L2-1.0/libpwc-20060101
7. 安裝到系統中
$ sudo make install

方法二:
與上面到第二個步驟都相同
3. 解壓縮pwc-10.0.12-rc1.tar.bz2
4. 建立Makefile
$ ./configure --with-parse-incdir=pwc-10.0.12-rc1
5. 編譯
$ make
6. 安裝
$ sudo make install

2009年2月13日 星期五

與webcam相關的程式碼

Camera Preview with V4l2

linux 下v4l2視頻採集的問題

libfg
主網頁

Qt Opencv webcam viewer
主網頁
$ sudo apt-get install libcv-dev libhighgui-dev

player-2.0.4.orig
主網頁

Simple Video Viewer
主網頁
出現找不到libv4lconvert.h的錯誤,請到此網站下載libv4l且安裝到系統中
同時必需安裝gtk+-2.0
$ sudo apt-get install libgtk2.0-dev
編譯
$ gcc -Wall svv.c -o svv $(pkg-config gtk+-2.0 --cflags --libs) -lv4lconvert

ubuntu-webcam
主網頁

Motion
主網頁

Webcam HOWTO
主網頁

在 Linux 使用 USB Webcam
主網頁

用 Linux 架設影像監視系統
主網頁

UVC
Linux UVC driver and tools
Linux UVC


不完整的程式碼:
在Linux上擷取Webcam影像
如何把視訊影像存入buff

參考的資料:
V4L2 API Specification
Ubuntu - Webcam

與capture.c相關的函數

int stat(const char *restrict path, struct stat *restrict buf);
stat - get file status
網址

char *strerror(int errnum);
strerror, strerror_r - get error message string
若上一個函數有出現錯誤,會把錯誤號碼存到erron,可以透過strerror來取得代表此錯誤數字的訊息
網址

function S_ISCHR(m: Word):Boolean;
Is file a character device
網址

struct stat
It provides detailed information about a file
網址

struct v4l2_capability
DRIVER CAPABILITIES
網址

struct v4l2_cropcap
網址

struct v4l2_crop
網址

VIDIOC_QUERYCAP
ioctl (fd, VIDIOC_QUERYCAP, &cap)
fd有何功能
網址

把M$下純文字檔轉成Unix下的純文字檔

在M$下在文字檔最後,會加入^M的特殊符號~
這個時候再linux下分析字串時,就有可能會因為這一個符號而造成結果有錯誤。

因此,tofrodos可以協助我們轉換:

1. 尋找軟體
$ apt-cache search tofrodos
2. 安裝軟體
$ sudo apt-get install tofrodos
3. 由M$轉換到Linux
$ dos2unix filename

參考資料:
Install unix2dos on Ubuntu

安裝IHU - I Hear You

之前學長留下來的MOD是架構在SCTP上,透過handover的機制,當其中一條斷線時,可以馬上切換到另外一條線路。
主要是當使用無線網路的時候,透過同時使用兩個線路的情況下,讓通話穩定度比較好~

而MOD是修改IHU (I hear you)而來的,所以,今天安裝IHU來試試看吧~

0. 需要有qt3與libogg-dev的套件
$ sudo apt-get install libogg-dev libqt3-mt-dev qt3-apps-dev qt3-assistant qt3-designer qt3-dev-tools qt3-doc qt3-examples qt3-qtconfig

1. 下載IHU原始檔
下載網址
$ wget http://jaist.dl.sourceforge.net/sourceforge/ihu/ihu-0.6.0.tar.gz

2. 解壓縮
$ tar -zxvf ihu-0.6.0.tar.gz

3. 產生Makefile,並且把安裝路徑設定在$HOME/ihu
$ cd ihu-0.6.0
$ ./configure --prefix=$HOME/ihu

4. 執行ihu
$ cd $HOME/ihu/bin
$ ./ihu

====================================
錯誤訊息:
因為我的qt環境是qt3與qt4共存的,因此,在configure時,會先找到Qt4的執行檔,所以,必需要把qt3的bin目錄擺在PATH的最前面。
$ export PATH=/usr/share/qt3/bin:$PATH

[2009.04.02 補充]
今天在ubuntu 8.04編譯IHU,出現很多套件沒有預設安裝,所以,必需要補安裝,把錯誤訊息列在下面,並且安裝的套件也列在裡面
checking for __gmpz_init in -lgmpxx... no
configure: error: GNU MP not found, download at http://swox.com/gmp

sudo apt-get install libgmp-ocaml-dev

checking for snd_pcm_writei in -lasound... no
configure: error: ALSA needed! Download at http://www.alsa-prject.org

sudo apt-get install libasound2-dev

checking for speex_encode in -lspeex... no
configure: error: Speex needed! Download at http://www.speex.org

sudo apt-get install libspeex-dev

checking for soundtouch/SoundTouch.h... no
configure: error: Soundtouch needed! Download at http://www.surina.net/soundtouch/

sudo apt-get install libsoundtouch-ocaml-dev


[2009.04.25 補充]
目前打算做出在sctp上,可以傳送語音、影像、文字的應用程式
影像的部分先在tcp上完成了,透過opencv來完成。
語音的部分,可能主要是要參考IHU來試試看,另外,原本IHU是透過GNU Autoconf 及 Automake 這兩個軟體來產生Makefile,也就是打./configure指令就會產生Makefile的過程,因為那太複雜了,還是用qmake來產生就好啦~

先進入src目錄。
以下面的指令產生src.pro檔案
$ qmake-qt3 -project
修改src.pro檔案
在INCLUDEPATH下面加入LIBS這一行
LIBS += -lasound -lgmpxx -lspeex -lSoundTouch -logg
然後再打以下指令
$ qmake-qt3
$ make

第一行是產生Makefile
第二行是編譯
在編譯的過程中,會產生一些錯誤,均是因為透過GNU Autoconf 及 Automake 成產生的變數,這個時候把它設定為字串或是把它刪除就好~
另外還有另一個除去錯誤的方法。
因為會出現錯誤,是因為若透過./configure會產生一個config.h
裡面有設定一些變數
當然要產生這一個檔案,就要先運行./configure
這個時候只要在Config.h這一個檔案,把#include "config.h"的上下個一行刪除,
基本上應該就可以正常運行啦~

getopt - getopt_long - 命令行參數的分析

在實際程序之中我們經常要對命令行參數進行分析. 比如我們有一個程序a可以接受許多參數.一個可能的情況是
a -d print --option1 hello --option2 world
那我們如何對這個命令的參數進行分析了?.經常用函數是getopt和getopt_long.
==============================================================
int getopt(int argc,char const **argv, const char *optstring);
==============================================================
int getopt_long(int argc,char const **argc, const char *optstring,const struct option *longopts, int *longindex);
==============================================================

這裡有一個getopt的範例程式
main.c

#include <stdio.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int ch; 
opterr = 0;
while((ch = getopt(argc,argv,"a:bcde"))!= -1) 
switch(ch)
{
case 'a':
printf("option a:'%s'\n",optarg);
break;
case 'b':
printf("option b :b\n");
break;
default:
printf("other option :%c\n",ch);
}
printf("optopt +%c\n",optopt);
}

執行方式:
$ ./getopt –b
option b:b
$ ./getopt –c
other option:c
$ ./getopt –a
other option :?
$ ./getopt –a12345
option a:'12345'


[2014/12/11 補充]
若參數後面要加數值的話,
則要加:

若不用另外加數值的話,則不需要加:

[2015/02/12 補充]
若想抓的參數是沒有接在-c這種後面的話,則可以使用optind
argv[optind]

而若有多個這種類型的參數的話,則可以使用迴圈
例如:
# ./a.out text.txt text2.txt

程式碼為:
for(; optind < argc; optind++)
{
  puts(argv[optind]);
}

參考資料:
命令行參數的分析
getopt(分析命令行參數)
C語言 getopt用法

2009年2月12日 星期四

編譯XawTV

這一個軟體主要是來擷取web camera的軟體,可以運行成功,但是,若自己編譯的話,還是有問題~
下載source檔
$ apt-get source xawtv

進入source資料夾後,建立Makefile
X include files are in /usr/include/X11/fonts
X library files are in /usr/lib/X11
並且,要install的路徑在$HOME/xxx下
$ ./configure --x-include=/usr/include/X11/fonts/ --x-libraries=/usr/lib/X11/ --prefix=$HOME/xxx

安裝編譯出來的檔案
$ make install

===============
錯誤訊息:
error: FSlib.h: No such file or directory

結果找到FSlib.h是存放在/usr/include/X11/fonts/目錄下,所以,把--x-include=/usr/include/X11/fonts/就可以了~

執行:
設定來源為/dev/video0且畫面大小為320x240
$ xawtv -c /dev/video0 -geometry 320x240

在xawtv中
v4l輸入
xlib輸出

2009年2月11日 星期三

CMake - 呼叫環境變數的方式

$ENV{NAME}指令就可以呼叫系統的環境變數了,例:
MESSAGE(STATUS “HOME dir: $ENV{HOME}”)

設置環境變量的方式是:
SET(ENV{變數名} 值)

CMAKE_INCLUDE_CURRENT_DIR
自動添加CMAKE_CURRENT_BINARY_DIR和CMAKE_CURRENT_SOURCE_DIR到當前處理的CMakeLists.txt

CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
將專案提供的header file目錄始終至於系統header file的目錄前面,避免與系統的發生衝突

CMAKE_INCLUDE_PATH
把路徑加入header file收尋路徑中,必需與FIND_PATH指令一起使用才會有效果
export CMAKE_INCLUDE_PATH=/usr/include/hello

CMAKE_LIBRARY_PATH
把路徑加入library收尋路徑中,必需與FIND_PATH指令一起使用才會有效果

BUILD_SHARED_LIBS
設不進行設置,則所有生成的library會是static
若SET(BUILD_SHARED_LIBS ON),默認生成的為動態函式庫

CMAKE_C_FLAGS
設置C編譯選項,也可以通過指令ADD_DEFINITIONS()添加

CMAKE_CXX_FLAGS
設置c++編譯選項,也可以通過指令ADD_DEFINITIONS()添加

CMake - 常用變數和常用環境變數

CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR
以上內容值都是一樣的,均表示專案的最上層目錄

CMAKE_CURRENT_SOURCE_DIR
是指當前處理的CMakeLists.txt所在的路徑

CMAKE_CURRRENT_BINARY_DIR
如果是in-source編譯,它跟CMAKE_CURRENT_SOURCE_DIR一致,如果是out-of-source編譯,它指的是target編譯目錄
使用ADD_SUBDIRECTORY(src bin)可以改變這個變量的值。
使用SET(EXECUTABLE_OUTPUT_PATH <新路徑>)並不會影響這個變量所造成影響,他僅僅修改了最終目標文件存放的路徑。

CMAKE_CURRENT_LIST_FILE
輸出呼叫這個變數的CMakeLists.txt的完整路徑

CMAKE_CURRENT_LIST_LINE
輸出這個變量所在的行

CMAKE_MODULE_PATH
這個變量用來定義自己的cmake模組所在的路徑。
為了讓cmake在處理CMakeLists.txt時找到這些模組,你需要通過SET指令,將自己的cmake模組路徑設置一下。例:
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
這個時候你就可以通過INCLUDE指令來調用自己的模組了

EXECUTABLE_OUTPUT_PATH
定義執行檔最終存放目錄

LIBRARY_OUTPUT_PATH
定義library最終存放目錄

PROJECT_NAME
傳回透過PROJECT所定義的項目名稱

Linux - ldd 指令

可以用來尋找此執行檔鏈接了哪一些函式庫

例如:
main.c

#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}


$ gcc main.c
$ ldd a.out
linux-gate.so.1 => (0xb7f0f000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dac000)
/lib/ld-linux.so.2 (0xb7f10000)

表示有用到以上三個函式庫

CMake - 使用外部library與header filer

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
這一個指令可以用來增加程式的搜索路徑,路徑之間用空白分割,若路徑包含空白,可用雙引號將它括起來。
把/usr/include/hello/加入收尋header file的路徑中
INCLUDE_DIRECTORIES(/usr/include/hello)

LINK_DIRECTORIES(directory1 directory2 ...)
添加非標準的library path

TARGET_LINK_LIBRARIES(target library1
<debug | optimized> library2
...)

這裡可以加入一個shared library
TARGET_LINK_LIBRARIES(main libhello.so)
也可以加入static library
TARGET_LINK_LIBRARIES(main libhello.a)

FIND_PATH用來指定路徑中搜索文件名
例:
FIND_PATH(myHeader NAMES hello.h PATHS /usr/include /usr/include/hello)

特殊的環境變數CMAKE_INCLUDE_PATH和CMAKE_LIBRARY_PATH
注意,這兩個是環境變數而不是cmake變數。
使用方法是要在bash中用export或者在csh中使用set命令設置或者CMAKE_INCLUDE_PATH=/home/include cmake

[2009.3.25 補充]
要在生成可執行檔時,要link一些library可以使用以下方法
例:
$ gcc main.c -lsctp
則在生成執行檔前,要加下面這一行
LINK_LIBRARIES(sctp)
只有對每一個target均需要使用到此library,才會使用到LINK_LIBRARIES
而且,LINK_LIBRARIES必需擺在ADD_EXECUTABLE指令之前。

若用TARGET_LINK_LIBRARIES取代的話,則TARGET_LINK_LIBRARIES必需擺在ADD_EXECUTABLE之後。
CMakeLists.txt
# Project Name
PROJECT(one-to-one)
# set source
SET(SRC_LIST clnt.c serv.c)

# add library,只有當對每一個target均需要此library,才使用LINK_LIBRARY,否則請使用TARGET_LINK_LIBRARY指令
# LINK_LIBRARIES(sctp)

# define the executable
ADD_EXECUTABLE(serv serv.c)
# add library for each target
TARGET_LINK_LIBRARIES(serv sctp)

#define the executable
ADD_EXECUTABLE(clnt clnt.c)
#add library for each target
TARGET_LINK_LIBRARIES(clnt sctp

CMake - 指令說明

指令:
PROJECT(projectname [CXX] [C] [Java])
設定這一個project的名稱,並且設定此project使用的語言
例:
此project名稱為HELLO
PROJECT (HELLO)

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
設定變數VAR的內容值
例:
設定${SRC_LIST}變數內容為main.c t1.c t2.c
SET(SRC_LIST main.c t1.c t2.c)

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"
...)
這個指令用於向終端輸出用戶定義的訊息,包含三種類型:
SEND_ERROR:產生錯誤,生成過程被跳過
SATUS:輸出等級為1的訊息
FATAL_ERROR:立即終止所有cmake過程

例:輸出PROJECT_SOURCE_DIR
MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR})

ADD_EXECUTABLE(exename [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
exename是指要產生出來的可執行檔,而[WIN32] [MACOSX_BUNDLE]分別在windows與mac才需要設定的,這裡不用理它。[EXCLUDE_FROM_ALL]是先把此目錄編譯排除在外,例如"examples資料夾",而source則是編譯出執行檔exename所需要的原始碼)
ADD_EXECUTABLE(hello main.c func.c)

ADD_EXECUTABLE(hello ${SRC_LIST})

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
這一個指令可以加入目前工程的子目錄,並且可以指定object與target存放的位置,而[EXCLUDE_FROM_ALL]是把此目錄在編譯過程排除在外。例如工程的examples目錄。可能是project完成後,再進入examples目錄單獨編譯
把src目錄加入工程,並且指定編譯輸出路徑為bin
ADD_SUBDIRECTORY(src bin)

INSTALL(TARGETS targets...
[[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION <dir>] [PERMISSIONS permissions...]
[CONFIGURATIONS
[Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL]
] [...])
INSTALL指令用於定義安裝規則,安裝的內容可以包括執行檔、shared library、static library、文件、目錄、腳本
可執行檔myrun安裝到${CMAKE_INSTALL_PREFIX}/bin目錄
shared library:libmylib安裝到${CMAKE_INSTALL_PREFIX}/lib目錄
static library:libmystaticlib安裝到${CMAKE_INSTALL_PREFIX}/libstatic目錄

INSTALL(TARGETS myrun mylib mystaticlib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION libstatic
)


普通文件的安裝:
INSTALL(FILES files... DESTINATION <dir>
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[RENAME <name>] [OPTIONAL])
如果若不設定權限PERMISSIONS,安裝後的權限為644權限。

非目標的可執行檔(例如腳本之類的)
INSTALL(PROGRAMS files... DESTINATION <dir>
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[RENAME <name>] [OPTIONAL])

跟上面的FILES指令使用方法一樣,唯一的不同是安裝後權限為755

目錄的安裝:
INSTALL(DIRECTORY dirs... DESTINATION <dir>
[FILE_PERMISSIONS permissions...]
[DIRECTORY_PERMISSIONS permissions...]
[USE_SOURCE_PERMISSIONS]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[[PATTERN <pattern> | REGEX <regex>]
[EXCLUDE] [PERMISSIONS permissions...]] [...])

DIRECTORY後面連接的是所在Source目錄的相對路徑,但務必注意:
abc和abc/有很大的區别。
如果目錄名不以/结尾,那麼這個目錄将被安裝為目標路徑下的abc,如果目錄名以/结尾,
代表将這個目錄中的内容安装到目標路徑,但不包括這個目錄本身。
PATTERN用於使用正規表示式進行過濾,PERMISSIONS用於指定PATTERN過濾後的文件

將icons目錄安裝到 /share/myproj,将scripts/中的内容安装到
/share/myproj
不包含目錄名為CVS的目录,對於scripts/*文件指定權限為 OWNER_EXECUTE
OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ.
INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
PATTERN "CVS" EXCLUDE
PATTERN "scripts/*"
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
GROUP_EXECUTE GROUP_READ)


$ cmake -DCMAKE_INSTALL_PREFIX=/usr ..
則會把安裝目錄設定在/usr下,但是,若沒有設定的話預設是/usr/local的目錄下

ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)

SHARED,動態函式庫
STATIC,靜態函式庫
MODULE,在使用dyld的系统有效,如果不支持dyld,则被當作SHARED對待。
EXCLUDE_FROM_ALL參數的意思是這個函式庫不會被默認建構,除非有其他的组件依賴或是手工建構。



變數:
PROJECT_BINARY_DIR
表示執行cmake的路徑
PROJECT_SOURCE_DIR
表示source的路徑,也就是主要的CMakeList.txt的位置
EXECUTABLE_OUTPUT_PATH
指定最終可執行檔存放的位置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
LIBRARY_OUTPUT_PATH
設定最終產生的shared library存放的位置
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

Makefile產生後,make所使用的參數:
DCMAKE_INSTALL_PREFIX
設定執行檔安裝的路徑
cmake -DCMAKE_INSTALL_PREFIX=/usr .

2009年2月10日 星期二

透過 Linux 恢復 Windows 系統管理員密碼

如果忘記了 Windows 的 administrator 密碼,可以透過 Linux 的 Live CD 進行恢復,而這裡會使用 Ubuntu 作為例子:

1. 使用 Ubuntu Live CD 開機
2. 安裝一個名為 “chntpw” 的程式
$ sudo apt-get install chntpw
3. 安裝 “chntpw” 後,便要將 Windows 的 NTFS 分割區掛載。
4. 進入 Windows 分割區下的 system32/config 目錄,然後輸入:
$ sudo chntpw SAM
5. 出現了一堆訊息後,系統會提示 reset 密碼,如果想設成空密碼,可以輸入星號 *,重新開機後便可以進入 Windows。

資料來源:
透過 Linux 恢復 Windows 系統管理員密碼

如何安裝GCC編譯器

目前,GCC可以用來編譯C/C++、FORTRAN、JAVA、OBJC、ADA等語言的程序,可根據需要選擇安裝支持的語言。本文以在Redhat Linux上安裝GCC4.1.2為例(因在項目開發過程中要求使用,沒有用最新的GCC版本),介紹GCC的安裝過程。

  安裝之前,系統中必須要有cc或者gcc等編譯器,並且是可用的,或者用環境變量CC指定系統上的編譯器。如果系統上沒有編譯器,不能安裝源 代碼形式的GCC 4.1.2。如果是這種情況,可以在網上找一個與你系統相適應的如RPM等二進制形式的GCC軟件包來安裝使用。本文介紹的是以源代碼形式提供的GCC軟 件包的安裝過程,軟件包本身和其安裝過程同樣適用於其它Linux和Unix系統。

  系統上原來的GCC編譯器可能是把gcc等命令文件、庫文件、頭文件等分別存放到系統中的不同目錄下的。與此不同,現在GCC建議我們將一個版 本的GCC安裝在一個單獨的目錄下。這樣做的好處是將來不需要它的時候可以方便地刪除整個目錄即可(因為GCC沒有uninstall功能);缺點是在安 裝完成後要做一些設置工作才能使編譯器工作正常。在本文中採用這個方案安裝GCC 4.1.2,並且在安裝完成後,仍然能夠使用原來低版本的GCC編譯器,即一個系統上可以同時存在並使用多個版本的GCC編譯器。

  按照本文提供的步驟和設置選項,即使以前沒有安裝過GCC,也可以在系統上安裝上一個可工作的新版本的GCC編譯器。

  1. 下載

  在GCC網站上(http://gcc.gnu.org)或者通過網上搜索可以查找到下載資源。目前GCC的最新版本為 4.2.1。可供下載的文件一般有兩種形式:gcc-4.1.2.tar.gz和gcc-4.1.2.tar.bz2,只是壓縮格式不一樣,內容完全一致,下載其中一種即可。

  2. 解壓縮

拷貝gcc-4.1.2.tar.bz2(我下載的壓縮文件)到/usr/local/src(根據自己喜好選擇)下,根據壓縮格式,選擇下面相應的一種方式解包(以下的「%」表示命令行提示符):

  % tar zxvf gcc-4.1.2.tar.gz
  或者
  % bzcat gcc-4.1.2.tar.bz2 | tar xvf -

  新生成的gcc-4.1.2這個目錄被稱為源目錄,用${srcdir}表示它。以後在出現${srcdir}的地方,應該用真實的路徑來替換它。用pwd命令可以查看當前路徑。

  在${srcdir}/INSTALL目錄下有詳細的GCC安裝說明,可用瀏覽器打開index.html閱讀。

  3. 建立目標目錄

  目標目錄(用${objdir}表示)是用來存放編譯結果的地方。GCC建議編譯後的文件不要放在源目錄${srcdir]中(雖然這樣做也可以),最好單獨存放在另外一個目錄中,而且不能是${srcdir}的子目錄。

  例如,可以這樣建立一個叫 /usr/local/gcc-4.1.2的目標目錄:

  % mkdir /usr/local/gcc-4.1.2
  % cd gcc-4.1.2

  以下的操作主要是在目標目錄 ${objdir} 下進行。

  4. 配置

  配置的目的是決定將GCC編譯器安裝到什麼地方(${destdir}),支持什麼語言以及指定其它一些選項等。其中,${destdir}不能與${objdir}或${srcdir}目錄相同。

  配置是通過執行${srcdir}下的configure來完成的。其命令格式為(記得用你的真實路徑替換${destdir}):

  % ${srcdir}/configure --prefix=${destdir} [其它選項]

  例如,如果想將GCC 4.1.2安裝到/usr/local/gcc-4.1.2目錄下,則${destdir}就表示這個路徑。

  在我的機器上,我是這樣配置的:

  % ../gcc-4.1.2/configure --prefix=/usr/local/gcc-4.1.2 --enable-threads=posix --disable-checking --enable--long-long --host=i386-redhat-linux --with-system-zlib --enable-languages=c,c++,java

  將GCC安裝在/usr/local/gcc-4.1.2目錄下,支持C/C++和JAVA語言,其它選項參見GCC提供的幫助說明。

  5. 編譯

  % make

  6. 安裝

  執行下面的命令將編譯好的庫文件等拷貝到${destdir}目錄中(根據你設定的路徑,可能需要管理員的權限):

  % make install

  至此,GCC 4.1.2安裝過程就完成了。

  6. 其它設置

  GCC 4.1.2的所有文件,包括命令文件(如gcc、g++)、庫文件等都在${destdir}目錄下分別存放,如命令文件放在bin目錄下、庫文件在 lib下、頭文件在include下等。由於命令文件和庫文件所在的目錄還沒有包含在相應的搜索路徑內,所以必須要作適當的設置之後編譯器才能順利地找到 並使用它們。

  6.1 gcc、g++、gcj的設置

  要想使用GCC 4.1.2的gcc等命令,簡單的方法就是把它的路徑${destdir}/bin放在環境變量PATH中。我不用這種方式,而是用符號連接的方式實現,這樣做的好處是我仍然可以使用系統上原來的舊版本的GCC編譯器。

  首先,查看原來的gcc所在的路徑:

  % which gcc

  在我的系統上,上述命令顯示:/usr/bin/gcc。因此,原來的gcc命令在/usr/bin目錄下。我們可以把GCC 4.1.2中的gcc、g++、gcj等命令在/usr/bin目錄下分別做一個符號連接:

  % cd /usr/bin
  % ln -s ${destdir}/bin/gcc gcc412
  % ln -s ${destdir}/bin/g++ g++412
  % ln -s ${destdir}/bin/gcj gcj412

  這樣,就可以分別使用gcc412、g++412、gcj412來調用GCC 4.1.2的gcc、g++、gcj完成對C、C++、JAVA程序的編譯了。同時,仍然能夠使用舊版本的GCC編譯器中的gcc、g++等命令。

  6.2 庫路徑的設置

  將${destdir}/lib路徑添加到環境變量LD_LIBRARY_PATH中,例如,如果GCC 4.1.2安裝在/usr/local/gcc-4.1.2目錄下,在RH Linux下可以直接在命令行上執行
% export LD_LIBRARY_PATH=/usr/local/gcc-4.1.2/lib

最好添加到系統的配置文件中,這樣就不必要每次都設置這個環境變量了,在文件$HOME/.bash_profile中添加下面兩句:
LD_LIBRARY_PATH=/usr/local/gcc-4.1.2/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

重啟系統設置生效,或者執行命令
% source $HOME/.bash_profile

  7. 測試

  用新的編譯命令(gcc412、g++412等)編譯你以前的C、C++程序,檢驗新安裝的GCC編譯器是否能正常工作。



參考資料:
如何安裝GCC編譯器

自動產生Makefile - CMake

在尋找autotools的文章當中,發現,有一個新的東西CMake,聽說比automake好用。
那就研究一下吧~

實驗一:單一程式檔的 Hello World:
先來個第一步吧~hello world!!
建立CMake/hello/
下面有兩個檔案:CMakeLists.txt與hello.c

ren@notebook:~/Desktop$ tree CMake
CMake
|-- hello
| |-- CMakeLists.txt
| `-- hello.c

hello.c
#include <stdio.h>
int main(){
printf("Hello World!\n");
return 0;
}

CMakeLists.txt
# Project name
PROJECT (HELLO)
# set the variable HELLO_SRCS to be "hello.c"
SET (HELLO_SRCS hello.c)
# helloDemo executable built from hello.c
ADD_EXECUTABLE (hello ${HELLO_SRCS})

$ cmake .
$ make VERBOSE=1


實驗二:把 Hello World 變成函式庫
實驗三:試試使用外部函式庫 libpng 的情況
實驗四:換試試寫個簡單的 Qt4 程式
請參考這裡

小技巧
哇!在產生Makefile的過程中,會產生一堆檔案,因為要透過svn上資料到server的話,沒有把這一些資料刪除,會很占空間的,這個時候out-source building就派上用場啦~
在剛剛的hello資料夾下產生一個build/的資料夾
$ mkdir build
$ cd build
$ cmake ..
$ make

這個時候產生的檔案都會在build/的資料夾下喔~要刪掉直接刪它就好啦~

用CMake編出來的Makefile在編譯時,不會出現詳細的編譯過程,原來加上VERBOSE=1就可以啦
$ make VERBOSE=1

CMakeLists.txt的內容說明
# Project name
PROJECT(HELLO)
# Source code subdirectories
SUBDIRS(src test)
# Create a library from the hello.cxx file
ADD_LIBRARY(Hello hello.c)
# Location of library include files
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/src)
# Library location for the linker
LINK_DIRECTORIES(${HELLO_BINARY_DIR}/src)
# helloDemo executable built from demo.c
ADD_EXECUTABLE(helloDemo demo.c)
# Link the executable to the Hello library.
TARGET_LINK_LIBRARIES(helloDemo Hello)


參考資料:
把玩 CMake 的第一步
CMake
貓也會的 CMake
CMake實踐
Jserv「貓也會的 CMake」簡報投影片
在 linux 下使用 CMake 構建應用程序

2009年2月8日 星期日

implicit declaration of function

用gcc編譯c程序的時候 經常會出現
implicit declaration of function '...' 的warning

偶經過這幾天的經驗,發現主要有2種情況會產生這種warning

1 沒有把函數所在的c文件生成.o目標文件
2 在函數所在的c文件中定義了,但是沒有在與之相關聯的.h文件中聲明

恩 差不多了

參考資料:
關於 implicit declaration of function 一點經驗之談

在Linux下使用web camera的軟體

xawtv - television viewer - X11 application
可以在Ubuntu下使用web camera,不過,放大視窗這一個程式就會當掉

相關資料

驅動程式
SPCA5xx webcams Linux driver(支援多種 webcam, 包含 spcagui 等小工具)
Linux-USB device overview

應用軟體
FSF: Free Software Search Results
Mercury
Motion
xawtv

相關文獻
繁體中文:
Linux Center: 如何在 Linux 上使用 WebCam (Webcam HOWTO 2.1 ~ 2.3.3 中譯)
Linux NetMag: GnomeMeeting
Jollen 網路學院: Linux 的應用 -- Video Streaming
在 Linux 使用 USB Webcam
在 Linux 下安裝 USB Camera 的心得分享
Linux 的應用 -- Video Streaming 探討
其他語言:
The Webcam HOWTO
Piloter une webcam (法文... 看圖說故事 :)

2009年2月7日 星期六

Unix Network Programming - compiler error

先去網站下載原始碼
下載點

那就看著README來做吧~

ren@notebook:~/Desktop/Unix_network_programming/unpv12e/lib$ make
gcc -g -O2 -D_REENTRANT -Wall -c -o connect_nonb.o connect_nonb.c
In file included from connect_nonb.c:1:
unp.h:114: error: redefinition of 'struct in_pktinfo'
make: *** [connect_nonb.o] Error 1

解決方法:
把unp.h第114以下共四行註解掉

ren@notebook:~/Desktop/Unix_network_programming/unpv12e/libgai$ make
gcc -g -O2 -D_REENTRANT -Wall -c -o getaddrinfo.o getaddrinfo.c
gcc -g -O2 -D_REENTRANT -Wall -c -o getnameinfo.o getnameinfo.c
getnameinfo.c:8: error: conflicting types for 'getnameinfo'
/usr/include/netdb.h:649: error: previous declaration of 'getnameinfo' was here
make: *** [getnameinfo.o] Error 1

解決方法:
把/usr/include/netdb.h的第649行暫時註解掉

【轉貼】自動產生Makefile - autoconf & automake

在 Unix 上寫程式的人大概都碰過 Makefile,尤其是用 C 來開發程式的人。用 make來開發和編譯程式的確很方便,可是要寫出一個 Makefile就不簡單了。偏偏介紹 Makefile 的文件不多,GNU Make 那份印出來要幾百頁的文件,光看完 Overview 就快陣亡了,難怪許多人聞 Unix 色變。

本文將介紹如何利用 GNU Autoconf 及 Automake 這兩套軟體來協助我們『自動』產生 Makefile 檔,並且讓開發出來的軟體可以像 Apache, MySQL 和常見的 GNU 軟體一樣,只要會 ``./configure'', ``make'', ``make install'' 就可以把程式安裝到系統中。如果您有心開發 Open Source 的軟體,或只是想在 Unix 系統下寫寫程式。希望這份介紹文件能幫助您輕鬆地進入 Unix Programming 的殿堂。

1. 簡介

Makefile 基本上就是『目標』(target), 『關連』(dependencies) 和『動作』三者所組成的一連串規則。而 make 就會根據 Makefile 的規則來決定如何編譯 (compile) 和連結 (link) 程式。實際上,make 可做的不只是編譯和連結程式,例如 FreeBSD 的 port collection 中, Makefile 還可以做到自動下載原始程式套件,解壓縮 (extract) ,修補 (patch),設定,然後編譯,安裝至系統中。

Makefile 基本構造雖然簡單,但是妥善運用這些規則就也可以變出許多不同的花招。卻也因此,許多剛開始學習寫 Makefile 時會感到沒有規範可循,每個人寫出來的 Makefile 長得都不太一樣,不知道從何下手,而且常常會受限於自己的開發環境,只要環境變數不同或路

徑改一下,可能Makefile 就得跟著修改。雖然有 GNU Makefile Conventions (GNU Makefile 慣例) 訂出一些使用 GNU 程式設計時撰寫 Makefile 的一些標準和規範,但是內容很長而且很複雜, 並且經常做些調整,為了減輕程式設計師維護 Makefile 的負擔,因此有了Automake。

程式設計師只需寫一些預先定義好的巨集 (macro),交給 Automake 處理後會產生一個可供Autoconf 使用的 Makefile.in 檔。再配合利用Autoconf 產生的自動設定檔configure即可產生一份符合 GNU Makefile慣例的 Makeifle 了。

2. 上路之前

在開始試著用 Automake 之前,請先確認你的系統已經安裝以下的軟體:

1. GNU Automake

2. GNU Autoconf

3. GNU m4

4. perl

5. GNU Libtool (如果你需要產生 shared library)

我會建議你最好也使用 GNU C/C++ 編譯器 、GNU Make 以及其它 GNU 的工具程式來做為開發的環境,這些工具都是屬於 Open Source Software不僅免費而且功能強大。如果你是使用Red Hat Linux 可以找到所有上述軟體的 rpm 檔,FreeBSD 也有現成的 package 可以直接安裝,或著你也可以自行下載這些軟體的原始檔回來 DIY。以下的範例是在 Red Hat Linux 5.2 + CLE2 的環境下所完成的。

3. 一個簡單的例子



Automake 所產生的 Makefile 除了可以做到程式的編譯和連結,也已經把如何產生程式文件(如 manual page, info 檔及 dvi 檔) 的動作,還有把原始程式包裝起來以供散 的動作都考慮進去了,所以原始程式所存放的目錄架構最好符合 GNU 的標準慣例,接下來我拿hello.c 來做為例子。

在工作目錄下建立一個新的子目錄 ``devel'',再在 devel 下建立一個``hello'' 的子目錄,這個目錄將作為我們存放 hello 這個程式及其相關檔案的地方:

% mkdir devel

% cd devel

% mkdir hello

% cd hello


用編輯器寫個 hello.c 檔,

#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello, GNU!");
return 0;
}

接下來就要用 Autoconf 及 Automake 來幫我們產生 Makefile 檔了,

1. 用 autoscan 產生一個 configure.in 的雛型,執行 autoscan 後會產生一個configure.scan 的檔案,我們可以用它做為configure.in檔的藍本。

% autoscan

% ls

configure.scan hello.c


2. 編輯 configure.scan 檔,如下所示,並且把它的檔名改成configure.in

dnl Process this file with autoconf to produce a con figure script.

AC_INIT(hello.c)

AM_INIT_AUTOMAKE(hello, 1.0)

dnl Checks for programs.

AC_PROG_CC

dnl Checks for libraries.

dnl Checks for header files.

dnl Checks for typedefs, structures, and compiler ch aracteristics.

dnl Checks for library functions.

AC_OUTPUT(Makefile)


3. 執行 aclocal 和 autoconf ,分別會產生 aclocal.m4 及 configure 兩個檔案

% aclocal

% autoconf

% ls

aclocal.m4 configure configure.in hello.c



4. 編輯 Makefile.am 檔,內容如下

AUTOMAKE_OPTIONS= foreign

bin_PROGRAMS= hello

hello_SOURCES= hello.c


5. 執行 automake --add-missing ,Automake 會根據 Makefile.am 檔產生一些檔案,包含最重要的 Makefile.in

% automake --add-missing

automake: configure.in: installing `./install-sh'

automake: configure.in: installing `./mkinstalldirs'

automake: configure.in: installing `./missing'


6. 最後執行 ./configure ,

% ./configure

creating cache ./config.cache

checking for a BSD compatible install... /usr/bin/in stall -c

checking whether build environment is sane... yes

checking whether make sets ${MAKE}... yes

checking for working aclocal... found

checking for working autoconf... found

checking for working automake... found

checking for working autoheader... found

checking for working makeinfo... found

checking for gcc... gcc

checking whether the C compiler (gcc ) works... yes

checking whether the C compiler (gcc ) is a cross-co mpiler... no

checking whether we are using GNU C... yes

checking whether gcc accepts -g... yes

updating cache ./config.cache

creating ./config.status

creating Makefile



現在你的目錄下已經產生了一個 Makefile 檔,下個 ``make'' 指令就可以開始編譯 hello.c 成執行檔,執行 ./hello 和 GNU 打聲招呼吧!

% make

gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c he llo.c

gcc -g -O2 -o hello hello.o

% ./hello

Hello! GNU!



你還可以試試 ``make clean'',''make install'',''make dist'' 看看會有什麼結果。你也可以把產生出來的 Makefile 秀給你的老闆,讓他從此對你刮目相看 :-)

4. 一探究竟



上述產生 Makefile 的過程和以往自行編寫的方式非常不一樣,捨棄傳統自行定義 make 的規則,使用 Automake 只需用到一些已經定義好的巨集即可。我們把巨集及目標 (target)寫在 Makefile.am 檔內,Automake讀入 Makefile.am 檔後會把這一串已經定義好的巨集展

開並且產生對應的Makefile.in 檔, 然後再由 configure 這個 shell script 根據Makefile.in 產生適合的 Makefile。

在此範例中可藉由 Autoconf 及 Automake 工具所產生的檔案有 configure.scan、aclocal.m4、configure、Makefile.in,需要我們加入設定者為 configure.in 及 Makefile.am。

4.1 編輯 configure.in 檔

Autoconf 是用來產生 'configure' 檔的工具。'configure' 是一個shell script,它可以自動設定原始程式以符合各種不同平台上 Unix 系統的特性,並且根據系統三數及環境產生合適的 Makefile 檔或是C 的標頭檔 (header file),讓原始程式可以很方便地在這些不同的平台上被編譯出來。Autoconf 會讀取 configure.in 檔然後產生 'configure' 這個shell script。

configure.in 檔的內容是一連串 GNU m4 的巨集,這些巨集經過autoconf 處理後會變成檢查系統特徵的 shell script。configure.in 內巨集的順序並沒有特別的規定,但是每一個 configure.in 檔必須在所有巨集前加入 AC_INIT 巨集,然後在所有巨集的最後面加上 AC_OUTPUT 巨集。我們可先用 autoscan 掃瞄原始檔以產生一個 configure.scan 檔,再對 configure.scan 做些修改成 configure.in 檔。在範例中所用到的巨集如下:

dnl

這個巨集後面的字不會被處理,可視為註解。

AC_INIT(FILE)

這個巨集用來檢查原始碼所在的路徑,autoscan 會自動產生,我們不必修改它。

AM_INIT_AUTOMAKE(PACKAGE,VERSION)

這是使用 Automake 所必備的巨集,PACKAGE 是我們所要產生軟體套件的名稱,VERSION 是版本編號。

AC_PROG_CC

檢查系統可用的 C 編譯器,如果原始程式是用 C 寫的就需要這個巨集。

AC_OUTPUT(FILE)

設定 configure 所要產生的檔案,如果是 Makefile 的話,configure 便會把它檢查出來的結果帶入 Makefile.in 檔然後產生合適的 Makefile。

實際上,我們使用 Automake 時,還須要一些其它的巨集,這些額外的巨集我們用 aclocal來幫我們產生。執行 aclocal 會產生 aclocal.m4檔,如果沒有特別的用途,我們可以不必修改它,用 aclocal 所產生的巨集會告訴 Automake 怎麼做。

有了 configure.in 及 aclocal.m4 兩個檔案後,便可以執行 autoconf來產生 configure檔了。

4.2 編輯 Makefile.am 檔



接下來我們要編輯 Makefile.am 檔,Automake 會根據 configure.in 中的巨集把Makefile.am 轉成 Makefile.in 檔。Makefile.am 檔定義我們所要產的目標:

AUTOMAKE_OPTIONS

設定 automake 的選項。Automake 主要是幫助開發 GNU 軟體的人員維護軟體套件,所以在執行 automake 時,會檢查目錄下是否存在標準 GNU 軟體套件中應具備的文件檔案,例如 'NEWS'、'AUTHOR'、'ChangeLog' 等文件檔。設成 foreign 時,automake 會改用一般軟體套件的標準來檢查。

bin_PROGRAMS

定義我們所要產生的執行檔檔名。如果要產生多個執行檔,每個檔名用空白字元隔開。

hello_SOURCES

定義 'hello' 這個執行檔所需要的原始檔。如果 'hello' 這個程式是由多個原始檔所產生,必須把它所用到的原始檔都列出來,以空白字元隔開。假設 'hello' 這個程式需要 'hello.c'、'main.c'、

'hello.h'

三個檔案的話,則定義

hello_SOURCES= hello.c main.c hello.h

如果我們定義多個執行檔,則對每個執行檔都要定義相對的filename_SOURCES。

編輯好 Makefile.am 檔,就可以用 automake --add-missing 來產生Makefile.in。加上 --add-missing 選項是告訴 automake 順便幫我們加入包裝一個軟體套件所必備的檔案。Automake 產生出來的 Makefile.in檔是完全符合 GNU Makefile 的慣例,我們只要執行 configure 這個shell script 便可以產生合適的 Makefile 檔了。

4.3 使用 Makefile

利用 configure 所產生的 Makefile 檔有幾個預設的目標可供使用,我們只拿其中幾個簡述如下:

make all

產生我們設定的目標,即此範例中的執行檔。只打 make 也可以,此時會開始編譯原始碼,然後連結,並且產生執行檔。

make clean

清除之前所編譯的執行檔及目的檔 (object file, *.o)。

make distclean

除了清除執行檔和目的檔外,也把 configure 所產生的 Makefile也清除掉。

make install

將程式安裝至系統中。如果原始碼編譯無誤,且執行結果正確,便可以把程式安裝至系統預設的執行檔存放路徑。如果我們用bin_PROGRAMS 巨集的話,程式會被安裝至 /usr/local/bin 這個目錄。

make dist

將程式和相關的檔案包裝成一個壓縮檔以供散播 (distribution) 。執行完在目錄下會產生一個以 PACKAGE-VERSION.tar.gz 為名稱的檔案。PACKAGE 和 VERSION 這兩個變數是根據 configure.in 檔中AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定義。在此範例中會產生

'hello-1.0.tar.gz' 的檔案。

make distcheck

和 make dist 類似,但是加入檢查包裝後的壓縮檔是否正常。這個目標除了把程式和相關檔案包裝成 tar.gz 檔外,還會自動把這個壓

縮檔解開,執行 configure,並且進行 make all 的動作,確認編譯無誤後,會顯示這個 tar.gz 檔已經準備好可供散播了。這個檢查非常有用,檢查過關的套件,基本上可以給任何一個具備 GNU 發展境的人去重新編譯。就 hello-1.tar.gz 這個範例而言,除了在 Red

Hat Linux 上,在 FreeBSD 2.2.x 版也可以正確地重新編譯。

要注意的是,利用 Autoconf 及 Automake 所產生出來的軟體套件是可以在沒有安裝 Autoconf 及 Automake 的環境上使用的,因為 configure 是一個 shell script,它己被設計可以在一般 Unix 的 sh 這個 shell 下執行。但是如果要修改 configure.in 及 Makefile.a

m 檔再產生新的configure 及 Makefile.in 檔時就一定要有 Autoconf 及 Automake 了。

5. 相關訊息



Autoconf 和 Automake 功能十分強大,你可以從它們所附的 info 檔找到詳細的用法。你也可以從許多現存的 GNU 軟體或 Open Source 軟體中找到相關的 configure.in 或 Makefile.am 檔,它們是學習 Autoconf 及Automake 更多技巧的最佳範例。

這篇簡介只用到了 Autoconf 及 Automake 的皮毛罷了,如果你有心加入Open Source 軟體開發的行列,希望這篇文件能幫助你對產生 Makefile有個簡單的依據。其它有關開發 GNU程式或 C 程式設計及 Makefile 的詳細運用及技巧,我建議你從 GNU Coding Standards3(GNU 編碼標準規定) 讀起,裡面包含了 GNU Makefile 慣例,還有發展 GNU 軟體套件的標準程序和慣例。這些 GNU 軟體的線上說明文件可以在http://www.gnu.org/ 這個網站上找到。

6. 結語



經由 Autoconf 及 Automake 的輔助,產生一個 Makefile 似乎不再像以前那麼困難了,而使用 Autoconf 也使得我們在不同平台上或各家 Unix之間散播及編譯程式變得簡單,這對於在 Unix 系統上開發程式的人員來說減輕了許多負擔。妥善運用這些 GNU 的工具軟體,可

以幫助我們更容易去發展程式,而且更容易維護原始程式碼。

一九九八年是 Open Source 運動風起雲湧的一年,許多 Open Source 的軟體普遍受到網路上大眾的歡迎和使用。感謝所有為 Open Source 奉獻的人們,也希望藉由本文能吸引更多的人加入『自由』、『開放』的 OpenSource 行列。

About this document ...

輕輕鬆鬆產生 Makefile1

This document was generated using the LaTeX2HTML translator Version 98.2 beta6 (August 14th, 1998) Copyright (C) 1993, 1994, 1995, 1996, Nikos Drakos, ComputerBased Learning Unit, University of Leeds.Copyright (C) 1997, 1998, Ross Moore, Mathematics Department,Macquarie University, Sydney.

The command line arguments were:

latex2html -split 0 -show_section_numbers automake.tex

The translation was initiated by on 1999-02-11

Footnotes

... itle1

本文件使用 ChiLaTeX 製作。

... CLE2

CLE (Chinese Linux Extension,Linux 中文延伸套件),

http://cle.linux.org.tw/

... Standards3

GNU Coding Standards, Richard Stallman.

藍森林 http://www.lslnet.com 2001年3月22日 08:44

作 者: 許明彥



參考資料:
【轉貼】makefile
CVS, Automake與Autoconf簡介
Linux系統下Autoconf/AutoMake學習筆記
利用 Autotools 來建立 Makefile 檔案
CVS和automake
automake
Using Automake and Autoconf

GVimPortable

有些人在windows下要編輯一下程式碼,用「記事本」實在太陽春了,
寫程式當然不會用office之類的大型軟體,
當然還有其它很好的程式編輯軟體,
但是,今天要介紹的是GVimPortable。

在Unix-Like下,我想大家都應該知道一個非常好用的編輯軟體vi/vim
檔案雖然不大,但是功能確非常完整。
尤其要透過遠端修改程式碼時,更是常用的一個工具。

GVim主頁面

有「安裝檔」與「免安裝檔」
而我當然是用「免安裝檔啦」

在vim可以設定許多功能開啟,
而在GVimPortable則是要修改
GVimPortable\Data\settings\vimrc
使得當開啟GVim時,會載入你的設定值
以下是我vimrc的內容

GVimPortable\Data\settings\vimrc
:set nu
:set hlsearch
:set showmode
:set ruler
:syntax on
:set backspace=2
:set autoindent
:set tabstop=8

相關一些功能也可以參考這裡

其實在GVIM本來就有設定一些特效,若是透過上面設定參數,每一次開啟檔案,在畫面的最下面會出現一些資料,很礙眼,而且會取代原本GVIM的設定。
現在發現一個新的地方
GVimPortable\App\DefaultData\settings\vimrc
可以直接對它修改,如此一來可以保留GVIM的一些蠻好的設定,自己又可以增加一些自己想要的設定。
另外,在這一個檔案設定的指令前面不需要加分號,例
:set no
只要打
set no
就好

另外一個問題,就是在GVIM打開在linux下完成的檔案,會出現亂碼,只要在上面所說的這一個檔案增加一下內容就可以顯示正常啦~

set fileencodings=ucs-bom,utf-8,gbk,big5,latin1
set encoding=utf-8
set termencoding=utf-8
set fileencoding=utf-8


[2009/10/14 補充]
最近因為工作的關係,需要在windows下編輯程式,之前都在Linux使用vim來寫程式,實在非常好用!因為,現在整理一下,在windows下的GVim的設定值是如何設定的
GVimPortable\Data\settings\vimrc
不在在gvim7.2的設定檔位置在GVimPortable\Data\settings\_vimrc
" 用雙引號當作註解

" 設定背景為藍色
" 設定檔放在$VIM$/vimfiles/colors/
colorscheme darkblue

" 設定在insert mode可以使用backspace
set nocompatible

" 設定在換行時,設定自動縮排
set autoindent

" 設定可以使用backspace移到上一行
set backspace=2

" 設定顯示行數
set nu

" 右下角顯示目前指標的訊息與目前的模式
set ruler

" 依特殊副檔名,顯示相對應的格式
syntax on

" 顯示所有符合要search的keyword
set hlsearch

" 設定每按一個tab鍵,會移動兩個空白鍵的距離
set tabstop=2

" 把tab鍵轉換成相對應的空白鍵
" 如果真的要打 Tab: ctrl + v + [tab]
set expandtab

" 設定字型為Consolas且字型大小為14
set gfn=Consolas:h14

" 不自動存檔
set nobackup

" 自動找對應括號
set showmatch

" 在normal mode按 >> 的跳的格數
set shiftwidth=2

" 設定數字與的左邊邊距
set numberwidth=4

" 設定記錄指令50筆
set history=50

" display incomplete commands
set showcmd

" 設定開啟ctags視窗
" nnoremap :TlistToggle

" 讓當前沒有被編輯的文件自動摺疊起來
let Tlist_File_Fold_Auto_Close=1

" 寫 C 時很好用,indent 比一般敏感,專為 C 程式碼而設。預設 off。編輯 C/C++ code 時會自動打開
" set cindent

" 狀態列的行數,預設一行,建議設成兩行。
set cmdheight=2

" 這是防止在做剪貼時位置會不正確
set paste

" 設定tabt頁面的最大值
set tabpagemax=30

" 可以讀取Unicode的檔案,且不會產生亂碼的選單
set encoding=utf-8
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim

" 這也可以算是一種模式,list mode。就是 Tab 的地方會以 ^I 顯示,而行尾之 EOL 會顯示成 $。可以讓您清楚的知道 Tab 在哪裡,換行是不是真的。
" set list

" search英文字不要分大小寫
" set ignorecase

" 設定檔案為C格式,特特殊字元會highlight
" set ft=c

" 設定編輯為Unix的檔案格式
" set ff=unix

" 設定超出行,仍不要自動換行
" set nowrap

" 加入tabnew, tabprevious, tabnext的快速鍵
nmap <C-t> :tabnew<CR>
nmap <C-Left> :tabprev<CR>
nmap <C-Right> :tabnext<CR>

" 只留下路徑上的檔案名稱
nmap <F4> :%s/.*\\\(.\+\)$/\1/g<CR>

" 移除每一行最後多餘的空白
nmap <F6> :%s/ \+$//gc<CR>

" 加入多個要search的關鍵字
nmap sa :exec "/" . getreg ('/') . "\\\\|" . "\\<" . expand("") . "\\>"<CR>

" 在目前的游標位置加入目前的日期與時間
nmap <C-n> "=strftime ("%Y.%m.%d-%H.%M.%S")<C-M>p


另外,要在windows下用GVim來search多個檔案的內容的話,請參照
Grep search tools integration with Vim
同時也可以安裝windows下的grep與find的指令喔,不過,要設定環境變數,才可以找到指令。
而這裡有一堆可以在Windows下使用的指令
GnuWin32
有空找一個時間研究一下

參考資料:
Win32平台下的_vimrc
gvim 亂碼的問題
不是打 vi 的廣告, vim 的環境設定 ( vimrc )
[Vim 筆記] TAB SPACE
vim 小技巧 : 行數的顯示與利用
大家來學VIM
vim 的設定與一些快捷鍵
gvim 設定
打造自己的VIM
The Vim Editor
Grep search tools integration with Vim
set 功能設定
史上最強大的vimrc

2009年2月6日 星期五

Dos指令 - 刪除指令

大量刪除檔案
當有大量的資料,且每一個資料只有幾萬個資料,若由winodws下用直接按右鍵要刪除資料,windows為了能夠顯示那條檔案數的百分比,所以會先掃瞄一次所有的檔案,所以你上百萬的檔案數量就要掃很久。

請使用以下兩個方法
方法一:
進入預刪除的資料夾,打以下的指令
% del * /f /s /q

方法二:
% rmdir /s 要刪除的資料夾
加上/q不詢問立刻刪除資料夾
% rmdir /s /q 要刪除的資料夾

Qtcreator - Qt的IDE

噹噹~
Qt出IDE啦,
跟Virtual C++一樣可以拉出視窗介面,
有以下幾個優點:
1. 它是免費的
2. 在windows下的原始碼可以直接在linux下編譯,不過,在windows下程式碼的system("pause");要刪掉
3. 它可以取代Dev C++
4. Syntax highlight
5. auto-complete
6. quick help
7. 即時的語法檢查

Qt Creator 整合了 Qt Designer 跟 debugger,現在你可以拖拖拉拉的把東西拉好,在程式碼編輯畫面把訊息處理加好,按下 F5 就可以開始一行一行的 debug 了。
滑鼠游標移過去就可以看到東西啦,然後 Qt 自己的 class 也有特別支援檢視。

不過目前不接受中文路徑

下載頁面

優點還在體驗中...

要在windows下編譯examples和demos
請把C:\Qt\QtCreator\bin\qtenv.bat修改成以下的內容
@echo off
rem
rem This file is generated
rem

echo Setting up a MinGW/Qt only environment...
echo -- QTDIR set to C:\Qt\QtCreator\qt
echo -- PATH set to C:\Qt\QtCreator\qt\bin
echo -- Adding C:\Qt\QtCreator\mingw\bin to PATH
echo -- Adding %SystemRoot%\System32 to PATH
echo -- QMAKESPEC set to win32-g++

set QTDIR=C:\Qt\QtCreator\qt
set PATH=C:\Qt\QtCreator\qt\bin
REM set PATH=%PATH%;C:\MinGW\bin
set PATH=%PATH%;C:\Qt\QtCreator\mingw\bin
set PATH=%PATH%;%SystemRoot%\System32
set QMAKESPEC=win32-g++

if not "%1"=="compile_debug" goto END
cd %QTDIR%
echo This will configure and compile qt in debug.
echo The release libraries will not be recompiled.
pause
configure -plugin-sql-sqlite -plugin-sql-odbc -qt-libpng -qt-libjpeg
cd %QTDIR%\src
qmake
mingw32-make debug
:END


以上要先確認自己系統有mingw32-make的執行檔~
若沒有的話,安裝Qt Creator
裡面就有內建了~

透過「命令提示字元」來執行此qtenv.bat批次檔,會跑個好幾個小時,去喝個茶吧~
% qtenv.bat compile_debug
完成後,執行qtdemo指令
% qtdemo

[2013.01.05 補充]
現在要安裝QtCreator裡面沒有內建MinGW了,
所以,必需要另外去安裝MinGW了。
只要確定安裝的版本跟QtCreator限定的是同一版的話,
安裝上就沒有什麼大問題了,否則會有一堆奇奇怪怪的問題。
可以參考讓Qt程試碼可以在windows xp下執行

2009年2月5日 星期四

Dia - 流程圖繪製

Dia 被設計成與商業版的視窗軟體 Visio 十分類似
免費的~
感覺很好用,先把它記錄下來!
應該不會太複雜,好像還可以畫UML哩!!

參考資料:
有17個教學錄影檔課程
維基百科

socket - sctp

成功大學多媒體行動實驗室 有做出以下的產品耶 SCTP-MOVIDEO Server

要使用sctp必需先安裝sctp套件
$ sudo apt-get install libsctp-dev

在寫一個簡單的sctp的server-client出現以下錯誤
ren@notebook:~/svn/renyang-learn/socket/sctp/ftp/test$ gcc -c copy_clinet.c -o copy_clinet.o
In file included from copy_clinet.c:7:
/usr/include/netinet/in.h:84: 錯誤: expected identifier before numeric constant

找了很久,測了很久,才發現header file的擺放順序有問題!!?
若是下面順序的話,就會出現以上錯誤!
#include <sys/socket.h>
#include <netinet/sctp.h>
#include <netinet/in.h>

而以下就可以過
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>

這真是太神奇啦~

在編譯serv.c時會出現以下錯誤
ren@notebook:~/Desktop/homework$ gcc serv.c -o serv
/tmp/ccwbUY4s.o: In function `main':
serv.c:(.text+0x1eb): undefined reference to `sctp_sendmsg'
collect2: ld returned 1 exit status

解決方法:多加一個 -lsctp 的參數
ren@notebook:~/Desktop/homework$ gcc serv.c -lsctp -o serv

ren@notebook:~/svn/renyang-learn/socket/sctp/one-to-many$ make
gcc -Wall -O2 -c client.c -o client.o
client.c: In function 'main':
client.c:33: warning: implicit declaration of function 'inet_pton'
client.c:38: warning: implicit declaration of function 'close'

表示inet_pton與close函式的header file沒有正確的被include進來
分別要include arpa/inet.h和unistd.h

ren@notebook:~/svn/renyang-learn/socket/sctp/ftp$ make
gcc -c client.c -o client.o
In file included from client.c:4:
/usr/include/netinet/in.h:84: 錯誤: expected identifier before numeric constant
make: *** [client.o] Error 1

表示有重覆include in.h之類的

inet_pton函數:將點分十進位串轉換成網路位元組序二進位值,此函數對IPv4位址和IPv6位址都能處理。
#include <arpa/inet.h>
int inet_pton(int family,const char * strptr,void * addrptr);
返回:1---成功 0---輸入不是有效的表達格式 -1---失敗

strtol(將字符串轉換成長整型數)
表頭文件:#include <stdlib.h>
定義函數:long int strtol(const char *nptr,char **endptr,int base);
函數說明:strtol()會將參數nptr字符串根據參數base來轉換成長整型數。參數base範圍從2至36,或0。參數base代表採用的進制方式,如 base值為10則採用10進制,若base值為16則採用16進制等。當base值為0時則是採用10進制做轉換,但遇到如'0x'前置字符則會使用 16進制做轉換。一開始strtol()會掃描參數nptr字符串,跳過前面的空格字符,直到遇上數字或正負符號才開始做轉換,再遇到非數字或字符串結束時('\0')結束轉換,並將結果返回。若參數endptr不為NULL,則會將遇到不合條件而終止的nptr中的字符指針由endptr返回。
返回值:返回轉換後的長整型數,否則返回ERANGE並將錯誤代碼存入errno中。
附加說明:ERANGE指定的轉換字符串超出合法範圍。
參考網站

參考資料:
SCTP Programmer's Guide
Stream Control Transmission Protocol (SCTP)
IBM SCTP socket API
SCTP Programmer's Guide: HP
以IPv6有線/無線網路Multihome-based SCTP通訊協定實作之可切換式多媒體視訊串流平台
一些sctp的文章
我國IPv6建置發展計畫
The Stream Control Transmission Protocol(SCTP) Research and simulation Page
程式資料
Linux C編程---網路編程

SCTP相關網站:
傳輸層:TCP、UDP 和 SCTP
lksctp Project
Quick HOWTO : Ch15 : Linux FTP Server Setup
使用 SCTP 優化網路
Linux Kernel SCTP
Stream Control Transmission Protocol
Solaris(TM) Stream Control Transmission Protocol (SCTP)
Better networking with SCTP
SCTP Features

2009年2月4日 星期三

socket - tcp - 觀念

程式寫出來了,觀念還是要說一下,tcp實作檔案傳輸請到這裡

IPv4的定義:
struct in_addr {
  in_addr_t s_addr;
};
struct sockaddr_in{
  unit8_t sin_len;
  sa_family_t sin_family;
  in_port_t sin_port;
  struct in_addr sin_addr;
char sin_zero[8];
};

一般在使用socket通訊時,分身為server的應用程式必需先建立一個通訊端(socket)
再以bind系統呼叫(system call)來完成通訊端的命名
server的應用程式會以listen系統呼叫來建立一個佇列(queue)
再以accept系統呼叫來進行接收
建立好連線之後,通訊端可看做是一個低階的檔案描述子(file descriptor)程式,只要利用read及write指令即可完成雙向的資料通訊

Socket提供了兩種通訊型式
–AF_UNIX
•主要是用來讓單一台電腦內的兩個應用程式,利用標準(或非標準)裝置的埠(PORT)來做資料的傳輸

–AF_INET
•基本的Internet Protocol(IP)的通訊協定,其又可分為stream與datagram等兩層的服務
–Stream是一種可靠的雙向通訊方式,可確保資料的完整性
–Datagram是一種不需要建立連結的通訊方式,無法保證所傳送出資料的完整性

在Linux和Windows網絡編程時需要用到htons和htonl函數,用來將主機字節順序轉換為網絡字節順序。
得到的結果是4096,一開始看感覺很怪。

解釋如下,數字16的16進製表示為0x0010,數字4096的16進製表示為0x1000。由於Intel機器是little-end,存儲數字16時實際順序為1000,存儲4096時實際順序為0010。因此在發送網絡包時為了報文中數據為0010,需要經過htons進行字節轉換。如果用IBM等big-end機器,則沒有這種字節順序轉換,但為了程序的可移植性,也最好用這個函數。

另外用注意,數字所佔位數小於或等於一個byte(8 bits)時,不要用htons轉換。這是因為對於主機來說,big-end and little-end的最小單位為字節(byte)。

sin_family指代協議族,在socket編程中只能是AF_INET
sin_port存儲端口號(使用網絡字節順序)
sin_addr存儲IP地址,使用in_addr這個數據結構
sin_zero是為了讓sockaddr與sockaddr_in兩個數據結構保持大小相同而保留的空字節。
s_addr按照網絡字節順序存儲IP地址
sockaddr_in和sockaddr是並列的結構,指向sockaddr_in的結構體的指針也可以指向
sockadd的結構體,並代替它。也就是說,你可以使用sockaddr_in建立你所需要的信息,
在最後用進行類型轉換就可以了bzero((char*)&mysock,sizeof(mysock));//初始化
mysock結構體名
mysock.sa_family=AF_INET;
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");
……
等到要做轉換的時候用:
(struct sockaddr*)mysock
換句話說在設定的時候用sockaddr_in
而在使用的時候用sockaddr
其實sockaddr_in與sockaddr是一樣的東西
我想是因為要相容於之後的版本,所以,在設定的時候用不同的sockaddr_in
而真正在使用的時候,均使用sockaddr,也就是要轉換成sockaddr的指標

詳細資料可以參考我寫的tcp程式碼,我有註釋在裡面!

[2009.04.30 補充]
在同一個ip,應用程式不可以bind同一個port,但是,透過
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);
可以決解目前這一個問題,詳情請看
socket編程:SO_REUSEADDR例解 (轉)

參考資料:
結構體sockaddr_in和sockaddr用法的問題
TCP 與 UDP
複製檔案 - fread fwrite
請問int a=send(socket,buf,len,flags) 這個a是代表發送的包的大小嗎?(各個參數值已知的情況下)

return與exit的區別

exit是結束一個程序,它將刪除程序使用的記憶體空間,同時把錯誤訊息回傳給父程序,在父程序中wait系統呼叫將接受到此返回訊息。

例子:
void a()
{
  exit();
}
void main()
{
  while(1)
  {
    a();
  }
}

這個程序並不會死循環,因為在a函數中調用exit,所以整個程序就結束了。但如果你在a函數中使用return,那麼就是個死循環了。

例子2:
#include <iostream.h>
using namespace std;
class bbb
{
    public:
        bbb();
        ~bbb();
};

bbb::bbb()
{
    // do nothing
}

bbb::~bbb()
{
    cout << "destruct" << endl;;
}

main()
{
    bbb b;
    //exit(0);
    return 0;
}

然後把//exit(0)的註釋去掉再編譯運行一次。會有不同的結果。

答:當沒有exit(0)時,return 0時,系統會輸出並清理緩衝區並關閉標準輸入cin、標準輸出cout、標準錯誤cerr、標準日誌clog。

當有exit(0)時,c函數會輸出並清理stdin, stdout,現在stdout已經被關閉了,在執行return 0時,cout的緩衝區的數據已經沒有寫入的目標了,所以無輸出。

這只能說明cout和stdout, cin 和stdin用的是不同的緩衝區。

參考資料:
return與exit的區別是什麼?
return和exit的區別

解決ubuntu的解析度

這次回家,
在家裡那一台爛電腦灌ubuntu 8.04,
一開始沒有問題,但是,更新完驅動程式,哭哭~看不到螢幕~
因為螢幕太爛,
找了一堆解決方式,最後,有解決~

不過,我忘記用哪一個方法解決了,下次再回家查好了~


參考資料:
ubuntu 螢幕解析度及 flash 問題解決
ubuntu - 寬螢幕解析度設定
解決ubuntu登入畫面解析度錯誤

2009年2月3日 星期二

I/O - STDIN_FILENO

STDIN_FILENO 是标准输入的文件描述符
详见/usr/include/unistd.h
代码:
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */

例:
int read(STDIN_FILENO, char *buffer, int sizeof(buffer));

例:
stdin
是讓使用者輸入字串,且回傳的是FILE的指標



參考資料:
STDIN和STDIN_FILENO的區別
file and stream : stdin and STDIN_FILENO
read function 設定Non-Blocking I/O的方式