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)

Busybox的halt, poweroff, reboot指令,以及driver內可以作這些動作的signal

指令 halt、poweroff、跟 reboot 的動作過程類似,都是 kill pid=1 的行程,一般是 init,pid=1 的行程會去執行 inittab 的 shutdown 動作後,呼叫函式庫函式 reboot()。reboot() 再執行系統呼叫進到 kernel 執行 sys_reboot() ,去做相關動作。

Signal的表格如下所示:


signal to kill initreboot() 參數kernel動作
haltSIGUSR1RB_HALT_SYSTEM (0xcdef0123)kernel_halt()停止所有程式
poweroffSIGUSR2RB_POWER_OFF (0x4321fedc)kernel_power_off()停止所有程式後關電 (關電未必有實作)
rebootSIGTERMRB_AUTOBOOT (0x01234567)kernel_restart()停止所有程式後再開機


與busybox的道理相同,假設我在driver內寫一個 kill_cad_pid(SIGTERM, 1);
接下來就會執行reboot()的動作

假設我是寫 kill_cad_pid(SIGUSR2, 1);
則接下來會進入poweroff的狀態

給不同的Signal會有不同的結果!



如果下這三個busybox指令的其中一個,再加上 -f 參數的話,就直接執行 reboot(),不做 inittab 的 shutdown 動作。

2017年2月21日 星期二

Init Script for OpenWrt,新增一個自己的init script

在OpenWrt的系統中,一開機會被執行的Script都會放在/etc/init.d/ 裡面,而當系統開機過程當中,會先去檢查/etc/rc.d/ 裡面,裡面便是告訴系統要做哪些process,而/etc/rc.d/ 裡的檔案都只是個link檔,連結到../init.d/中的process,從/etc/rc.d/裡面的link我們可以知道有哪些開機script會去做

接著我們來實作一個每隔20秒就印出一個 "Hello"的程式(Daemon?)

首先我們要實作的這個題目,我們無法將while loop寫在開機叫起來的這個script裡面,我嘗試過這樣寫,但是開機過程會導致系統開不到console的部分。




所以我們分程兩部分寫:
1. 先寫一個開機script叫做Hello_script.sh,我們在這個script再去呼叫另外一個有while loop 的Hello.sh

2. Hello.sh就負責每20秒印一次Hello訊息到console




以下是實際的範例:(注意第一行一定要有,才有辦法在OpenWrt裡順利執行)
==================  Hello_script.sh =====================
#!/bin/sh /etc/rc.common

START=99
STOP=99

start()
{
          /sbin/Hello.sh &
}

stop()
{
         killall Hello.sh
         echo "===== stop Hello.sh ======"
}
========================================================

講解:
首先當你寫完此檔案後,可以先執行 ./etc/init.d/Hello_scrip.sh enable(如果沒辦法做start請先確定上面範例的第一行程式碼有寫 /etc/rc.common嗎)
這樣表示告訴OpenWrt下次開機就要自動執行此script,當enable完之後,你也可以發現在/etc/rc.d/裡面產生了一個link檔叫做K99Hello_script.sh

OpenWrt 每支 Init Script 都有下列指令可以使用:

/etc/init.d/Hello_script.sh
/etc/init.d/Hello_script.sh  enable //在開機時就自動執行
/etc/init.d/Hello_script.sh  boot
/etc/init.d/Hello_script.sh  start //啟動Hello_script.sh
/etc/init.d/Hello_script.sh  restart //重新啟動
/etc/init.d/Hello_script.sh  stop //停止
/etc/init.d/Hello_script.sh  disable //取消開機時就自動執行

而START=99 意思是給此script在開機時的優先順序,99是一個最低的優先權限,STOP也是相同的意思


另外一個Hello.sh內容如下:
====================== Hello.sh ======================
#!/bin/sh
        while [ 1 ]
        do
             echo "Hello!!"
             sleep 20
        done
=====================================================


這樣就可以讓OpenWrt開機時,自動去做你寫的Daemon了~


此印訊息的範例似乎舉例的不是很好,實際執行起來terminal看不到訊息,但是我們用ps -aux可以確實知道我們的Hello.sh Daemon是一直在執行的!!!




2017年2月14日 星期二

openssl 1.1.0d版本 交叉編譯成arm的

今天剛好需要做到,先在此做個紀錄

1.首先要做config的動作,指令如下:
./config no-asm shared --prefix=/home/danny/extern_lib

prefix的路徑,就看你到時候做make install的時候,要安裝在哪個資料夾

2.手動修改Makefile,config之後進入Makefile會發現CROSS_COMPILE參數是空的,我們手動加入自己的toolchain,ex: CROSS_COMPILE=/home/danny/toolchain/bin/arm-linux-gnueabihf-

3.make
   make install

ps.
1. 我make的時候會遇到 "-m64"的錯誤訊息,目前是到Makefile把"-m64"的參數都先刪除,就       可以順利編譯完成

2. 若是遇到這樣的錯誤訊息 ==> openssl libcrypto.so: undefined reference to `getcontext' ...
     請在第一步驟再加個參數 "no-async" 就可以編譯完成!