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來做些範例。