2010-07-07

讓ubuntu開機後自動執行特定的script

  在Linux平台中若要開機/關機執行某些script,只要將script加入/etc/init.d目錄中,再依照執行的runlevel將/etc/rcX.d對/etc/init.d目錄中的script作softlink即可,雖然只是幾個步驟不過還是滿雜的,在ubuntu系統中可以藉由update-rc.d命令輕鬆完成後續的工作。

1)首先將開機要執行的動作寫在一個script中,在此以acos.sh命名作為範例,此檔案內容為

#! /bin/sh

mount -t vboxsf DATA /mnt
2)將此檔案移至/etc/init.d目錄下
3)執行sudo update-rc.d default 99 1

完成上述動作後即完成設定。
default => 不指定要設定第幾runlevel,則rc0.d~rc6.d都會加入softlink
99 => 表示開機執行的順序,越小越早執行
1 => 表示關機執行的順序,越小越早執行
開機與關機執行順序數值應屆於00~99之間,通常會建議讓兩數值相加為100,如此開機過程中越早開啟的程序在關機時將越晚關閉。

2010-02-22

【Linux筆記】關於/proc/stat與CPU使用率的計算

下達指令:

$ cat /proc/stat
會得到類似以下的顯示結果
cpu  480 0 708 4305468 1901 27 53 0 0
cpu0 264 0 503 2143900 1730 27 53 0 0
cpu1 215 0 204 2161567 170 0 0 0 0
intr 1587075 115 8 0 2 3 0 5 0 1 0 0 0 119 0 24081 0 1306153 3575
0 685 0 0 0 0 0 0 0 68461 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 499671
btime 1266751940
processes 1984
procs_running 2
procs_blocked 0
softirq 1574719 0 142505 4290 68517 7047 1306131 25188 7 21034

詳細的說明可以參考man 5 proc手冊,下面簡單記錄各欄位意義
  1. 第一列的cpu表示所有cpu0~cpuN(此範例可看出該系統具備雙核心)的加總,接續後面的七組數字代表CPU花了多少"力氣"在不同的工作上,而這"力氣"的單位是Jiffies,cpu各欄位資訊的意義
    user: 一般跑在user mode下的processes
    nice: 跑在user mode下的nice processes(叫nice processes的理由是因為此類processes太nice了,讓出自己的優先權讓別人有更多機會搶先執行)
    system: 執行在kernel mode下的processes
    idle: cpu閒閒沒事的累計數量
    iowait: 等待I/O完成的時間
    irq: 執行中斷服務的時間
    softirq: 執行軟體中斷服務的時間
    stead: Since Linux 2.6.11, there is an eighth column, steal - stolen time, which is the time spent in other operating systems when running in a virtualized environment
    guest: Since Linux 2.6.24, there is a ninth column, guest, which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel
  2. intr後面接續著很多行數字(包括很多的0),其計算從開機(boot time)以來每一種中斷的服務次數,其中第一欄數字是所有中斷的總合
  3. ctxt累計所有cpus的context switches次數
  4. btime紀錄系統開機時距離Unix epoch多少時間(也就是記錄開機的時間點),單位為秒。
  5. processes紀錄有多少processes與threads被建立
  6. procs_running紀錄cpu正執行多少個processes
  7. procs_blocked記錄當下有多少process被block住等待I/O服務完成

參考下面程式碼計算cpu的"當前"使用率(usage rate)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/poll.h>
#include <sys/time.h>

#define TRIMz(x) ((tz = (unsigned long long)(x)) < 0 ? 0 : tz)

void stat() {

FILE *fp_stat ;
char buff[128+1] ;
static unsigned long long u, u_sav, u_frme, s, s_sav, s_frme,
n, n_sav, n_frme, i, i_sav, i_frme,
w, w_sav, w_frme, x, x_sav, x_frme,
y, y_sav, y_frme, z, z_sav, z_frme,
tot_frme, tz ;
float scale ;
fp_stat = fopen("/proc/stat","r") ;
while( fgets(buff, 128, fp_stat) ) {
if( strstr(buff, "cpu") ) {
sscanf(buff, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&u, &n, &s, &i, &w, &x, &y, &z) ;
break ;
}
}
fclose(fp_stat) ;
u_frme = u - u_sav ;
s_frme = s - s_sav ;
n_frme = n - n_sav ;
i_frme = TRIMz(i - i_sav) ;
w_frme = w - w_sav ;
x_frme = x - x_sav ;
y_frme = y - y_sav ;
z_frme = z - z_sav ;
tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme ;
if (tot_frme < 1)
tot_frme = 1 ;
scale = 100.0 / (float)tot_frme ;
printf("%5.1f%%us,%5.1f%%sy,%5.1f%%ni,%5.1f%%id,%5.1f%%wa,%5.1f%%hi,%5.1f%%si,%5.1f%%st\n",
u_frme * scale, s_frme * scale, n_frme * scale,
i_frme * scale, w_frme * scale, x_frme * scale, y_frme * scale, z_frme * scale) ;
u_sav = u;
s_sav = s;
n_sav = n;
i_sav = i;
w_sav = w;
x_sav = x;
y_sav = y;
z_sav = z;
}

int main() {
int i, j ;
struct itimerval tick ;
int res ;

/**
*
* Timer interrupt handler
*
*/
signal(SIGALRM, stat) ; /* SIGALRM handeler */
/* setting first time interval */
tick.it_value.tv_sec = 0 ; // sec
tick.it_value.tv_usec = 500000 ; // usec
/* setting next time interval */
tick.it_interval.tv_sec = 0 ; // sec
tick.it_interval.tv_usec = 500000 ; // usec
res = setitimer(ITIMER_REAL, &tick, NULL);
if(res)
fprintf(stderr, "Error: timer setting faul.\n") ;
else
printf("Timer start...\n") ;
/*
* END
*/

getchar() ;

return 0 ;
}

此程式會印出cpu當前在各種不同工作下的使用比率,仿top指令中的效果,每隔0.5秒印出cpu總使用率。
【程式簡述說明】
設定timer每隔0.5秒發出SIGALRM訊號,接收SIGALRM訊號後將執行stat副程式,此副程式會讀取/proc/stat資訊,相減計算前後兩次間隔中總共耗費多少cpu的力氣

u_frme = u - u_sav ;
s_frme = s - s_sav ;
n_frme = n - n_sav ;
i_frme = TRIMz(i - i_sav) ;
w_frme = w - w_sav ;
x_frme = x - x_sav ;
y_frme = y - y_sav ;
z_frme = z - z_sav ;
tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme ;

藉由個別工作所耗費的力氣除以總耗費力氣即可求得即時的cpu使用率
scale = 100.0 / (float)tot_frme ;
計算scale的100,只是為了表示百分比加上去的,與其在計算個別工作使用率時先各自除以總耗費力氣後再乘上100,不如先乘好這100!

2010-02-13

在ubuntu上安裝完整的man pages

  難得三更半夜有動力coding一下,熊熊要查一system call卻沒書可翻用到的函數網路資料又少...,最後向man求援居然沒資料,原來ubuntu的man pages有給它偷工減料(畢竟人家使用者是針對普羅大眾...就不跟他計較了XD)。

  如果要安裝完整system call的man pages可以:
sudo apt-get install manpages-dev

2010-02-07

測試哪套Linux Distribution比較適合你

  目前以Linux為核心的Distribution已經多到則以讓新手眼花撩亂了,究竟哪套Distribution適合自己呢?或許可以參考一下Linux Distribution Chooser網站,做幾個選擇測驗找出可能適合自己的Distribution吧!

2010-02-03

【Linux筆記】Chapter7. The /proc File System(一)

Textbook: Advanced Linux Programming

  在Linux檔案系統下有一目錄/proc裏頭檔案紀錄著一些存取參數、資料結構以及一些與kernel相關的資訊,在書本中直接說明該目錄是kernel的對外視窗,特別的是目錄下的檔案都是在讀取當下即時產生。
$ ls -l /proc/version
-r--r--r-- 1 root root 0 2010-02-03 10:36 /proc/version
  上面指令使用ls觀察/proc/version檔案,可以看到兩個特點:其一,檔案大小為0,亦即不占據任何空間;其二,檔案的修改時間為下指令時的時間。
$ cat /proc/version
Linux version 2.6.31-14-generic (buildd@rothera) (gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8) ) #48-Ubuntu SMP Fri Oct 16 14:04:26 UTC 2009
  使用cat指令觀看該檔案內容則可以看到得知該檔案紀錄著Linux Kernel的相關資訊,在上述訊息中可以得知目前使用的核心版本是2.6.31,使用gcc-4.4.1版本的編譯器編譯而成等訊息。

$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz
stepping : 6
cpu MHz : 1866.837
cache size : 0 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 constant_tsc up pni monitor
bogomips : 3733.67
clflush size : 64
  上面範例可以知道/proc/cpuinfo檔案儲存著關於系統處理器的相關資訊,若處理器具備多顆核心則會有多組訊息。底下程式示範如何運用/proc下的檔案內容擷取CPU的工作時脈:
#include <stdio.h>
#include <string.h>

float get_cpu_clock_speed() {
FILE *fp ;
char buffer[2048] ;
size_t bytes_read ;
char *match ;
float clock_speed ;

fp = fopen("/proc/cpuinfo", "r") ;
bytes_read = fread(buffer, 1, sizeof(buffer), fp) ;
fclose(fp) ;
/* Bail if read failed or if buffer isn't big enough */
if(bytes_read == 0 || bytes_read == sizeof(buffer))
return 0 ;
/* NUL-terminate the text */
buffer[bytes_read] = '\0' ;
/* Locate the line that starts with "cpu MHz" */
match = strstr(buffer, "cpu MHz") ;
if(match == NULL)
return 0 ;
/* Parse the line to extract the clock speed */

sscanf(match, "cpu MHz : %f", &clock_speed) ;
return clock_speed ;
}

int main() {
printf("CPU clock speed: %4.2f Mhz\n", get_cpu_clock_speed()) ;
return 0 ;
}

2010-01-15

Google跟中國政府玩真的!!

最近資訊相關新聞炒得火熱的除了各家廠商在CES繽紛爭豔,大概就是Google落實執行Do not evil的決心了(就是不再配合中國政府過濾一些敏感字串的搜尋了),本來以為這張圖是人家剪輯合成用來娛樂的,結果好奇一試還真的是...一樣的耶,Google來真的了嗎?

2009-11-24

Ubuntu下的Flash中文亂碼解決方法

修改/etc/fonts/conf.d/49-sansserif.conf內容
→把所有sans-serif都改成sansserif即可。

sudo vi /etc/fonts/conf.d/49-sansserif.conf

2009-10-28

【C語言】秀出數值的二進位表示

#include <stdio.h>

void showBinary(int value, int size) {
int i ;

for(i=(size<<3)-1 ; i>=0 ; i--)
(value & (1<<i) ) ? putchar('1') : putchar('0') ;
}

int main() {
int i=5 ;
char j = 15 ;

//example1: show int type, value is 5
showBinary(i, sizeof(i)) ;
putchar('\n') ;
//example2: show char type, value is 15
showBinary(j, sizeof(j)) ;

getchar() ;
return 0 ;
}

2009-10-22

資工 = 宅 ... @@!?


這圖到底是怎麼回事...實在很不想承認這個事實...
你好~我是宅系出身的正統宅男...@@"

2009-10-11

步進馬達: TS3653NE9

步進馬達區分每條顏色各自為A、A'、B、B'與COM的方法
  1. 將線條分類為兩組:A、A'與COM;B、B'與COM(若控制線只有五條表示只有一個COM)
    用三用電表的電阻擋測試,會三條三條彼此短路,如此便能分為兩大類(A與B)
  2. 找出各自的COM
    一樣使用三用電表的電阻擋量測,A與COM的電阻值會等於A'與COM的電阻值;同樣的,B與COM的電阻值會等於B'與COM的電阻值
    或是A與COM的電阻值會等於2倍的A與A'的電阻值
  3. 分辨出A、A'、B與B'
    將步驟2找出的COM都接到Vcc,四條中挑一條接在Gnd此時馬達會轉一格,然後接續從三條中挑一條接上Gnd,如果順序符合A→B→A'→B'→...的話馬達會順著同一方向旋轉。
    如此便能分辨出A、A'、B與B'
TS3653N3E9這顆步進馬達顏色表示:
COM→黃、白
A→黑
A'→綠
B→藍
B'→紅

2009-10-04

【C語言】左移&右移巨集

恩...就左移與右移巨集函數

#include <stdio.h>

#define ROTATE_LEFT(NUM,BIT) ( \
(NUM<<BIT) | (NUM>>( (sizeof(unsigned)<<3)-BIT) ) \
)

#define ROTATE_RIGHT(NUM,BIT) ( \
(NUM>>BIT) | (NUM<<( (sizeof(unsigned)<<3)-BIT) ) \
)

int main() {
unsigned int x = 0xff000000 ;
printf("0x%8X\t0x%08X\n", x, ROTATE_RIGHT(x,4)) ;
printf("0x%8X\t0x%08X\n", x, ROTATE_LEFT(x,4)) ;
system("pause") ;
return 0 ;
}

2009-07-25

Simplescalar/ARM模擬器安裝與測試

裝這模擬器純粹是老闆要我安裝給他跑而已...
本人對這模擬器沒說很瞭
有任何問題請留言討論,但別期待能幫上什麼忙...

  1. 下載Simplescalar/ARM
    網址: http://www.simplescalar.com/v4test.html
    直接下載網址: http://www.eecs.umich.edu/~taustin/code/arm/simplesim-arm-0.2.tar.gz
  2. 下載Mibench ARM
    網址: http://www.eecs.umich.edu/mibench/
    直接下載網址: http://www.eecs.umich.edu/%7Ejringenb/mibench/mibench_arm_binaries.tar.gz
  3. 解壓縮simplesim-arm-0.2.tar.gz
    $ tar zxvf simplesim-arm-0.2.tar.gz
  4. 進入解壓縮後的目錄
    $ cd simplesim-arm

    PS. 官網上的安裝使用說明文件: http://www.eecs.umich.edu/~taustin/code/arm/ANNOUNCE.ARM

  5. 照上面的說明文件只要兩步驟,一個是設定環境、另一個是make
    $ make config-arm
    $ make
  6. 沒意外的話應該會發生點錯誤,不然也不用寫這篇文章了...
    在最後面應該會看到提示字元 => make: *** [sim-safe.o] Error 1
    往前捲動一下會看到真正錯誤的來源 => machine.h:349: 錯誤: 陣列元素的類型不完全
    其他的錯誤都只是一些副效應 => machine.h:349: 錯誤: 陣列元素的類型不完全
    觀察一下349行附近的敘述
    $ gedit machine.h &
    發現敘述內容為 => extern enum md_opcode md_mask2op[];
    往下面幾行會看到上面用到的列舉型別md_opcode,宣告在354-363行間,敘述如下
    /* global opcode names, these are returned by the decoder (MD_OP_ENUM()) */
    enum md_opcode {
    OP_NA = 0, /* NA */
    #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) OP,
    #define DEFUOP(OP,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) OP,
    #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) OP,
    #define CONNECT(OP)
    #include "machine.def"
    OP_MAX /* number of opcodes + NA */
    };
    把354-363敘述搬到列舉宣告前就可以了,修改完後存檔在重新make一次。
    $ make
  7. 過一會肯定又是眉頭一皺,事情果然並不單純...出現以下錯誤
    /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference in eval.o
    /lib/libc.so.6: could not read symbols: Bad value
    collect2: ld 回傳 1
    make: *** [sim-safe] Error 1

    查看eval.c檔案
    $ gedit eval.c &
    發現83-85行的敘述
    #if defined(__CYGWIN32__)
    #include
    #endif
    但仔細查看Makefile或其他*.h檔案中都沒定義這巨集變數__CYGWIN32__,自然errno.h會被忽略,但程式碼中用到錯誤常數需要此標頭檔定義,所以把83跟85刪掉即可。
    再重新編譯
    $ make
  8. 肯定想飆髒話了,出現以下錯誤
    /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference in range.o
    /lib/libc.so.6: could not read symbols: Bad value
    collect2: ld 回傳 1
    make: *** [sim-safe] Error 1

    此時請查看range.c檔案
    $ gedit range.c &
    找到81-83行的敘述,跟前一個eval.c的問題一樣,把兩行假指令刪掉即可
  9. 在重新編譯
    $ make
    這次可跑比較久了,心中肯定暗爽結束了結束了,就快要編好了,結果伸個懶腰回神一看,下面訊息...
    make: *** [sim-outorder.o] Error 1
    心中肯定充滿無限#@^%&(*&^%#
    想捶牆壁又怕手會痛,實在很無力...
  10. 其實就剩下gcc版本問題了
    查看一下自身gcc版本會發現是4.X
    $ gcc -v
    裝一個3.X版的gcc就可以了
    $ sudo apt-get install gcc-3.4
    如果上述指令安裝失敗請先安裝
    $ sudo apt-get install gcc-3.4-base
  11. 安裝完畢後修改Makefile,設定CC使用gcc-3.4即可
    $ gedit Makefile &
    應該在177行敘述為CC = gcc
    改成CC = gcc-3.4即可
    這次應該就OK了,下make去編譯吧
    $ make
  12. 編完後測試一下,先回到上層目錄
    $ cd ..
    解壓縮mibench_arm_binaries.tar.gz檔案
    $ tar zxvf mibench_arm_binaries.tar.gz
  13. 先把剛剛編譯完的模擬器(這裡示範用sim-outorder,每個模擬器之間的不同請參考官網上的說明)複製到mibench目錄下
    $ cp simplesim-arm/sim-outorder mibench_arm_binaries
  14. 進到mibench的目錄下進行模擬測試
    $ cd mibench_arm_binaries/
    $ ./sim-outorder bitcount/bitcnts.arm 150000
  15. 應該會看到類似下面訊息
    sim: ** simulation statistics **
    sim_num_insn 99409825 # total number of instructions committed
    sim_num_uops 149104246 # total number of UOPs executed
    sim_avg_flowlen 1.4999 # uops per instruction
    sim_num_refs 24470769 # total number of loads and stores committed
    sim_num_loads 14563043 # total number of loads committed
    sim_num_stores 9907726.0000 # total number of stores committed
    這些就是模擬的數據結果,再依據所需觀察各個數值吧

2009-06-20

尋找格蘭菲迪

在ptt上看到網友推薦的活動,好奇心驅使之下就給他參加了
外盒包裝,格蘭菲迪商標很清楚的印在上面!推開外包裝,裡面是一個很有質感的黑色盒子
打開盒子,上面紙張背面印有活動的序號
恩...內包裝的樣子
真是超迷你的迷你酒瓶
品酒準備~贈送的迷你酒+贈送的酒杯+自己準備的冰水
第一步,色澤的觀察
恩...中間品酒步驟跳過
這樣的行銷很棒,有免費的酒可以品嘗還贈送酒杯真是太有心了
巧的是格蘭菲迪12年是我人生購買的第一支威士忌
跟這山羊牌威士忌還真是有緣份
接下來就等15年的品酪禮盒寄來了
最後是18年...雖然送的迷你酒容量只有50ml
品酒而已嘛~這樣很夠了

PS. 品茗酒香,基本上分為三個步驟
首先,距離瓶口不用太近,先讓鼻子熟悉酒精的刺激
接著兩步驟才是真正去感受威士忌釀造時所帶入的花果香味

2008-09-03

【LP】程式讀取參數列

  在Linux下寫程式要讀取參數列的參數(值),最直覺的作法莫過於直接使用main()中的argc與argv變數,不過要自己在程式中處理參數列並且想要提供使用者靈活的參數組合,恐怕會是一個叫人頭痛的"超級任務"。
  以ls程式為例,其參數項目就已經玲瑯滿目(如:-l、-a...等),參數項豐富頂多就是在程式中的switch...case敘述多寫一點,但是再加上沒有參數值的參數項可以合併在一個破折號後面(如:-la),這就很麻煩了。
  在Linux下可使用getopt()函數來幫我們處理參數列的問題,其prototype如下:

int getopt(int argc, char *argv[], const char * optstring) ;
extern char *optarg ;
extern int optind, opterr, optopt ;
  使用上很簡單,getopt函數前兩個參數就將main函數宣告的參數項(argc與argv)填入就是了,重點在於optstring,直接用例子來說明:
#include <stdio.h>
#include
<unistd.h>

int main(int argc, char *argv[]) {
int opt ;


while( (opt=getopt(argc, argv, "x:yz")) != -1 ) {
switch(opt) {
case 'x':
printf("option: %c argument: %s\n", opt, optarg) ;
break ;
case 'y':
case 'z':
printf("option: %c\n", opt) ;
break ;
case '?':
printf("unknow option\n") ;
}
}


return 0 ;
}
  將此範例存檔為lab_arg.c並編譯成lab_arg:gcc -o lab_arg lab_arg.c
  此程式可接受參數x、y、z,並且參數x其後會接著一個參數值,可以先執行看看其效果。在optstring部分範例中用了"x:yz",其表示此程式接受參數有x、y、z,而在x後面加一個冒號(:)說明x參數將會帶一個參數值。
  getopt會依序解析使用者傳入的參數項,若符合optstring規則的參數會回傳對應的參數字元,當getopt函數解析完餐數個數後,會傳回-1表示結束,因此使用一個while迴圈將之包附並檢查傳回值是否為-1。
  使用getopt()我們僅需關注程式中對於各個參數項的對應行為即可,而不需費盡心思自己在程式中解析複雜的參數組合可能。
  更詳細的getopt()函數說明請參閱:http://fair.athost.net/main/linux_c/function/16.html#linuxc293

2008-08-26

建立Toolchain

  當我們在編譯某些Library或是open source的程式時,會遇到target board廠商所提供的toolchain版本過舊/新而產生版本差異引發的錯誤,此時可以藉由自己建構特定版本的toolchain來解決此類的問題。
  那究竟如何建構自己的toolchain呢?其實也不難,跟在一般的PC上建構編譯環境是一樣的,只是我們是要跨平台的編譯環境而已,因此不外乎就是安裝binutilsgccglibcheader這些編譯需要的元件。
  如果覺得很陌生也無所謂,網路上已經有高手寫好自動安裝編譯的script了,我們只需要取得該script檔案並且選擇想要的gcc版本跟glibc版本之後,就可以讓電腦自動完成安裝,接下來我們所需要做的事就是好好品味一下咖啡的香!

  1. 下載crosstool的build script
    開啟http://kegel.com/crosstool/連結,進入download頁面下載crosstool-0.43.tar.gz,記得一定要選擇0.43版本,0.42版在gcc版本驗證的正規表示式限制住只能安裝3.x版本。
  2. 將檔案解壓縮並進入該目錄
    # tar zxvf crosstool-0.43.tar.gz
    # cd crosstool-0.43
  3. 然後依據target的機器選擇script檔,在此選擇demo-arm.sh:
    1 TARBALLS_DIR=$HOME/downloads
    2 RESULT_TOP=/opt/crosstool
    3 export TARBALLS_DIR RESULT_TOP
    4 GCC_LANGUAGES="c,c++"
    ……
    5 eval `cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest
    1 安裝過程中會下載需要的tarball檔,選擇暫存這些檔案的目錄,預設為家目錄下的downloads。
    2 選擇toolchain的安裝根目錄,預設會裝在/opt/crosstool目錄下。
    3 只是把剛剛定義定變數暫時丟給環境變數,方便其他shell取用而已。
    4 這裡可以把需要的編譯語言加進去,比如java等。
    5 你會在這個script檔中看到很多行類似的敘述,這就依需要的版本做選擇就可以了,前面有加井號(#)的表是不採用,沒有加井號的就是我們選擇的版本,因此千萬記住只能有一行是沒有加井號!
  4. 接著建立安裝目錄,並且更改目錄的擁有者為目前登入的帳號:
    # sudo mkdir /opt/crosstool
    # sudo chown $USER /opt/crosstool
  5. 上述基本動作都做完後,下最後一道指令就可以去喝咖啡了!
    # sh demo-arm.sh
  6. 咖啡喝完回來發現:什麼還在跑!sorry剛剛忘了說要多吃一塊pizza,出去再回來後應該就差不多啦,當你看到DONE.提示字串,那就恭喜老爺賀喜老爺:是個活跳跳的toolchain。現在可以透過命令:
    #/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc
  7. 用這樣一長串命令來進行編譯了,每次編譯都打這一長串,只要是人一定會受不了的,因此我們將此路徑加入預設路徑(建議就把這路徑寫入~/bashrc這樣就不用每次登入都要設定路徑):
    # export PATH=$PATH: /opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc
【關鍵字:toolchain、cross compiler、ARM、跨平台編譯器】

2008-06-21

這才叫貪食蛇?!

  阿宅他們這學期在微處理機實習用8051單晶片完成貪食蛇遊戲,想必功力大增不少!不過看到下面這段波蘭學生用宿舍實作貪食蛇,恐怕還是得再加把勁才是...>"<

2008-06-16

【96-下】林志敏 => 作業系統II(期末考)

【關鍵字:林志敏 、作業系統II、考古題、期末考】

2008-06-04

用XOR交換兩個變數的資料

  『用XOR交換變數內容可以不用第三個變數唷!』這句話相信已經是老梗話題了,既然老梗那還寫這篇搞笑...這篇只是用數學來證明為何運用連續的互斥或運算就可以達成兩個變數的交換而且不必用到其他暫存變數。
  在遊戲開始之前先作此假設:運算式的敘述是從右到左。那麼遊戲就開始了,請直接參考下面這張用Tabel PC手寫的證明圖片吧!

<==============全文結束==============>
  好啦~我承認寫這篇其實是炫耀而已,我買了台Table PC耶!手寫功能真方便,ㄎㄎㄎ(喔不~宅男毛病又犯了...向殭屍會磨牙一樣~克制不了XD)

2008-06-03

【王壘-OS】上課筆記 - 排成演算法考試解答

上課範例:FCFS排程演算法→先到的先服務,非強奪式的排程演算法。

小考題目(1):SJF排程演算法→Job最短者先服務,非強奪式的排程演算法。

小考題目(2):SRTF排程演算法→與SJF相似,但是是強奪式的排程演算法。