2009年12月29日 星期二

ubuntu 9.10 desktop 開機時進入console mode


為了使用新版的GLIBC版本,以前的Centos 5.3已經不敷所需,最近在決定要用Fedora,還是ubuntu好呢? Fedora在使用上跟Centosㄧ樣,比較可以馬上上手,無奈在VMWare中就是無法安裝成功,回想以前裝Fedora 6時好像就是裝不起來,才選用Centos。想不到到了Fedora 12 還是不行。唉,可能有其他高手有安裝成功吧,還是Fedora被排擠了......哈哈!!!
看來只好試試ubuntu 9.10,整個安裝過程都蠻順利的,一下子就裝好了。
不過開機完就進入視窗模式,因為比較喜歡console模式,當要使用視窗模式時再開啟。
這版本比較特殊的樣子,怎麼設定都會跑到Graphic mode,最後的解決方式是修改grub 設定:


root@ecken03:~# vi /etc/default/grub

#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" 將這行修改成如下
GRUB_CMDLINE_LINUX_DEFAULT="quiet text"


root@ecken03:~# update-grub


更新設定後,再重開機就會進入console mode。

至於以前的版本,可以參閱/etc/rc2.d/README
# mv /etc/rc2.d/S30gdm /etc/rc2.d/K30gdm
將S開頭改為K開頭就不會執行。

2009年12月17日 星期四

9大NB品牌購買後前三年故障率

為了以後購買NB方便,留下這個資料

9大NB品牌購買後前三年故障率 (200911)
ASUS 15.60%
TOSHIBA 15.70%
SONY 16.80%
Apple 17.40%
DELL 18.30%
Lenovo 21.50%
ACER 23.30%
Gateway 23.50%
HP 25.60%


故障率圖片

很湊巧的,我的ACER NB在快到第二年時,主機板上的顯示卡就壞了,還好還在保固期內,服務站幫我換了主機板,順便檢查到我的硬碟有壞軌,所以也換掉了硬碟,代表保固服務還不錯。

資料: 20091125 聯合報╱國際中心/綜合報導

2009年11月30日 星期一

Get my IP from network card

這個範例顯示如何取得網卡的IP:
eth0.c


#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
int fd;
char IPbuf[30];
struct ifreq ifr;
struct sockaddr_in *myAddr;

strcpy(ifr.ifr_name, "eth0");
fd = socket(AF_INET, SOCK_STREAM, 0);

if(ioctl(fd, SIOCGIFFLAGS, &ifr)>=0)
{
if (ifr.ifr_flags & IFF_UP)
puts("eth0 is UP");
else
{
puts("eth0 is DOWN");
return 1;
}
}

if(ioctl(fd, SIOCGIFADDR, &ifr)>=0)
{
myAddr = (struct sockaddr_in*)&ifr.ifr_addr;
sprintf(IPbuf,inet_ntoa(myAddr->sin_addr));
printf("IP:%s\n",IPbuf);
}

close(fd);

return 0;
}



執行結果:
[root@ecken01 net]# gcc -Wall eth0.c -o eth0
[root@ecken01 net]# ./eth0
eth0 is UP
IP:192.168.0.51

程式中struct ifreq 定義:

struct ifreq {
char ifr_name[IFNAMSIZ];/* Interface name */
union {
struct sockaddrifr_addr;
struct sockaddrifr_dstaddr;
struct sockaddrifr_broadaddr;
struct sockaddrifr_netmask;
struct sockaddrifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmapifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char * ifr_data;
};
};

struct ifconf {
int ifc_len; /* size of buffer */
union {
char * ifc_buf; /* buffer address */
struct ifreq *ifc_req; /* array of structures */
};
};




ioctl的指令:


SIOCGIFNAME:回傳網路卡名稱
SIOCGIFINDEX:取得網路卡索引值
SIOCGIFFLAGS, SIOCSIFFLAGS:取得或設定裝置的Enable旗標

















Device flags
IFF_UP
Interface is running.
IFF_BROADCAST
Valid broadcast address set.
IFF_DEBUG
Internal debugging flag.
IFF_LOOPBACK
Interface is a loopback interface.
IFF_POINTOPOINT
Interface is a point-to-point link.
IFF_RUNNING
Resources allocated.
IFF_NOARP
No arp protocol, L2 destination address not set.
IFF_PROMISC
Interface is in promiscuous mode.
IFF_NOTRAILERS
Avoid use of trailers.
IFF_ALLMULTI
Receive all multicast packets.
IFF_MASTER
Master of a load balancing bundle.
IFF_SLAVE
Slave of a load balancing bundle.
IFF_MULTICAST
Supports multicast
IFF_PORTSEL
Is able to select media type via ifmap.
IFF_AUTOMEDIA
Auto media selection active.
IFF_DYNAMIC
The addresses are lost when the interface goes down.


SIOCGIFMTU, SIOCSIFMTU:傳回或設定最大的傳輸單位MTU
SIOCGIFHWADDR, SIOCSIFHWADDR:取得或設定網路卡的硬體位址
SIOCSIFHWBROADCAST:設定網路卡的廣播位址
SIOCGIFMAP, SIOCSIFMAP:取得或設定網路卡的硬體參數,參數使用ifr_map
struct ifmap {
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};

SIOCADDMULTI, SIOCDELMULTI:增加或刪除網路卡的位址(link layer using ifr_hwaddr)
SIOCGIFTXQLEN, SIOCSIFTXQLEN:取得或設定傳輸佇列的長度
SIOCSIFNAME:改變網路卡名稱
SIOCGIFADDR:取得網路卡位址
SIOCGIFCONF:傳回網路卡位址列表(IPV4)


參考資料:
netdevice(7) - Linux man page

2009年11月27日 星期五

Git introduction and linux command

Git是分散式的版本控制系統(Distributed Revision Control System,DVCS),與其它CVS不同的是它並不一定需要伺服器才能使用,所以我只需要在我的PC上操作即可。它利用分散式的管理方法, 也就是說每個人下載的版本裡有包含有史以來更改過的紀錄。目前有許多的open source project都漸漸的從Subversion 轉到Git,知名的project如 linux kernel, Samba, X.org server, Ruby on Rails....還有許多的專案也都支援使用Git下載最新代碼。

在linux中要使用Git可先到Git官網下載最新版本,然後安裝。我的安裝方式如下:
[root@ecken01 work2]# tar jxvf git-1.6.5.3.tar.bz2
[root@ecken01 work2]# cd git-1.6.5.3
[root@ecken01 git-1.6.5.3]# make
[root@ecken01 git-1.6.5.3]# make install
它會安裝到預設的目錄去,預設的目錄是家目錄 ~/bin/ ,若要更改安裝目錄可使用
[root@ecken01 git-1.6.5.3]# make prefix=/usr install



在linux command 下的基本指令如下:


git init # 開始用 Git 來管理
git add mine.txt # 把 mine.txt 這個檔案加入管理
git add . # 把所有檔案加入 Git
git commit -a # 提交,將目前的檔案狀態變成一個版本
git commit -a -m "your message here" # commit 時直接寫訊息, 不用到下個螢幕上寫

git clone git://github.com/someone/some_project.git local_project #從遠端複製一份專案到我的電腦,目錄名稱為local_project

git status # 查詢從上個版本到現在哪些檔案被修改
git diff # 查詢從上個版本到現在哪幾行被修改
git diff v0.01 v0.03 # 查詢兩個版本間的差異
git diff v0.01:story.txt v0.03:story.txt # 查詢兩個版本間某個檔案的差異

git log # 顯示每個版本那些檔案被修改
git log -p # 顯示每個版本檔案修改的內容
git log --stat --summary # 查詢每個版本間變動的檔案跟行數

git tag v0.02 # 本版別名取為 v0.02
git tag v0.03 40e3e # 把版本 40e3e 取名為 v0.03
git show v1.01 # 查詢 v1.01 版裡的修改內容
git show v1.01:story.txt # 叫出在 v1.01 版時的 story.txt 檔案
git show v1.01:story.txt > test.txt # 把 v1.01 版的 story.txt 抓出來,放入一個叫 test.txt 的檔案
git show HEAD # 看此版本修改的資料
git show HEAD^ # 看此版本前一版的修改的資料

git grep "熊" # 查詢現在的版本裡有沒有熊

git branch 加英文版 # 建立新的分枝叫 "加英文版"
git branch # 查看現有的分枝
git branch beta v0.5 # 依照 "v0.5" 版裡的內容來建立一個叫 "beta" 的分枝
git checkout 加英文版 # 換到 "加英文版" 的分枝上
git checkout master # 換到主幹上
git branch -d 加英文版 # 刪除 "加英文版" 分枝

gitk # 版本瀏覽軟體(需要X-window)
git gui # 瀏覽從上一版本到現在變動的地方(需要X-window)

git gc # 維護 Git 的資料庫
git fsck --full # 同上, 三不五時下次指令

參考資料:
國網中心 Ruby on Rails
Tsuang's Blog
Book: Pro Git
朱雀雀的巴士站

2009年11月24日 星期二

Glib(2) MainLoop, timeout and thread

這個範例展示如何使用多線程,包含timeout function及thread function。

thread.c

#include <stdio.h>
#include <glib.h>
#include <stdio.h>

#define G_THREADS_ENABLED //use multi-thread safe

gboolean TimerFunc (gpointer data)
{
printf ("Timeout: %s\n\n",(char *)data);
return TRUE;
}

gpointer ThreadFunc (gpointer data)
{
int i;
for (i = 0; i < 10; i++)
{
g_print("Thread: %s\n", (char *)data);
g_usleep(500000);
}
return NULL;
}

int main ()
{
GMainLoop *loop;

/* Either the thread system is initialized or, if no thread system is available in GLib , the program will abort */
if (!g_thread_supported ())
{
g_thread_init (NULL);
}

/* Creates a new GMainLoop structure. */
loop = g_main_loop_new (NULL,FALSE);

/* This function creates a new thread with the default priority.
GThread * g_thread_create(GThreadFunc func, gpointer data,
gboolean joinable, GError **error); */
g_thread_create(ThreadFunc, "Running", FALSE, NULL);

/* Sets a function to be called at regular intervals.
guint g_timeout_add(guint interval, GSourceFunc function, gpointer data);*/
g_timeout_add(2000, TimerFunc, ".......");

/* Runs a main loop until g_main_loop_quit() is called on the loop. */
g_main_loop_run(loop);

return 0;
}


這次compile 要再加上 gthread-2.0 library,執行的結果如下:

sh-3.2# ./thread
Thread: Running
Thread: Running
Thread: Running
Thread: Running
Timeout: .......

Thread: Running
Thread: Running
Thread: Running
Thread: Running
Timeout: .......

Thread: Running
Thread: Running
Timeout: .......

Timeout: .......

Timeout: .......

ThreadFunc()執行完後會自行結束。

2009年11月23日 星期一

iPod connector and protocol

前天有人問說想要用ipod來連接控制我們的系統,這真是個好問題ㄚ,要能通訊的話要先了解pin的定義,於是就上網找了一下iPod的腳位及protocol,把相關資料整理一下。



iPod總共有30pin
communication: serial port ,8N1, 19200 baud rate

針腳定義:

The male dock connector's internal pin numbering:

1 3 5 7 9 11 13 15 17 19 21 23 25 27 29
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
Pin#/Functions:

1 Ground (-) 1
2 Line Out - Common Ground (-) 1
3 Line Out - R (+)
4 Line Out - L (+)
5 Line In - R (+)
6 Line In - L (+)
7
8 Video Out - Composite Video (for ipod colour when slideshow activated) 6
9 S-Video Chrominance 7
10 S-Video Luminance 7
11 Serial GND
12 Serial TxD
13 Serial RxD
14
15 Ground (-) 2
16 USB GND (-) 2
17
18 3.3V Power (+) 8
19 Firewire Power 12 VDC (+) 3
20 Firewire Power 12 VDC (+) 3
21 Accessory Indicator 4
22 FireWire Data TPA (-)
23 USB Power 5 VDC (+) 9
24 FireWire Data TPA (+)
25 USB Data (-) 9
26 FireWire Data TPB (-)
27 USB Data (+) 9
28 FireWire Data TPB (+)
29 FireWire Ground (-) 5
30 FireWire Ground (-) 5



資料格式:



















FieldSizeValue
Header20xff 0x55
Length 1 Size of Mode + Command + Parameter
Mode 1 The mode the command is referring to.
Command 2 The two bite command.
Parameter 0..n Optional parameter, depending on the command.
Checksum 1 0x100 - ( (sum of all length/mode/command/parameter bytes) & 0xFF)


例如: FF 55 03 00 01 04 F8

看起來應該可以很容易連線....

參考資料:
http://nuxx.net/wiki/iPod_Dock_Connector
http://nuxx.net/wiki/Apple_Accessory_Protocol
http://stud3.tuwien.ac.at/~e0026607/ipod_remote/ipod_ap.html

2009年11月20日 星期五

Glib (1) Key-value file parser

Glib中有個功能,Key-value file parser 是用來讀取你一個設定檔,如一般常看到的.ini or .conf ,運用glib 可以很容易分析出所設定的參數。用一個小程式來了解如何運用這項功能:
demo file: keyfile.c myconf.ini


keyfile.c

#include <stdio.h>
#include <glib.h>

typedef struct
{
gchar **prod;
gint *price;
} GOODS;

int main()
{
GOODS *conf;
GKeyFile *keyfile;
GKeyFileFlags flags;
GError *error = NULL;
int channel;
double freq;
gsize length;
int i;

// Create a new GKeyFile object and a bitwise list of flags.
keyfile = g_key_file_new();
flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;

// Load the GKeyFile from keyfile.conf or return.
if (!g_key_file_load_from_file (keyfile, "myconf.ini", flags, &error))
return 0;

printf("[doc]\n");
printf("value: %d\n", g_key_file_get_integer(keyfile, "doc", "value", NULL));
printf("version: %s\n", g_key_file_get_string(keyfile, "doc", "version", NULL));

printf("\n[TV]\n");
if (g_key_file_get_boolean(keyfile, "tv", "on", NULL))
printf("TV: true\n");
else
printf("TV: true\n");
channel=g_key_file_get_integer(keyfile, "tv", "channel", NULL);
freq=g_key_file_get_double(keyfile, "tv", "Hz", NULL);
printf("TV: %d\n", channel);
printf("TV: %f\n",freq);

/* Create a new Settings object. If you are using GTK+ 2.8 or below, you should use g_new() or g_malloc() instead! */
conf = g_slice_new (GOODS);

conf->prod = g_key_file_get_string_list(keyfile, "LIST","prod_list", &length, NULL);
conf->price= g_key_file_get_integer_list(keyfile, "LIST","price_list", &length, NULL);

printf("\n[LIST]\n");
printf("name: ");
for(i=0;i printf("%s ",conf->prod[i]);

printf("\nprice: ");
for(i=0;i printf("%d ",conf->price[i]);

printf("\n");

return 0;
}



myconf.ini



# This is a example

[doc]
value=66
version=2.6.17

[tv]
on=yes
channel=23
Hz=59.6

[LIST]
prod_list=book;coffee;pen
price_list=23;54;3


接下來編譯:


[root@ecken02 glib]# arm-linux-gcc -Wall -static `arm-linux-pkg-config --cflags --libs glib-2.0` -o keyfile keyfile.c -lglib-2.0 -liconv -lintl

移到版子上執行
sh-3.2# ./keyfile
[doc]
value: 66
version: 2.6.17

[TV]
TV: true
TV: 23
TV: 59.600000

[LIST]
name: book coffee pen
price: 23 54 3
sh-3.2#


它已經將設定檔的值讀出來了,不過感覺執行的速度有點慢....

sh-3.2# ls -l
-rwxrw-r-- 1 root root 152 Nov 9 2009 Makefile
-rwxr-xr-x 1 root root 2304376 Nov 23 2009 keyfile
-rwxrw-r-- 1 root root 1641 Nov 9 2009 keyfile.c
-rwxrw-r-- 1 root root 136 Nov 9 2009 myconf.ini
sh-3.2#

天啊 !! 想不到執行檔要2.3M,真是不符合軟體短小精幹的要求。
再去掉不必要的symbol,

sh-3.2# ls -l
-rwxrw-r-- 1 root root 152 Nov 9 2009 Makefile
-rwxr-xr-x 1 root root 1363192 Nov 23 2009 keyfile
-rwxrw-r-- 1 root root 1641 Nov 9 2009 keyfile.c
-rwxrw-r-- 1 root root 136 Nov 9 2009 myconf.ini
sh-3.2#

還有1.3M,差不多就只能這樣了。

2009年11月19日 星期四

Porting Glib to ARM

Glib 是一種低階的函式庫,創建 GDK 和 GTK 應用程式時該函式庫可提供許多有用的定義和函式。
它全部是用C語言構成的,當要大量使用資料結構或演算法時,它真的是一個好的library,雖然不玩GTK,不過glib的功能可以簡化我的程式碼,不用寫的哩哩摳摳一大串,現在先從它的README看一下它的功能:

GLib Core Application Support
The Main Event Loop — manages all available sources of events
Threads — thread abstraction; including threads, different mutexes, conditions and thread private data
Thread Pools — pools of threads to execute work concurrently
Asynchronous Queues — asynchronous communication between threads
Dynamic Loading of Modules — portable method for dynamically loading 'plug-ins'
Memory Allocation — general memory-handling
IO Channels — portable support for using files, pipes and sockets
Error Reporting — a system for reporting errors
Message Output and Debugging Functions — functions to output messages and help debug applications
Message Logging — versatile support for logging messages with different levels of importance

GLib Utilities
String Utility Functions — various string-related functions
Character Set Conversion — convert strings between different character sets using iconv()
Unicode Manipulation — functions operating on Unicode characters and UTF-8 strings
Base64 Encoding — encodes and decodes data in Base64 format
Data Checksums — Computes the checksum for data
Internationalization — gettext support macros
Date and Time Functions — calendrical calculations and miscellaneous time stuff
Random Numbers — pseudo-random number generator
Hook Functions — support for manipulating lists of hook functions
Miscellaneous Utility Functions — a selection of portable utility functions
Lexical Scanner — a general purpose lexical scanner
Automatic String Completion — support for automatic completion using a group of target strings
Timers — keep track of elapsed time
Spawning Processes — process launching
File Utilities — various file-related functions
URI Functions — URI Functions
Hostname Utilities — Internet hostname utilities
Shell-related Utilities — shell-like commandline handling
Commandline option parser — parses commandline options
Glob-style pattern matching — matches strings against patterns containing '*' (wildcard) and '?' (joker)
Perl-compatible regular expressions — matches strings against regular expressions
Simple XML Subset Parser — parses a subset of XML
Key-value file parser — parses .ini-like config files
Bookmark file parser — parses files containing bookmarks
Testing — a test framework
Windows Compatibility Functions — UNIX emulation on Windows

GLib Data Types
Memory Slices — efficient way to allocate groups of equal-sized chunks of memory
Memory Chunks — deprecated way to allocate groups of equal-sized chunks of memory
Doubly-Linked Lists — linked lists containing integer values or pointers to data, with the ability to iterate over the list in both directions
Singly-Linked Lists — linked lists containing integer values or pointers to data, limited to iterating over the list in one direction
Double-ended Queues — double-ended queue data structure
Sequences — scalable lists
Trash Stacks — maintain a stack of unused allocated memory chunks
Hash Tables — associations between keys and values so that given a key the value can be found quickly
Strings — text buffers which grow automatically as text is added
String Chunks — efficient storage of groups of strings
Arrays — arrays of arbitrary elements which grow automatically as elements are added
Pointer Arrays — arrays of pointers to any type of data, which grow automatically as new elements are added
Byte Arrays — arrays of bytes, which grow automatically as elements are added
Balanced Binary Trees — a sorted collection of key/value pairs optimized for searching and traversing in order
N-ary Trees — trees of data with any number of branches
Quarks — a 2-way association between a string and a unique integer identifier
Keyed Data Lists — lists of data elements which are accessible by a string or GQuark identifier
Datasets — associate groups of data elements with particular memory locations
Relations and Tuples — tables of data which can be indexed on any number of fields
Caches — caches allow sharing of complex data structures to save resources
Memory Allocators — deprecated way to allocate chunks of memory for GList, GSList and GNode

從它文件中,可以看到它提供很多的功能,為了要了解它提供的一些功能,先把它移植到ARM,順便再做一些範例。 (PS:唉,又是ARM,誰叫我是做embedded的呢。不過其實一些功能已經在PC上測過了,真的還蠻方便的,不過一直沒實做到ARM上。)

CPU:ARM9
toolchain: GCC 4.2.1
glib dependence: libiconv , gettext

gettext-0.16.1.tar.gz
[root@ecken02 gettext-0.16.1]# ./configure --host=arm-linux --prefix=/usr/local/arm_linux_4.2/arm-linux
[root@ecken02 gettext-0.16.1]# make
[root@ecken02 gettext-0.16.1]# make install

libiconv-1.13.1.tar.gz
[root@ecken02 libiconv-1.13.1]# ./configure --host=arm-linux --prefix=/usr/local/arm_linux_4.2/arm-linux
[root@ecken02 libiconv-1.13.1]# make
[root@ecken02 libiconv-1.13.1]# make install

glib-2.20.5.tar.gz
[root@ecken02 glib-2.20.5]# ./configure --host=arm-linux --prefix=/usr/local/arm_linux_4.2/arm-linux/ --enable-static --disable-selinux --cache-file=arm-linux.cache
[root@ecken02 glib-2.20.5]# make
[root@ecken02 glib-2.20.5]# make install

編譯glib之前先設好一些參數,其原因absurd在他的博客已有說明
#cat arm-linux.cache
ac_cv_type_long_long=yes
glib_cv_stack_grows=no
glib_cv_uscore=no
ac_cv_func_posix_getpwuid_r=yes
ac_cv_func_posix_getgrgid_r=yes

compile時會有一個錯誤,
giounix.c:185: error: 'SSIZE_MAX' undeclared
將#include <bits/posix1_lim.h> 加到giounix.c 即可


至此應該已經將glib library加入系統中了。接下來運用它提供的function來做些範例。

2009年9月22日 星期二

在linux上使用vncserver

由於NB上的硬碟空間不足,都得借用其他SERVER的空間,為了方便管理程式以及使用X-window於是便想到來使用linux上的vncserver,利用遠端桌面來操作。

在linux 命令列執行vncserver,第一次執行會要求建立密碼
[root@ecken02 ~]# vncserver

You will require a password to access your desktops.

Password:
Verify:

New 'ecken02:1 (root)' desktop is ecken02:1

Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/ecken02:1.log

我們看一下/root/.vnc/ecken02:1.log的內容
Tue Sep 22 11:39:07 2009
vncext: VNC extension running!
vncext: Listening for VNC connections on port 5901
vncext: Listening for HTTP connections on port 5801
vncext: created VNC server for screen 0

vncserver開啟了兩個port,port 5901是讓vnc client連線進入的,port 5801可以經由http進入

接下來就來試試連線進入的畫面:
1.以網頁HTTP進入
a.開啟IE,輸入IP及port,我們可以發現它是由java來執行的,它的對話框已經幫我們輸入IP,直接按OK即可。


b.輸入當初所建的密碼


c.進入的後的畫面有點醜,只有256色



2. 用vnc client進入
a.先到 RealVNC 下載VNC Free Edition並安裝,安裝完在程式集就可以看到RealVNC.

b. 執行Run VNC Viewer. 輸入IP及port


c.輸入密碼


d.進入後的畫面


以上的操作就可以很簡單的使用遠端桌面。

但事實上有些簡單的事情並不是很容易,繼續來看一些設定值。
一開始執行vncserver是無法進入X-window,要改一下設定值。
使用X-window 桌面:
修改/root/.vnc/xstartup

#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#預設值是使用twm,只有console可以用
#twm &

#使用GNOME桌面
#gnome-session

#使用KDE桌面
startkde


開機自動執行vncserver
修改/etc/sysconfig/vncservers,修改方式參閱http://fedoranews.org/tchung/vnc/01.shtml

# VNCSERVERS="2:myusername"
# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -nohttpd -localhost"
VNCSERVERS="1:root"

2009年9月21日 星期一

利用pkg-config幫助編譯

當我們在compile程式時,有時會利用pkgconfig來尋找某些套件include or library的位置,特別是在不同台電腦compile時更是有用,先來看看編譯時期所需要用到的路徑設定:
1. /etc/ld.so.conf
2. ldconfig
3. PKG_CONFIG_PATH

首先說下/etc/ld.so.conf:

這個文件記錄了編譯時使用的動態鏈接庫的路徑。
默認情況下,編譯器只會使用/lib和/usr/lib這兩個目錄下的庫文件
如果你安裝了某些庫,比如在安裝gtk+-2.4.13時它會需要glib-2.0 >= 2.4.0,辛苦的安裝好glib後
沒有指定 --prefix=/usr 這樣glib庫就裝到了/usr/local下,而又沒有在/etc/ld.so.conf中添加/usr/local/lib
這個搜索路徑,所以編譯gtk+-2.4.13就會出錯了
對於這種情況有兩種方法解決:
一:在編譯glib-2.4.x時,指定安裝到/usr下,這樣庫文件就會放在/usr/lib中,gtk就不會找不到需要的庫文件了 :)
對於安裝庫文件來說,這是個好辦法,這樣也不用設置PKG_CONFIG_PATH了 (稍後說明)

二:將/usr/local/lib加入到/etc/ld.so.conf中,這樣安裝gtk時就會去搜索/usr/local/lib,同樣可以找到需要的庫 :)
將/usr/local/lib加入到/etc/ld.so.conf也是必須的,這樣以後安裝東東到local下,就不會出現這樣的問題了。
將自己可能存放庫文件的路徑都加入到/etc/ld.so.conf中是明智的選擇 ^_^
添加方法也極其簡單,將庫文件的絕對路徑直接寫進去就OK了,一行一個。例如:
/usr/X11R6/lib
/usr/local/lib
/opt/lib

再來看看ldconfig是個什麼東東吧 :

它是一個程序,通常它位於/sbin下,是root用戶使用的東東。具體作用及用法可以man ldconfig查到
簡單的說,它的作用就是將/etc/ld.so.conf列出的路徑下的庫文件 緩存到/etc/ld.so.cache 以供使用
因此當安裝完一些庫文件,(例如剛安裝好glib),或者修改ld.so.conf增加新的庫路徑後,需要運行一下/sbin/ldconfig
使所有的庫文件都被緩存到ld.so.cache中,如果沒做,即使庫文件明明就在/usr/lib下的,也是不會被使用的,結果
編譯過程中抱錯,缺少xxx庫,去查看發現明明就在那放著,搞的想大罵computer蠢豬一個。 ^_^
我曾經編譯KDE時就犯過這個錯誤,(它需要每編譯好一個東東,都要運行一遍),所以

切記改動庫文件後一定要運行一下ldconfig,在任何目錄下運行都可以。


再來說說 PKG_CONFIG_PATH這個變量吧:

先來看一個編譯過程中出現的錯誤:

[root@ecken01 glib]# make
gcc `pkg-config --cflags --libs glib-2.0` -o keyfile keyfile.c -Wall
Package glib-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `glib-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'glib-2.0' found
keyfile.c:2:18: glib.h: No such file or directory

很明顯,上面這段說明,沒有找到glib-2.4.x,並且提示應該將glib-2.0.pc加入到PKG_CONFIG_PATH下。
究竟這個pkg-config PKG_CONFIG_PATH glib-2.0.pc 是做什麼的呢? let me tell you ^_^
先說說它是哪冒出來的,當安裝了pkgconfig-x.x.x這個包後,就多出了pkg-config,它就是需要PKG_CONFIG_PATH的東東
pkgconfig-x.x.x又是做什麼的? 來看一段說明:


代碼:
-->The pkgconfig package contains tools for passing the include path and/or library paths to build tools during the make file execution.

pkg-config is a function that returns meta information for the specified library.

The default setting for PKG_CONFIG_PATH is /usr/lib/pkgconfig because of the prefix we use to install pkgconfig. You may add to PKG_CONFIG_PATH by exporting additional paths on your system where pkgconfig files are installed. Note that PKG_CONFIG_PATH is only needed when compiling packages, not during run-time.-->
我想看過這段說明後,你已經大概瞭解了它是做什麼的吧。
其實pkg-config就是向configure程序提供系統信息的程序,比如軟件的版本啦,庫的版本啦,庫的路徑啦,等等
這些信息只是在編譯其間使用。你可以 ls /usr/lib/pkgconfig 下,會看到許多的*.pc,用文本編輯器打開
會發現類似下面的信息:

prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: GLib
Description: C Utility Library
Version: 2.4.7
Libs: -L${libdir} -lglib-2.0
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include

明白了吧,configure就是靠這些信息判斷你的軟件版本是否符合要求。並且得到這些東東所在的位置,要不去哪裡找呀。
不用我說你也知道為什麼會出現上面那些問題了吧。

解決的辦法很簡單,設定正確的PKG_CONFIG_PATH,假如將glib-2.x.x裝到了/usr/local/下,那麼glib-2.0.pc就會在
/usr/local/lib/pkgconfig下,將這個路徑添加到PKG_CONFIG_PATH下就可以啦。
並且確保configure找到的是正確的glib-2.0.pc。(如果有的話 ^-^)
設定好後可以加入到~/.bashrc中,例如:
PKG_CONFIG_PATH=/usr/lib/pkgconfig
[root@ecken01 glib]# echo $PKG_CONFIG_PATH
/usr/lib/pkgconfig

從上面可以看出,安裝庫文件時,指定安裝到/usr,是很有好處的,無論是/etc/ld.so.conf還是PKG_CONFIG_PATH
默認都會去搜索/usr/lib的,可以省下許多麻煩,不過從源碼包管理上來說,都裝在/usr下
管理是個問題,不如裝在/usr/local下方便管理
其實只要設置好ld.so.conf,PKG_CONFIG_PATH路徑後,就OK啦

正確的編譯範例:

[root@ecken01 glib]# gcc `pkg-config glib-2.0 --cflags --libs ` -o keyfile keyfile.c -Wall
[root@ecken01 font]# gcc `pkg-config freetype2 --cflags --libs` -o ftdemo ftdemo2.c -Wall
[root@ecken01 font]# gcc -g arrow.c -o arrow `pkg-config "gtk+-2.0 > 2.0.0" --cflags --libs`

2009年9月18日 星期五

linux上安裝 QT creator 4.5

自從QT開始以LGPL授權就想來試試它的IDE
OS: Centos 5.3
Software: qt-sdk-linux-x86-opensource-2009.03.1.bin

File/New/Projects/QT4 GUI Application 建立一個hello的project

可以看到他已經建好一個視窗範例 main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}



直接Build看看
發生錯誤
No valid Qt version set. Set one in Tools/Options

到Tools/Options 選擇QT 正確的路徑

再重新編譯看看,還是有錯誤

/opt/qtsdk-2009.03/qt/lib/libQtGui.so: undefined reference to `FcFreeTypeQueryFace'
collect2: ld returned 1 exit status
make: Leaving directory `/root/hello'
make: *** [hello] Error 1

fontcofig 要使用2.4.2版本
http://www.fontconfig.org/release/ 下載2.6.0原始碼
安裝 fontconfig-2.6.0.tar.gz
# cd fontconfig-2.6.0
# ./configure --sysconfdir=/etc --prefix=/usr --mandir=/usr/share/man
# make
# make install

再重新Build All,已經可以看到編譯成功了。
接下來RUN 程式就跑出了空的視窗畫面

2009年4月29日 星期三

FIFO: communication between two process

為了控制另一個程式的執行,這個範例用了pipe的方式,兩個程式之間用pipe來溝通(不過是單向),利用這種方式,我們就可以很簡單的控制另一個程式的執行。

r.c: read date.
w.c: write data.

r.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF

int main(int argc, char *argv[])
{
int res;
int open_mode = 0;
int n=0;
char MYkey;
open_mode= O_RDONLY | O_NONBLOCK; //是nonblock的

if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0777);
if (res != 0) {
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}

res = open(FIFO_NAME, open_mode);
while(1)
{
n=read(res,&MYkey,BUFFER_SIZE);
if(n>0)
printf("%c\n",MYkey);
else
printf("No Data.\n");
sleep(1);
}
exit(EXIT_SUCCESS);
}



w.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF

int main(int argc, char *argv[])
{
int res;
int open_mode = 0;
int n=0;
char MYkey='A';
open_mode= O_WRONLY | O_NONBLOCK;

if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0777);
if (res != 0) {
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}

res = open(FIFO_NAME, open_mode);
while(1)
{
n=write(res,&MYkey,BUFFER_SIZE);
if(n>0)
printf("write %c\n",MYkey);
sleep(3);
MYkey++;
}
exit(EXIT_SUCCESS);
}



執行結果:

[root@ecken02 fifo]# ./r &
[1] 16226
No Data.
[root@ecken02 fifo]# ./w
write A
A
No Data.
No Data.
write B
B
No Data.
No Data.
write C
C
No Data.

typedef for function pointer


#include <stdio.h>
typedef void (*VPF) (int *, int *);
void Square(int *rX, int *rY);
void Swap(int *rX, int *rY);
void PrintVals(VPF,int , int );

int main()
{
int valOne=2, valTwo=5;
VPF pFunc;

pFunc = Swap;
PrintVals ( pFunc, valOne, valTwo);

pFunc = Square;
PrintVals ( pFunc, valOne, valTwo);

return 0;
}

void PrintVals( VPF pFunc,int x, int y)
{
printf("x:%d y:%d\n",x,y);
pFunc(&x,&y);
printf("x:%d y:%d\n",x,y);
printf("\n");
}

void Square(int *rX, int *rY)
{
(*rX) *= (*rX);
(*rY) *= (*rY);
}

void Swap(int *rX, int *rY)
{
int temp;
temp = *rX;
*rX = *rY;
*rY = temp;
}


執行結果:

x:2 y:5
x:5 y:2

x:2 y:5
x:4 y:25

2009年2月11日 星期三

Netlink (2) 應用 hot plug

接下來利用netlink提供的功能來看使用USB熱插拔訊息:
kernel: 2.6.18
GCC: 4.1.2

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>


#define UEVENT_BUFFER_SIZE 1024

static int init_hotplug_sock(void)
{
struct sockaddr_nl snl;
const int buffersize = 16 * 1024;
int retval;

memset(&snl, 0x00, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;

int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (hotplug_sock == -1) {
printf("error getting socket: %s", strerror(errno));
return -1;
}

/* set receive buffersize */
setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));

if (retval < 0) {
printf("bind failed: %s", strerror(errno));
close(hotplug_sock);
hotplug_sock = -1;
return -1;
}
return hotplug_sock;
}

int main(int argc, char* argv[])
{
int hotplug_sock = init_hotplug_sock();
char buf_cache[UEVENT_BUFFER_SIZE*2] = {0};

while(1) {
memset(buf_cache, 0 ,sizeof(buf_cache));
recv(hotplug_sock,buf_cache, sizeof(buf_cache), 0);
printf("======buf_cache: %s\n", buf_cache);
}

return 0;
}


這個程式一開始使用netlink socket開啟 hotplug_sock,並且註冊netlink family為NETLINK_KOBJECT_UEVENT,這個協定目前我看到的是kernel 2.6.15以後才有,利用這個協定來將kernel space message傳給user space。
然後設定hotplug_sock的緩衝區,SO_RCVBUFFORCE(since Linux 2.6.14)可以設定比rmem_max 更大的buffer,將與位址bind 之後,就可以recv()。如此一來,我們就可以很方便收到從kernel傳來USB熱插拔的訊息。

參考資料:
http://blog.csdn.net/absurd/archive/2007/04/27/1587938.aspx

linux kernel man page

Netlink (1) 基礎

Netlink 是一種在內核與用戶應用間進行雙向數據傳輸的非常好的模式,用戶使用標準的 socket API 就可以使用 netlink 提供的強大功能,內核需要使用專門的內核 API 來使用 netlink。我們可以從man中看到它的簡介。

NAME
netlink, PF_NETLINK - Communication between kernel and user

SYNOPSIS
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

netlink_socket = socket(PF_NETLINK, socket_type, netlink_family);


Netlink 相對於系統調用,ioctl 以及 /proc 檔案系統而言具有以下優點︰
1. 為了使用 netlink,用戶僅需要在 include/linux/netlink.h 中增加一個新類型的 netlink 協議定義即可, 如 #define NETLINK_MYTEST 17 然後,內核和用戶態應用就可以立即透過 socket API 使用該 netlink 協議類型進行數據交換。但系統調用需要增加新的系統調用,ioctl 則需要增加設備或檔案, 那需要不少代碼,proc 檔案系統則需要在 /proc 下添加新的檔案或目錄,那將使本來就混亂的 /proc 更加混亂。

2. netlink是一種異步通信機制,在內核與用戶態應用之間傳遞的消息儲存在socket緩沖隊列中,發送消息只是把消息儲存在接收者的socket的接收隊列,而不需要等待接收者收到消息,但系統調用與 ioctl 則是同步通信機制,如果傳遞的數據太長,將影響調度。

3. 使用 netlink 的內核部分可以採用模塊的模式實現,使用 netlink 的應用部分和內核部分沒有編譯時倚賴,但系統調用就有倚賴,而且新的系統調用的實現必須靜態地連接到內核中,它無法在模塊中實現,使用新系統調用的應用在編譯時需要倚賴內核。

4. netlink 支援多播,內核模塊或應用可以把消息多播給一個netlink組,屬於該neilink 組的任何內核模塊或應用都能接收到該消息,內核事件向用戶態的通知機製就使用了這一特性,任何對內核事件感興趣的應用都能收到該子系統發送的內核事件,在後面的文章中將介紹這一機製的使用。

5. 內核可以使用 netlink 首先發起會話,但系統調用和 ioctl 只能由用戶應用發起調用。

6. netlink 使用標準的 socket API,因此很容易使用,但系統調用和 ioctl 則需要專門的培養訓練才能使用。


接下來看一下socket的參數
netlink_socket = socket(PF_NETLINK, socket_type, netlink_family);

socket_type: SOCK_RAW or SOCK_DGRAM,Both can do.
netlink_family: define in kernel source include/linux/netlink.h

#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_W1 1 /* 1-wire subsystem */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Firewalling */
#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ISCSI 8 /* Open-iSCSI */
#define NETLINK_AUDIT 9 /* auditing */
#define NETLINK_FIB_LOOKUP 10
#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16

retval = bind(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
函數 bind() 用於把一個打開的 netlink socket 與 netlink socket 位址綁定在一起。netlink socket 的位址架構如下︰

struct sockaddr_nl
{
sa_family_t nl_family;
unsigned short nl_pad;
__u32 nl_pid;
__u32 nl_groups;
};


參考資料:
http://eddiefu.bokee.com/viewdiary.14137760.html

http://blog.csdn.net/absurd/archive/2008/11/07/3244482.aspx

2009年2月2日 星期一

diff & patch

Compare two file
#diff -u file_old file_new > file.patch

parameter of diff

[root@ecken02 temp]# ls
pnscan-1.8.tar.gz
[root@ecken02 temp]# tar zxvf pnscan-1.8.tar.gz
[root@ecken02 temp]# mv pnscan-1.8 pnscan-1.8.old
[root@ecken02 temp]# tar zxvf pnscan-1.8.tar.gz
[root@ecken02 temp]# ls
pnscan-1.8 pnscan-1.8.old pnscan-1.8.tar.gz
[root@ecken02 temp]# diff -Nur pnscan-1.8.old pnscan-1.8 > file.patch
[root@ecken02 temp]# cat file.patch
diff -Nur pnscan-1.8.old/bm.c pnscan-1.8/bm.c
--- pnscan-1.8.old/bm.c 2002-03-22 18:02:55.000000000 +0800
+++ pnscan-1.8/bm.c 2009-02-02 13:44:47.000000000 +0800
@@ -109,7 +109,7 @@
xsize = m;

saved_m = m;
- saved_x = (unsigned char *) malloc(m);
+ saved_x = (unsigned char *) malloc(m); /* I am here */
if (saved_x == NULL)
return -2;

diff -Nur pnscan-1.8.old/pnscan.c pnscan-1.8/pnscan.c
--- pnscan-1.8.old/pnscan.c 2002-03-22 21:09:52.000000000 +0800
+++ pnscan-1.8/pnscan.c 2009-02-02 13:58:05.000000000 +0800
@@ -106,7 +106,7 @@
return val & 0xFF;
}

-
+/* I am here */
int
dehex(char *str)
{
@@ -996,7 +996,9 @@
goto EndOptions;

case 'h':
- usage(stdout);
+
+ usage(stdout); /* I am here */
+
exit(0);

case 'w':
[root@ecken02 temp]#



Patch file:
#patch -p1 < file.patch

parameter of patch

[root@ecken02 temp]# cp pnscan-1.8.old pnscan-1.8.new
[root@ecken02 temp]# patch -tp1 -d pnscan-1.8.new -i /absolute path/file.patch

2009年1月14日 星期三

My code style

# indent 可以改變你的程式風格
GNU STYLE: -gnu or
-nbad -bap -nbc -bbo -bl -bli2 -bls -ncdb -nce -cp1 -cs -di2 -ndj -nfc1 -nfca -hnl -i2 -ip5 -lp -pcs -nprs -psl -saf -sai -saw -nsc -nsob

-nbad: Do not force a blank line after every block of declarations.
-bap: forces a blank line after every procedure body.
-nbc: Do not Force newline after commas in declaration.
-bbo: Prefer to break long lines before boolean operators.
-bl: Put braces on line after if.
-blin: Indent braces n spaces.
-bls: Put braces on the line after struct declaration lines.
-ncdb: Do not put comment delimiters on blank lines.
-nce: Do not cuddle } and else.
-cp1: Put comments to the right of #else and #endif statements in column n.
-cs: Put a space after a cast operator.
-di2: Put variables in column n.
-ndj:
-nfc1: Do not format comments in the first column as normal.
-nfca: Do not format any comments.
-hnl: Prefer to break long lines at the position of newlines in the input.
-i2: Set indentation level to n spaces.
-ip5: Indent parameter types in old-style function definitions by n space.
-lp: Line up continued lines at parentheses.
-pcs: put space after the function in function calls.
-nprs: Do not put a space after every '(' and before every ')'.
-psl: Put the type of a procedure on the line before its name.
-saf: put a space after every for.
-sai: put a space after every if.
-saw: put a space after every while.
-nsc: Do not put the `*´ character at the left of comments.
-nsob: Do not swallow optional blank lines.

2009年1月9日 星期五

Big Array



看看下面的例子

#include <stdio.h>
int main()
{
char buf1[3145728];
char buf2[3145728];
char buf3[3145728];
char buf4[3145728];
printf("ok\n");
return 0;
}

程式是沒有錯的,但是能執行嗎?
電腦會跟你說 Segmentation fault !!!
但是假如只有buf1及buf2就能順利執行。

這樣的問題就發生在我們建立的buf是在memory的stack,而stack並不夠大到可以容納我們的array。這就是所謂的stack overflow.

但假如我們使用global variable or dynamic memory allocate的方式就解決了,如下面的例子:


#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buf1;
char *buf2;
char *buf3;
char *buf4;
char *buf5;
char *buf6;
if ((buf1 = (char *) malloc (3145728)) == NULL) {
printf("buf1 error\n");
return 9;
}
printf("buf1 ok\n");

if ((buf2 = (char *) malloc (3145728)) == NULL) {
printf("buf2 error\n");
return 9;
}
printf("buf2 ok\n");
.
.
.
if ((buf6 = (char *) malloc (3145728)) == NULL) {
printf("buf6 error\n");
return 9;
}
printf("buf6 ok\n");

free(buf1);
free(buf2);
free(buf3);
free(buf4);
free(buf5);
free(buf6);

return 0;
}

這時你的Array配置在memory的heap,可以讓你有很大的空間使用。

所以在function中,local variable勿無限制的使用(雖然它也有優點),尤其是多線程很容易忽略它,不然就使用malloc()的方式,使用完後也記得要清理free()。


更多的知識可查詢stack、heap