2017年6月14日 星期三

【Linux cmd】Linux下使用top來監控cpu使用率或記憶體使用率

top可以顯示系統各進程 (process) 狀態的文字模式工具,top 可以列出消耗系統資源最多的十多個進程。

通常我們會用這樣的方式來啟動top,意思是啟動top並且每秒更新狀態
#top -d 1

當啟動 top 後會顯示Process的數目、CPU 和 記憶體使用量等系統資訊,並預設會列出 CPU 使用率 (%CPU) 最高的十多個Process。另外我們可以按不同的按鍵來改變 top 顯示系統方式,包括按【M】鍵列出佔用最多記憶體的Process,【R】排列出 CPU 使用率最高的Process。另外常用的 top 命令有:
     【? 】或 【h】 - 顯示說明畫面。
     【q】 - 離開 top。
     【Space】或【Enter】 - 更新並重新繪畫整個畫面。
     【M】 - 進程依記憶體使用率 (%MEM) 由大至小排列。
     【T】 - 進程依總 CPU 時間 (TIME+) 由大至小排列。
     【I 】- 在 Solaris 和 Irix 模式切換,改變 CPU 使用率的計算方法。預設一般為 Irix 模式,
     【k】 - 終止某個進程。
     【r】 - 改變進程 nice 值,影響進程的優先序。
       ***process priority nice值範圍 -20 ~ +19,越小優先權越高,一般userSpace程式為0


下圖是進入top後的畫面:












整個 top 畫面主要分成三個區域,由上至下分別為:
     概要區 (Summary Area) - 顯示整個系統的資訊
     訊息/提示列 (Message/Prompt Line) - 顯示各命令的結果訊息或讓使用者輸入命令的參數,平常為一列空行。
     任務區 (Task Area) - 顯示各個task/process的資料。


概要區 (Summary Area) - 系統運作時間及平均負載
第一列顯示現時時間、系統運作時間 (up time)、使用者數目 (users) 和平均負載 (load average)。可以按 【l】 鍵切換是否顯示。



平均負載的三個數值分別為在平均過去 1 分鐘、5 分鐘和 15 分鐘在可運行或不可中斷狀態的進程數目。平均負載為 1.0 表示一個 CPU 被佔用所有時間。如果電腦有多個 CPU,平均負載的參考值亦會倍數增長。例如一個雙處理器雙核的電腦,所有 CPU 所有時間被完全佔用時的平均負載應該為 1.0 x 2 x 2 = 4.0。

任務資訊
第二列顯示任務 (task) 資訊,包括任務總數、運行中 (running)、睡眠中 (sleeping)、停止了(stopped) 和不能運作 (zombie) 的process數目。可以按 【t】 鍵切換是否和下一列 CPU 狀態列一同顯示。



CPU 使用率
第三列顯示 CPU 狀態,包括以下資訊:
us (user): 使用者空間 (user space) 佔用 CPU 百分比。此數值主要受較少 I/O 等系統呼叫的進程所影響。
sy (system): 核心空間 (kernel space) 佔用 CPU 百分比。一般在系統要處理大量 IRQ 或任務排程時,此值會較高。
ni (nice): nice 值比一般值 0 大 (優先序較低) 的進程佔用 CPU 百分比
id (idle): CPU 閒置時間百分比
wa (iowait): CPU 等待輸入/輸出的百分比。當些值過高 (如超過 30%),表示系統的儲存或網路 I/O 效能有問題。
hi (H/W Interrupt): CPU 處理硬體中斷時間的百分比。除光碟機不斷檢查是否有光碟外,一般此值不會太高。
si (S/W Interrupt): CPU 處理軟體中斷時間的百分比,此值很少機會會太高。
st: (Steal): 在如 Xen 等虛擬環境下 CPU 運作虛擬機器時間的百分比。太高表示可能需要停止一些虛擬機器。





您可以按 【t】鍵切換不同顯示方式。在多處理器 (multi-processor) 或多核 (multi-core) 系統上,您亦可以按 數字【1】鍵切換使用一列顯示整體 CPU 使用狀態還是每個 CPU 使用一列顯示其狀態。

記憶體和置換空間使用率
接下來的兩列分別顯示記憶體和置換空間 (swap space) 使用率。可以按 【m】 鍵切換是否顯示。




buffers (緩衝區) 表示被用作磁碟寫入快取 (write cache) 的記憶體大小。當系統記憶體不夠時,自然會把 buffers上的資料清出 (flush) 至磁碟並釋放有關記憶體。過大 buffers (超過幾百 MB) 一般表示儲存子系統有問題,導至buffers上的資料無法清出。
cache (快取) 則表示被使用作檔案讀取快取 (read cache) 的記憶體大小。同樣在記憶體不夠時,部份 cache 使用的記憶體會被釋放。當系統正進行大量讀取工作,此值若高會是不錯的現象。但如果此值在有大量讀取工作時過低 (少於總記憶體大小的四成),這表示系統到了需要增加記憶體的時候。
對大部份伺服器工作,當置換空間 (swap) 被使用時,一般都會拖慢整個系統。除 Oracle 等本身會盡用置換空間的服務外,一般伺服器在開始使用超過幾 MB 的置換空間時,就表示需要進行一些微調工作。


任務區 (Task Area)
任務區會顯示Process耗用系統資源的資訊。每個Process預設會顯示以下資料:









PID (Process ID) - Process ID
USER (Effective user name) - 執行此Process的owner。
PR (priority) - Process的優先值,數值越小表示進程的優先順序越高。
NI (nice) - Process的 nice 值,會影響進程的優先順序 (priority),可以為 20 至 -19 任何一個整數,數值越小會令進程的優先序越高。
VIRT (Virtual memory) - Process使用的總虛擬記憶體 (virtual memory) 大小,包括Process的程式碼、資料和共用程式庫再加上被置換 (swap out) 的空間,單位為 KiB。VIRT = SWAP + RES.
RES (Resident size) - Process非Swap的實體記憶體大小,單位為 KiB。RES = CODE + DATA
SHR (Shared Mem size) - Process使用的共用記憶體大小,也就是可以和其他進程共用的記憶體空間,單位為 KiB。
S (Stats) - Process的狀態,可以為:
   D (uninterruptible sleep) - 在不可中斷的休眠中 (一般為正在進行輸入/輸出)
   R (running) - 在運行中或可以被運行 (即在運行序列 run queue)
   S (sleeping) - 在可以被中斷的休眠中 (一般是正在等待某事件完結)
   T (traced or stopped) - 已被停止。因工作控制訊號 (job control signal) 或Process在被追蹤中。
   Z (Zombie) - 不能運作的進程,即所謂殭屍進程。一般因為已終止但未能被其母進程成功接收的進程。
%CPU (CPU usage) - 由上次 top 畫面更新資料後Process的 CPU 使用率。為Process佔用的 CPU 時間除以實際時間 (CPU 時間 / 實際時間),以百分比顯示。顯示小數點後一個位。可以按 I 鍵切換 Irix 模式 (一般計算方法) 和 Solaris 模式 (一般的 CPU 使用率再除系統的處理器數目) 改變此欄顯示的數值。
%MEM (Memory usage) - Process佔用實體記憶體大小與系統總實體記憶體大小的比例,以百分比顯示。
TIME+ (CPU Time) - 由進程被啟動至今的總 CPU 時間。可以按 S 鍵切換是否開啟累計模式 (Cumulative mode) 改變此欄顯示的數值。
COMMAND (Command line or Program name) - 啟動Process的命令,可以按 c 鍵切換只顯示程式名稱或整個連參數的命令行。


主要命令:
  • ? 或 h - 顯示說明畫面。
  • q - 離開 top。
  • 【Space】【Enter】 - 更新並重新繪畫整個畫面。
  • d 或 s - 改變畫面更新時間。
  • z - 切換單色或彩色顯示模式。
  • B - 切換是否以粗體強調重要資料。
  • c - 切換進程命令欄只顯示命令本身還是連參數顯示整個命令。
  • f - 改變會顯示的進程資料欄目。
  • o - 改變顯示進程的排序方法。
  • M - 進程依記憶體使用率 (%MEM) 由大至小排列。
  • N - 進程依 PID 由大至小排序。
  • P - 進程依 CPU 使用率 (%CPU) 由大至小排列,預設一般使用此方法排列。
  • T - 進程依總 CPU 時間 (TIME+) 由大至小排列。
  • I - 在 Solaris 和 Irix 模式切換,改變 CPU 使用率的計算方法。預設一般為 Irix 模式,
  • u - 監察有效 UID (effective UID) 為個別使用者的進程。
  • U - 監察個真正/有效 UID 為別使用者的進程。
  • i - 切換只顯示活躍進程 (不顯示閒置進程 idle process) 或所有進程,預設一般顯示所有進程
  • n - 設定顯示最多進程數目,預設一般會盡用畫面的空間顯示最多的進程。
  • = - 解除如 u/U/i/n 等命令或 -p 選項監察進程的過濾,顯示所有進程。
  • x - 切換是否以粗體或反白強調排序的進程資料欄目。
  • y - 切換是否以粗體或反白強調正在運行的進程。
  • b - 切換 x/y 命令強調的資料以粗體還是反白顯示。
  • k - 終止某個進程。
  • r - 改變進程 nice 值,影響進程的優先序。
  • l - 切換是否顯示系統運作時間 (up time) 和平均負載 (load average)。預設會顯示。
  • m - 切換是否顯示記憶體和置換空間 (swap space) 使用率。預設會顯示。
  • t - 切換是否顯示進程 (task) 和 CPU 狀態。預設會顯示。
  • 1 - 切換以一列顯示所有 CPU 的平均狀態還是每一個 CPU 顯示一列狀態資訊。預設會只顯示一列平均狀態。

也可以直接下命令,例如: top -o %CPU

在 top 命令中,-o 是用來指定排序的選項。具體來說,-o 後面跟著您想要排序的欄位名稱,例如 %CPU 或 %MEM。

這表示您希望 top 根據 CPU 使用率(%CPU)進行排序,這樣 CPU 使用率最高的進程會顯示在最上面。


更詳細的內容請參考以下的鏈結:
http://wiki.linux.org.hk/w/Monitor_processes_with_top

實際使用到的一個範例,與解釋
top -bi -d 1 -n 1 -w 512

-b:以「批次模式」(batch mode) 輸出,適合用於腳本或將輸出導向檔案。
-i:只顯示有活動的進程(不顯示 idle 的進程)。
-d 1:每 1 秒更新一次(但因為 -n 1,其實只會執行一次)。
-n 1:只執行 1 次(顯示 1 次後就結束)。
-w 512:設定輸出寬度為 512 字元,避免資訊被截斷。

這個指令的用途:
這個指令會以批次模式顯示一次目前系統的活動進程資訊,只顯示有活動的進程,並且將每行寬度設為 512 字元,方便你在腳本或自動化工具中取得完整的系統狀態快照。

2017年6月2日 星期五

Makefile當中 CFLAGS, LDFLAGS, LIBS的使用方法

1. 首先是CFLAGS: 
       說明: 在Makefile當中這個變數是用來指定header所在的位置
       用法: CFLAGS=-I/usr/include/ -I/usr/local/include (指定兩個以上用空白隔開)

2. LDFLAGS:
       說明: 用來指定編譯時所需要用到的Library的路徑位置
       用法: LDFLAGS=-L/usr/lib -L/lib/ (指定兩個以上用空白隔開)

3. LIBS:
       說明: 用來告訴Makefile需要用到的Library檔名叫做甚麼
       用法: LIBS=-lpthread -lz 

2017年5月22日 星期一

IE遇到日曆 網路對話無法運作的問題,解決的方法

如果你操作IE,遇到"日曆網路對話"沒辦法正常運作的情形(選了無反應,或是下面的功能根本叫不出來),如下圖:













解決方法只需在IE的設定--->相容性檢視 的地方




















把你要操作日曆的網址加入下圖的位置,應該就可以正常操作了~

2017年4月27日 星期四

將ubuntu 14.04桌面, 換成類似windows的Style

新版的ubuntu操作介面用起來實在很不習慣,其實只要安裝一個Gnome套件就可以類似windown的操作介面了

安裝指令如下:
     sudo apt-get update; 
  sudo apt-get install gnome-session-fallback;

安裝完成之後,先登出然後在登入的地方可以看到如下圖,請選紅色框框















然後會出現下圖選項,請選擇 Compiz



















接下來登入進去就會看到Style不一樣了,用起來會比較上手!



2017年3月7日 星期二

交叉編譯memtester來測試記憶體是否有問題

要把memtester移植到arm的版子上來執行,因為memtester本身沒有configure的script來幫你產生Makefile,不過只需要去修改下面兩個檔案就可以達到cross-compiler的目的
1. conf-cc
2.conf-ld

1. 首先來看conf-cc這支,原使內容是使用cc來當作compiler,而我們就只需要把cc改成我們arm的toolchain,所以修改方式如下:

原始內容:
cc -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c

This will be used to compile .c files.

修改後:
/home/danny/toolchain/bin/arm-linux-gnueabi-gcc -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c

This will be used to compile .c files.



2. 接著是conf-ld,修改方式也與上面大同小異,修改方式如下:

原始內容:
cc -s


This will be used to link .o files into an executable.

修改後:
/home/danny/toolchain/bin/arm-linux-gnueabi-gcc -s

This will be used to compile .c files.


修改完上述的兩個檔案後,接著指需執行make就可以編譯成功了!!!

====================================================================


memtester的使用方式如下:

memtester [要測試的大小] [測幾個循環]
ex: memtester 512M 5    // 測試512MB共測試5個round


另外還有其他參數 "-p", "-d",這個參數作者沒實際使用過,不過從README解讀的作用大概如下所述:

"-p"
./memtester -p 0x0 64k 1       //直接對實體位置(physical address) 64K的測試一次


"-d"

./memtester –p 0x0 –d /dev/foodev 64k 1    // 若是沒有/dev/mem這個character device,用-d指定memory device.




2017年3月2日 星期四

在linux下,SVN基本的指令

首先先來了解 SVN Trunk, Tags, Branches 這三個的概念

  • trunk: Main line of development(主要的開發線)
  • tags: Releases (想要 Release 時, 可以標Tag, 之後可依 Tag 來找回之前版本的資料)
  • branches: Preparation of release, bug fixing(分支)


接下來是SVN 基本功能,以及指令操作:


Import: 將整個 project_directory 的資料 import 進 svn 裡面

  • svn import project_directory http://domain_name/svn_project



Checkout: 將整個project從svn checkout 回來

  • svn co http://domain_name/svn_project
  • svn co -r 5 http://domain_name/svn_project # checkout第5版的 projcets



List: 列出project中的檔案/資料

  • svn ls http://domain_name/svn_project


Update: 將目前版本更新成 SVN Server上最新版本.

  • svn up


Commit: 將目前所修改的部分 commit 回 SVN Server

  • svn ci


Status: 查看目前檔案結構 跟 SVN Server上的版本有哪些不同

  • svn st


Add: 新增檔案或目錄到 svn

  • svn add File 或 svn add DIR


MV: 更改檔名, 並且此檔案之前紀錄還要繼續留下

  • svn mv filename new_filename


Revert: 還原這次的修改, 回到前一版(未 commit 前可使用)

  • svn revert [File | DIR]


SVN 檔案狀態資訊:

?: 此檔案不存在 SVN 裡面
A: 此次新增的檔案
C: 此檔案已經有人改過, 合併不成功, 需要人工介入
D: 此次移除的檔案
M: 此檔案有修改過
U: 此檔案有被更新過



另外有進階的指令:

建立一個 branch:

  • svn copy http://domain_name/trunk http://domain_name/branches/my-branch -m 'create a branch' 

建立 Release Tags:

  • svn copy http://domain_name/trunk http://domain_name/tags/Release_0.1 -m 'create Release tags for Release 0.1'


合併兩個版本的檔案     //參考自: 用 Subversion 的 Merge 來 Undo

svn merge -r REV1:REV2 {path/to/workingcopy}
 (UNDO) svn merge -r 123:122 ...
 (MERGE)svn merge -r 123:124 ...
svn merge --dry-run -r 343:344 http://domain_name/trunk



有 "C" 狀態處理完後, 用 resolved  將自動產生的檔案刪除, 才能正常 commit:

  • svn resolved filename    //會把自動產生 diff 等等的檔案刪除



找版本間有什麼不同 diff:

  • svn diff     //自動以現在檔案跟 SVN 內最新版做 diff
  • svn diff -r123:124


Info: 列出現在路徑, 版本編號, 最後一次修改日期等等的資訊

  • svn info


Log: 如果沒輸入參數, 預設會把所有 commit log 都列出來

  • svn log
  • svn log -l 10    //顯示最新10筆Log
  • svn log -c 100    //顯示 revision 100 的 Log
  • svn log -v -c 100    //顯示 revision 100 的詳細 Log
relocate: 假設你的SVN Server換IP Address了,使用此參數來重新定位你目前的這包code
  • svn relocate svn://192.168.1.3/home/repos/test/branch/FW


Propset (propset, pset, ps): 版本控制都有些特殊 Keyword 設定, 如 Id 就是最常用的, 設定方法如下:

在檔案內找地方加入 $Id$
設定此檔案要能吃 Id 的 Keyword: svn ps svn:keywords 'Id' filename (只需設一次即可, 之後就不用再設)
svn ci 後, $Id$ 會自動代換成 $Id:filename 編號 年月日時分秒 username $ 的資訊
svn help ps 可以看到有哪些 Keyword 可以用, 即 Keyword 的說明.(ex: URL, Author, Date, Rev, Id 等.)

2017年2月24日 星期五

Linux內核驅動程序初始化順序的調整


今天在做一個驅動的時候要用到另一個驅動(I2C)提供的API,在內核初始化時碰到了一個依賴問題。

我的驅動在I2C初始化之前就運行起來了,而這時I2C提供的API還處於不可用狀態。查了很多資料,網上有人說所有使用module_init這個宏的驅動程序的起動順序都是不確定的(我沒有查到權威的資料)。

所有的__init函數在區段.initcall.init中還保存了一份函數指針,在初始化時內核會通過這些函數指針調用這些__init函數指針,並在整個初始化完成後,釋放整個init區段(包括.init.text,.initcall.init等)。

注意,這些函數在內核初始化過程中的調用順序只和這裡的函數指針的順序有關,和1)中所述的這些函數本身在.init.text區段中的順序無關。在2.4內核中,這些函數指針的順序也是和鏈接的順序有關的,是不確定的。在2.6內核中,initcall.init區段又分成7個子區段,分別是
?
1
2
3
4
5
6
7
.initcall1.init
.initcall2.init
.initcall3.init
.initcall4.init
.initcall5.init
.initcall6.init
.initcall7.init
當需要把函數fn放到.initcall1.init區段時,只要聲明
?
1
core_initcall(fn);
即可。
其他的各個區段的定義方法分別是:
?
1
2
3
4
5
6
7
core_initcall(fn) --->.initcall1.init
postcore_initcall(fn) --->.initcall2.init
arch_initcall(fn) --->.initcall3.init
subsys_initcall(fn) --->.initcall4.init
fs_initcall(fn) --->.initcall5.init
device_initcall(fn) --->.initcall6.init
late_initcall(fn) --->.initcall7.init


而與2.4兼容的initcall(fn)則等價於device_initcall(fn)。各個子區段之間的順序是確定的,即先調用.initcall1.init中的函數指針,再調用.initcall2.init中的函數指針,等等。而在每個子區段中的函數指針的順序是和鏈接順序相關的,是不確定的。

在內核中,不同的init函數被放在不同的子區段中,因此也就決定了它們的調用順序。這樣也就解決了一些init函數之間必須保證一定的調用順序的問題。按照include/Linux/init.h文件所寫的,我在驅動裡償試了這樣兩種方式:

?
1
2
__define_initcall("7", fn);
late_initcall(fn);
都可以把我的驅動調整到最後調用。實際上上面兩個是一回事:
?
1
#define late_initcall(fn) __define_initcall("7", fn)