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 ;
}