天天看點

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

嵌入式系統就是一個專用的計算機系統,其上運作的作業系統一般采用Linux系統,既然如此我們就要學會如何使用Linux作業系統。

2.1啟動Linux系統

1.在主控端上啟動虛拟機,點選啟動Ubuntu系統。 如下圖所示:

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

2、Ubuntu系統啟動以後,出現登入畫面,選擇使用者名,并輸入使用者密碼,登入系統,如下圖所示。

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

3. 進入虛拟機後,打開菜單Applications->Accessories->Terminal,打開終端。

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

4.進入終端後,你就可以在終端中輸入相關的Linux指令了,如下圖所示。

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

我們既可以在圖形界面,也可以在字元界面下啟動和操作Linux系統,Linux中的操作大部分都可以以圖形界面界面的形式操作,普通的使用者并不會有太大的不适感。

對于初學者來說,比較習慣與使用圖像界面,但是作為科技人員來說,要習慣使用字元界面,圖形界面要耗費大量的資源,因而有的時候,系統可能根本不會提供圖形化界面,在某些嵌入式系統中甚至隻有字元界面。要想充分利用Linux系統的優勢,對Linux系統進行更精細化操作或進行的Linux系統下的開發的話,還是必須掌握字元界面有關操作技巧的。

小貼士:

   在Ubuntu中直接按ctrl+Alt+T組合鍵可以直接打開終端。

2.2 Linux檔案

Linux一個非常重要的思想是“一切皆檔案”。檔案是Linux系統中非常重要的概念。

需要注意的是Linux系統中檔案名是區分大小寫的,如readme和ReadMe是兩個不同的檔案,并且在Linux系統中檔案名也不存在所謂擴充名,Linux系統也不會根據所謂擴充名來區分檔案,這是與Windows系統不同的。同時也需要注意的是當一個檔案名以小圓點.開頭表示這個檔案是隐藏檔案。

2.2.1Linux目錄

與Windows系統下一樣,在Linux中也是通過目錄來組織檔案的。但不同的是,在 Linux 或 Unix 作業系統中,所有的檔案和目錄都被組織成以一個根節點開始的倒置的樹狀結構,而不象Windows那樣找不到所謂的C槽、D盤。Linux中檔案系統的最頂層是由根目錄開始的,系統使用 / 來表示根目錄。在根目錄之下的既可以是目錄,也可以是檔案,而每一個目錄中又可以包含子目錄檔案。如此反複就可以構成一個龐大的檔案系統。

登入系統後,在目前終端視窗下輸入指令:

$ ls /
           

你會看到如下圖所示:

bin     dev    home   lost+found    mnt     proc    sbin     srv      tmp    var 

boot    etc    lib    media         opt     root     sys      usr 
           

詳細的目錄介紹如下表所示:

目錄 作用 備注
/boot 存放的啟動Linux 時使用的核心檔案,包括連接配接檔案以及鏡像檔案。 系統啟動必須
/etc 這個目錄用來存放所有的系統管理所需要的配置檔案和子目錄。
/lib 這個目錄裡存放着系統最基本的動态連接配接共享庫,其作用類似于Windows裡的DLL檔案。幾乎所有的應用程式都需要用到這些共享庫。
/ sys 這是linux2.6核心的一個很大的變化。該目錄下安裝了2.6核心中新出現的一個檔案系統 sysfs,該檔案系統直覺反映核心裝置樹。當一個核心對象被建立的時候,對應的檔案和目錄也在核心對象子系統中被建立。
/bin bin是Binary的縮寫, 這個目錄存放着最經常使用的指令。 指令集合
/sbin s就是Super User的意思,這裡存放的是系統管理者使用的系統管理程式。
/home 使用者的主目錄,在Linux中,每個使用者都有一個自己的主目錄,一般該目錄名是以使用者的賬号命名的。 賬戶
/root 該目錄為系統管理者,也稱作超級權限者的使用者主目錄。
/dev dev是Device(裝置)的縮寫, 該目錄下存放的是Linux的外部裝置,在Linux中通路裝置的方式和通路檔案的方式是相同的。 外部檔案管理
/media linux系統會自動識别一些裝置,例如U盤、光驅等等,當識别後,linux會把識别的裝置挂載到這個目錄下。
/mnt 系統提供該目錄是為了讓使用者臨時挂載别的檔案系統的,我們可以将光驅挂載在/mnt/上,然後進入該目錄就可以檢視光驅裡的内容了。
/lost+found 這個目錄一般情況下是空的,當系統非法關機後,這裡就存放了一些檔案。 臨時檔案
/ tmp 這個目錄是用來存放一些臨時檔案的。
/opt 預設是空的,使用者安裝的額外軟體一般放在這裡。 擴充用的
/srv 存放服務啟動後需要提取的資料(不用伺服器就是空)
/ var  存放經常修改的資料,比如程式運作的日志檔案(/var/log 目錄下)。 運作過程中要用
/proc 這個目錄是一個虛拟的目錄,它是系統記憶體的映射,我們可以通過直接通路這個目錄來擷取系統資訊。
/usr 使用者的很多應用程式和檔案都放在這個目錄下,類似于windows下的program files目錄。 使用者目錄,這是一個非常重要的目錄

在Linux檔案系統中還有幾個特殊的目錄,一個使用者所在的工作目錄,也叫目前目錄,可以使用一個點 . 來表示;另一個是目前目錄的上一級目錄,也叫父目錄,可以使用兩個點 .. 來表示;使用者的主目錄,可以用一個點波浪線~表示:

  •  . :代表目前的工作目錄,也可以使用 ./ 來表示;
  •  .. :代表目前的工作目錄的父目錄,也可以 ../ 來代表。
  • ~ :代表使用者的主目錄,一般位于/home下,以使用者名命名。

小貼士:

圖形界面下,打開菜單places->Home Folder 将打開一個檔案浏覽器,如下圖所示。對于初學者來說,圖形化界面非常容易操作。點選檔案圖示可以打開檔案,右擊還可以有更多的操作,與Windows系統基本類似,此處不再詳述,讀者可自行探索。

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

2.2.2檔案類型

Linux下主要的檔案類型可分為4種:普通檔案、目錄檔案、連結檔案和裝置檔案。

  1. 普通檔案:使用者最常使用的檔案,即我們通常意義上所說的檔案。它包括文本檔案、資料檔案、二進制可執行檔案等。
  2. 目錄檔案:在Linux中目錄也是檔案,其内容包含了檔案名和子目錄名以及指向檔案和子目錄的指針。
  3. 連結檔案:類似于Windows系統中的快捷方式,但并不完全一樣,可分為軟連結檔案和硬連結檔案
  4. 裝置檔案:在Linux中把裝置抽象成檔案,然後對裝置的操作就像對普通檔案一樣。Linux中裝置相關的維護一般都在“/dev”目錄下。

2.2.3檔案的絕對路徑與相對路徑

  • 絕對路徑:

    路徑的表示方法,由根目錄 / 開始寫起,例如: /usr/share/doc 這個目錄。

  • 相對路徑:

    路徑的表示方法,不是由 / 寫起,而是某個指定位置開始寫起,例如目前路徑為 /usr/share/doc ,要表示 /usr/share/man ,可以寫成 ../man 。

2.2.3檔案屬性

在linux終端中輸入“ls -l”将列出目前目錄下的所有檔案及目錄的相關資訊,如

[email protected]:~$ ls -l
total 64
rxwxr-xr-x  1 ada ada   712  2017-11-12 23:15 build
drwxr-xr-x  2 ada ada 4096 2019-06-18 22:11 Desktop
..........
           

在上面的執行個體中每一行表示某一個檔案或目錄的資訊,共有7組資訊:檔案類型及權限,檔案硬連結數,檔案屬主名,檔案屬組名,檔案大小,檔案時間戳及檔案名。

第一列共有 10 個位置,其中第一個字元代表這個檔案是目錄、檔案或連結檔案等等。

  • 當為[ d ]則是目錄
  • 當為[ - ]則是檔案;
  • 若是[ l ]則表示為連結文檔(link file);
  • 若是[ b ]則表示為裝置檔案裡面的塊裝置(可随機存取裝置),如硬碟等;
  • 若是[ c ]則表示為裝置檔案裡面的字元裝置,例如鍵盤、滑鼠(一次性讀取裝置)。

從第二個字元開始到第十個 9 個字元,3 個字元一組,分别表示了 3 組使用者對檔案或者目錄的權限。權限字元用橫線代表不許可,[ r ]代表可讀(read)、[ w ]代表可寫(write)、[ x ]代表可執行(execute)。 要注意的是,這三個權限的位置不會改變,如果沒有權限,就會出現減号[ - ]。第1-3位确定屬主(該檔案的所有者)擁有該檔案的權限。第4-6位确定屬組(所有者的同組使用者)擁有該檔案的權限,第7-9位确定其他使用者擁有該檔案的權限。

注意:在Linux文本環境中,對于指令前的“[email protected]:~#”,其中“ada”表示登入使用者名,“Ubuntu”表示計算機名,而“~”表示的是使用者目前目錄,最後的字元為指令提示符。Linux作業系統預設是使用普通賬戶登入系統的,預設的指令提示符為“$”,如果使用root超級使用者賬号登入系統後,預設的指令提示符為"#"。

2.3 Linux 常用指令

Linux是一款高可靠性、高性能的操作平台,其優越性在使用者直接使用指令行(shell環境)運作時将得到更加充分的展現,嵌入式系統開發者需要掌握一定的Linux指令。Linux指令系統的指令很多,但是對嵌入式系統開發者來說,隻要重點掌握20多條即可,其他的需要時可以查詢相關資料學習。

Linux指令一般包括檔案及檔案夾管理指令,使用者管理指令,系統管理指令,網絡管理指令及其他等

Linux指令格式:

指令 [選項][參數]

Linux指令行風格

linux中有三種約定區分選項和參數的風格:原始的Unix風格、GNU風格和X tookit風格。

Unix風格:以連字元'-'開頭的單個字元(System V風格)或沒有連字元'-'開頭的單個字元(BSD風格)。如果選項後面不帶參數,則被稱為模式選項,模式選項可以組合在一起使用。如果選項帶參數,這些參數要緊接在選項後面(是否以空格分隔可選)。特點是比較簡潔,但是選項有可能不夠用。

如: gcc -v

GNU風格:使用兩個連續的連字元‘--’後接關鍵字(注意,不是單個字元)。GNU風格的選項不用空格就不能組合使用。選項參數既可以用空格分隔也可以使用單個等号“=”來分隔。特點是容易了解,也容易輸入錯誤或記不住。

如: gcc  --version

X toolkit風格:使用單個連字元‘-’和關鍵字,并由X toolkit進行解析。比較複雜,最好不用。

注:以下部分内容引用了linux指令

2.3.1檔案與目錄管理

ls指令

就是 list 的縮寫,通過 ls 指令不僅可以檢視 linux 檔案夾包含的檔案,而且可以檢視檔案權限(包括目錄、檔案夾、檔案權限)檢視目錄資訊等等。

常用參數搭配:

ls -a 列出目錄所有檔案,包含以.開始的隐藏檔案
ls -A 列出除.及..的其它檔案
ls -r 反序排列
ls -t 以檔案修改時間排序
ls -S 以檔案大小排序
ls -h 以易讀大小顯示
ls -l 除了檔案名之外,還将檔案的權限、所有者、檔案大小等資訊詳細列出來
           

執行個體:

(1) 按易讀方式按時間反序排序,并顯示檔案詳細資訊

ls -lhrt
           

(2) 按大小反序顯示檔案詳細資訊

ls -lrS
           

(3)列出目前目錄中所有以"t"開頭的目錄的詳細内容

ls -l t*
           

cat 指令

cat 指令用于連接配接檔案并列印到标準輸出裝置上。

cat 主要有三大功能:

1.一次顯示整個檔案:

cat filename
           

 2.從鍵盤建立一個檔案:

cat > filename
           

    隻能建立新檔案,不能編輯已有檔案。

3.将幾個檔案合并為一個檔案:

cat file1 file2 > file
           

 cp 指令

将源檔案複制至目标檔案,或将多個源檔案複制至目标目錄。

注意:指令行複制,如果目标檔案已經存在會提示是否覆寫,而在 shell 腳本中,如果不加 -i 參數,則不會提示,而是直接覆寫!

-i 提示
-r 複制目錄及目錄内所有項目
-a 複制的檔案與原檔案時間一樣
           

 執行個體:

(1)複制 a.txt 到 test 目錄下,保持原檔案時間,如果原檔案存在提示是否覆寫。

cp -ai a.txt test
           

 mv 指令

移動檔案或修改檔案名,根據第二參數類型(如目錄,則移動檔案;如為檔案則重指令該檔案)。

當第二個參數為目錄時,第一個參數可以是多個以空格分隔的檔案或目錄,然後移動第一個參數指定的多個檔案到第二個參數指定的目錄中。

執行個體:

(1)将檔案 test.log 重命名為 test1.txt

mv test.log test1.txt
           

 (2)将檔案 log1.txt,log2.txt,log3.txt 移動到根的 test3 目錄中

mv llog1.txt log2.txt log3.txt /test3
           

 (3)将檔案 file1 改名為 file2,如果 file2 已經存在,則詢問是否覆寫

mv -i log1.txt log2.txt
           

(4)移動目前檔案夾下的所有檔案到上一級目錄

mv * ../
           

rm 指令

删除一個目錄中的一個或多個檔案或目錄,如果沒有使用 -r 選項,則 rm 不會删除目錄。如果使用 rm 來删除檔案,通常仍可以将該檔案恢複原狀。

rm [選項] 檔案…
           

   執行個體:

(1)删除任何 .log 檔案,删除前逐一詢問确認:

rm -i *.log
           

 (2)删除 test 子目錄及子目錄中所有檔案删除,并且不用一一确認:

rm -rf test
           

(3)删除以 -f 開頭的檔案

rm -- -f*
           

cd 指令

cd(changeDirectory) 指令文法:

cd [目錄名]
           

說明:切換目前目錄至 dirName。

執行個體:

(1)進入根目錄

cd /
           

(2)進入主 目錄

cd ~
           

(3)進入上一次工作路徑

cd -
           

pwd 指令

pwd 指令用于檢視目前工作目錄路徑。

執行個體:

(1)檢視目前路徑

pwd
           

mkdir 指令

mkdir 指令用于建立檔案夾。

可用選項:

  •     -m: 對建立目錄設定存取權限,也可以用 chmod 指令設定;
  •     -p: 可以是一個路徑名稱。此時若路徑中的某些目錄尚不存在,加上此選項後,系統将自動建立好那些尚不在的目錄,即一次可以建立多個目錄。

執行個體:

(1)目前工作目錄下建立名為 t的檔案夾

mkdir t
           

    (2)在 tmp 目錄下建立路徑為 test/t1/t 的目錄,若不存在,則建立:

mkdir -p /tmp/test/t1/t
           

chmod 指令

Linux/Unix 的檔案調用權限分為三級 : 檔案擁有者、群組、其他。利用 chmod 可以控制檔案如何被他人所調用。

用于改變 linux 系統檔案或目錄的通路權限。用它控制檔案或目錄的通路權限。該指令有兩種用法。一種是包含字母和操作符表達式的文字設定法;另一種是包含數字的數字設定法。

常用參數:

-c 當發生改變時,報告處理資訊
-R 處理指定目錄以及其子目錄下所有檔案
           

 權限範圍:

權限設定字串格式如下 :

[ugoa...][[+-=][rwxX]...][,...]
           
u :目錄或者檔案的目前的使用者
g :目錄或者檔案的目前的群組
o :除了目錄或者檔案的目前使用者或群組之外的使用者或者群組
a :所有的使用者及群組
           

 權限代号:

r :讀權限,用數字4表示
w :寫權限,用數字2表示
x :執行權限,用數字1表示
- :删除權限,用數字0表示
s :特殊權限
           

 執行個體:

(1)增加檔案 t.log 所有使用者可執行權限

chmod a+x t.log
           

  (2)撤銷原來所有的權限,然後使擁有者具有可讀權限,并輸出處理資訊

chmod u=r t.log -c
           

    (3)給 file 的屬主配置設定讀、寫、執行(7)的權限,給file的所在組配置設定讀、執行(5)的權限,給其他使用者配置設定執行(1)的權限

chmod 751 t.log -c(或者:chmod u=rwx,g=rx,o=x t.log -c)
           

 (4)将 test 目錄及其子目錄所有檔案添加可讀權限

chmod u+r,g+r,o+r -R text/ -c
           

此外chmod也可以用數字來表示權限,文法為:

chmod abc file
           

其中a,b,c各為一個數字,分别表示User、Group、及Other的權限。r=4,w=2,x=1

若要rwx屬性則4+2+1=7;

若要rw-屬性則4+2=6;

若要r-x屬性則4+1=5。

執行個體:

将test/hello.c設為所有人可讀可寫可執行

chmod 777 test1/hello.c

或chmod a+rwx  test1/hello.c
           

tar指令

用來壓縮和解壓檔案。tar 本身不具有壓縮功能,隻具有打包功能,有關壓縮及解壓是調用其它的功能來完成。

弄清兩個概念:打包和壓縮。打包是指将一大堆檔案或目錄變成一個總的檔案;壓縮則是将一個大的檔案通過一些壓縮算法變成一個小檔案

-c:建立新的歸檔檔案
-x:從歸檔檔案中還原檔案
-f:指定打封包件或還原的檔案名,這個是必選的,代表檔案
-v:詳細報告tar處理的檔案詳細
-z:用gzip來壓縮或解壓
-j:用bzip2來壓縮或解壓
-J:用xz來壓縮或解壓
-C:配合選項x,指定解壓檔案要存儲的位置
           

執行個體:

将arm-linux-gcc-4.4.3.tar.gz  檔案解壓在/opt下,解壓過程中顯示解壓資訊

tar -xzvf arm-linux-gcc-4.4.3.tar.gz  -C  /opt
           

2.3.2系統指令

useradd:添加使用者

使用者:管理者

使用方式:useradd [選項]  使用者名 

Linux系統是一個多使用者多任務的分時作業系統,任何一個要使用系統資源的使用者,都必須首先向系統管理者申請一個賬号,然後以這個賬号的身份進入系統,不同的使用者用不同的權限,不同的使用者有不同的主目錄。其中root使用者是系統的超級管理者,為系統的預設使用者,具有最高權限,其主目錄為/root,其他使用者的主目錄一般位于/home下的與使用者同名的目錄,其權限由root賦予。

useradd指令用于建立使用者帳号。帳号建好之後,再用passwd設定帳号的密碼.而可用userdel删除帳号。使用useradd指令所建立的帳号,實際上是儲存在/etc/passwd文本檔案中。

-c comment 指定一段注釋性描述。
-d 目錄 指定使用者主目錄,如果此目錄不存在,則同時使用-m選項,可以建立主目錄。
-g 使用者組 指定使用者所屬的使用者組。
-G 使用者組,使用者組 指定使用者所屬的附加組。
-s Shell檔案 指定使用者的登入Shell。
-u 使用者号 指定使用者的使用者号,如果同時有-o選項,則可以重複使用其他使用者的辨別号。
           

例:建立了一個使用者sam,并設定使用者主目錄為/home/sam,并屬于ada使用者組。

useradd  -d  /home/ada  -m  -g ada
           

passwd:設定使用者密碼

使用者:所有使用者

使用方式:passwd  [選項] [使用者名]

使用者管理的一項重要内容是使用者密碼的管理。使用者賬号剛建立時沒有密碼,但是被系統鎖定,無法使用,必須為其指定密碼後才可以使用,即使是指定空密碼。超級使用者可以為自己和其他使用者指定密碼,普通使用者隻能用它修改自己的密碼。如果預設使用者名,則修改目前使用者的密碼。普通使用者修改自己的密碼時,passwd指令會先詢問原密碼,驗證後再要求使用者輸入兩遍新密碼,如果兩次輸入的密碼一緻,則将這個密碼指定給使用者;而超級使用者為使用者指定密碼時,就不需要知道原密碼。

-l 鎖定密碼,即禁用賬号。

-u 密碼解鎖。

-d 使賬号無密碼。

-f 強迫使用者下次登入時修改密碼。

例:給sam使用者設定密碼

passwd sam 
           

ps:顯示程序狀态

使用者:所有使用者

使用方式:ps [選項]  

有的時候我們要終止一個程序的執行或者了解該程序的執行情況,我們就可以通過ps指令獲得程序的程序号(pid)等資訊。ps 的參數非常多,這裡直接給出常用的指令:ps aux  該指令将顯示系統中所有程序資訊。其輸出格式 為:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

其中

  • USER: 程序擁有者
  • PID:  程序号
  • %CPU: 占用的 CPU 使用率
  • %MEM: 占用的存儲器使用率
  • VSZ: 占用的虛拟存儲器大小
  • RSS: 占用的存儲器大小
  • TTY: 終端的次要裝置号碼 (minor device number of tty)
  • STAT: 該程序的狀态:

         D: 無法中斷的休眠狀态 (通常 IO 的程序)

         R: 正在執行中

         S: 靜止狀态

         T: 暫停執行

        Z: 不存在但暫時無法消除

        W: 沒有足夠的記憶體分頁可配置設定

        <: 高優先序的行程

        N: 低優先序的程序

        L: 有存儲器分頁配置設定并鎖在存儲器内 (實時系統或捱A I/O)

  • START: 程序開始時間
  • TIME: 執行的時間
  • COMMAND:所執行的指令

kill:終止程序

使用者:所有使用者

使用方式:kill [選項]  程序号 

kill指令用于删除執行中的程式或工作。

kill可将指定的資訊送至程式。預設的資訊為SIGTERM(15),可将指定程式終止。若仍無法終止該程式,可使用SIGKILL(9)資訊嘗試強制删除程式。程式或工作的編号可利用ps指令檢視。

  • -s <資訊名稱或編号>  指定要送出的資訊。

例:殺死程序12345

kill 12345
           

例:徹底殺死程序12345

kill -9 12345
           

sudo:以系統管理者的身份執行指令

使用者:在 /etc/sudoers 中有出現的使用者。

使用方式:sudo command

export:設定或顯示環境變量

使用方式:export [-fnp][變量名稱]=[變量設定值]

說明:在shell中執行程式時,shell會提供一組環境變量。export可新增,修改或删除環境變量,供後續執行的程式使用。export的效力僅及于該次登陸操作。

-f  代表[變量名稱]中為函數名稱。

-n  删除指定的變量。變量實際上并未删除,隻是不會輸出到後續指令的執行環境中。

-p  列出所有的shell賦予程式的環境變量。

例:列出目前的所有環境變量值

# export -p 
           

例:顯示目前的環境變量PATH的值

# export $PATH

例:将/opt/toolschain/arm-linux-gcc/bin加入目前的搜尋路徑中

 export PATH=PATH:/opt/toolschain/arm-linux-gcc/bin

小知識:

Linux是一個多使用者的作業系統,每個使用者登入系統時都會有一個專用的運作環境,通常情況下每個使用者的預設的環境都是相同的。這個預設環境就是一組環境變量的定義。每個使用者都可以通過修改環境變量的方式對自己的運作環境進行配置。

環境變量主要分三種:1是對所有使用者有效,并且是“永久的”,其一般儲存在/etc/profile檔案中,由root添加。2是僅對目前使用者有效,并且是“永久的”,其一般儲存在使用者目錄下的.bash_profile或.bashrc檔案。3是僅對目前shell (BASH) 有效(臨時的),目前對話結束就失效的。在shell的指令行下直接使用[export變量名=變量值]定義變量,該變量隻在目前的shell(BASH)或其子shell(BASH)下是有效的,shell關閉了,變量也就失效了,再打開新shell時就沒有這個變量,需要使用的話還需要重新定義。

set:設定所使用shell的執行方式

使用方式:set [選項]  

-a  标示已修改的變量,以供輸出至環境變量。

-b  使被中止的背景程式立刻回報執行狀态。

-C  轉向所産生的檔案無法覆寫已存在的檔案。

-d  Shell預設會用雜湊表記憶使用過的指令,以加速指令的執行。使用-d參數可取消。

-e  若指令傳回值不等于0,則立即退出shell。

-f  取消使用通配符。

-h  自動記錄函數的所在位置。

-H Shell  可利用"!"加<指令編号

例:顯示環境變量

# set
BASH=/bin/bash
BASH_ARGC=()
BASH_ARGV=()
BASH_LINENO=()
BASH_SOURCE=()
.............................
           

2.3.3網絡相關指令

ifconfig 指令

  • ifconfig 用于檢視和配置 Linux 系統的網絡接口。
  • 檢視所有網絡接口及其狀态:

    ifconfig -a

  • 使用 up 和 down 指令啟動或停止某個接口:

    ifconfig eth0 up

    ifconfig eth0 down

ping 指令

ping指令用于檢測網絡功能是否正常。

執行個體:

ping  www.baidu.com
           

2.3.4其他

指令 說明 格式
clear 清屏 clear
echo 輸出字元串到标準輸出裝置(螢幕) echo [選項] 字元串
mount 挂載檔案系統 mount [選項] 裝置或結點目标目錄
man MANual pages 顯示指令幫助 man [領域代号] 指令名

man是Linux的

*man是Linux的線上幫助系統。這些man page通常是放在/usr/share/man中,但是我們可以通過修改它的man page搜尋路徑來改變這個指令,修改/etc/man.config即可

2.3.5輸入輸出重定向和管道

重定向就是使用檔案代替标準輸入、标準輸出和标準錯誤輸出。

重定向有5種方式,分别是: 輸出重定向、輸入重定向、錯誤重定向、追加重定向以及同時實作輸出和錯誤的重定向。

标準輸入 (stdin)      :代碼為 0 ,使用 < 或 << ;

标準輸出 (stdout)    :代碼為 1 ,使用 > 或 >> ;

标準錯誤輸出(stderr):代碼為 2 ,使用 2> 或 2>> ;

其中,有一個箭頭的表示以覆寫的方式重定向,而有兩個箭頭的表示以追加的方式重定向。

可以将不需要的标準輸出以及标準錯誤輸出重定向到 /dev/null ,相當于扔進垃圾箱。

如果需要将标準輸出以及标準錯誤輸出同時重定向到一個檔案,需要将某個輸出轉換為另一個輸出,例如 2>&1 表示将标準錯誤輸出轉換為标準輸出。

注:以下部分内容摘自《嵌入式Linux應用開發完成手冊》,韋東山,人民郵電出版社,2008.8 ISBN978-7-115-18262-3

2.4Linux開發工具的使用

源檔案需要經過編譯才能生成可執行檔案。在windows下進行開發時,隻需要單擊節幾個按鍵即可編譯,內建開發環境已經将各種編譯工具的使用封裝好了。Linux下一般更多的時候是直接使用編譯工具。目前Linux下最常用的C語言編譯器是GCC(GNU Compiler Collection),主要涉及的工具有gcc、ld、objcopy、objdump等。不管是生成主機端的程式,還是目标端的程式,gcc的用法是類似的,一般主機端開發工具使用gcc,而目标端使用arm-linux-gcc等。

2.4.1GCC編譯器的使用選項

一個C/C++檔案要經過預處理(preprocessing)、編譯(compilation)、彙編(assembly)和連接配接(linking)等4個步驟才能變成可執行檔案。在日常交流中通常使用“編譯”通稱這4個步驟,如果不特定指明這4個步驟中的某一個,一般以慣例。

第2章 Linux作業系統應用入門2.1啟動Linux系統2.2 Linux檔案2.3 Linux 常用指令2.4Linux開發工具的使用2.5 開發環境的建立2.6常用工具的使用

(1)預處理

C/C++源檔案中,以“#”開頭的指令被稱為預處理指令,如包含指令“#include”、宏定義指令“#define”等。預處理就是将要包含(include)的檔案插入原檔案中,将宏定義展開、根據條件編譯指令選擇要使用的代碼,最後将這些代碼輸入到一個“.i”檔案中等待進一步處理。預處理将要用到cpp工具。

(2)編譯

編譯就是把C/C++代碼(比如上述的“.i”檔案)“翻譯”成彙編代碼,所用到的工具為cc1。

(3)彙編

彙編就是将第二步輸出的彙編代碼翻譯成符合一定格式的機器代碼,在Linux系統上一般變形為ELF格式目标檔案(obj),用到的工具為as。

(4)連接配接

連接配接就是将上步生成的OBJ檔案和系統庫的OBJ檔案、庫檔案連接配接起來,最終生成可以在特定平台運作的可執行檔案,用到的工具為ld。

一般各個階段的工具不需要指定,由gcc自動調用。在編譯過程中,除非使用了“-c","-S"或“-E”選項(或者編譯錯誤阻止了位置的過程),否則最後的步驟總是連接配接。

以一個簡單的“hello world”為例,代碼如下:

/*hello.c*/
#include<stdio.h>
int main(int argc,char **arv){
    printf("hello world!\n");
    return 0;
}
           

 使用gcc,隻需要一個指令就可以生成可執行檔案hello,它包含了上述4個步驟

$gcc -o hello hello.c
           

加上“-v”選項,即使用“gcc -v -o hello hello.c”指令可以觀看編譯的細節,下面摘抄關鍵部分:

cc1 hello.c -o /temp/cctETob7.s
as -o /temp/ccve2KbL.o /temp/cctEtob7.s
collect2 -o hello crt1.o,crti.o crtbegin.o /temp/ccve2KbL.o crtend.o crtn.o
           

 以上3個指令分别對應于編譯步驟的預處理+編譯、彙編和連接配接,ld被collect2調用來連接配接程式。預處理和編譯被放在了一個指令(cc1)中進行,可以把它再次拆分為以下兩步:

ccp -o hello.i hello.c
cc1 hello.i -o /temp/cctETob7.s
           

 可以通過各種控制選項來控制gcc的動作,下面介紹一些常用的選項。

1.總體選項

(1) -c

預處理、編譯和彙編源檔案,但是不做連接配接,編譯器根據源檔案生成OBJ檔案。預設情況下,GCC通過用“.o”替換源檔案名的字尾“.c”等,産生OBJ檔案。可以使用“-o“選項選擇其他名字。

(2)-o file

指定輸出檔案為file。無論是預處理、編譯、彙編還是連接配接,這個選項都可以使用。如果沒有使用“-o”選項,預設的輸出結果是:可執行檔案為“a.out”;若輸入檔案的名稱是“source.suffix”,則它的OBJ檔案是“source.o”,彙編檔案是“source.s”,而預處理後的代碼送往标準輸出。

(3)-v

顯示制造GCC根據自身時的配置指令;同時顯示編譯器驅動程式、預處理器、編譯器的版本号。

以一個程式為例,它包含2個檔案。代碼如下:

/*main.c*/
#include<stdio.h>
extern int add(int x,int y);
int main(int argc,char **arv){
    int i;
    printf("the result=%d!\n",add(3,4));
    return 0;
}
           
/*add.c*/
int add(int x,int y){
   return x+y;
}
           

 使用上面介紹的選項進行編譯,指令如下:

$ gcc -c -o main.o main.c
$ gcc -c -o add.o add.c
$ gcc -o test main.o add.o
           

 其中,main.o、add.o是經過了預處理、編譯、彙編後生成的OBJ檔案,他們還沒有被連接配接成可執行檔案;最後一步将他們連接配接成可執行檔案test,可以直接運作以下指令:

$ ./test
the result=7
           

 以上編譯過程也可以簡寫為:

$ gcc -o test main.c add.c
           

(4)-g

要求編譯器在編譯的時候提供以後對程式進行調試的資訊。

2.警告選項

“-Wall”選項基本打開了所有需要注意的警告資訊,比如沒有指定類型的聲明、在聲明之前就使用的函數、局部變量除了聲明之外就沒再使用等。

上面的main.c檔案中,第5行定義的變量i沒有被使用,但是使用 “gcc -c -o main.o main.c"進行編譯時并沒有出現提示。可以加上“-Wall”選項,如下:

$ gcc -Wall -c main.c
           

執行上述指令後,得到如下警告資訊:

main.c: in function 'main':
main.c:5:warning: unused variable 'i'
           

 3.調試選項

-g:産生調試資訊,隻有加入該選項,GDB才能使用調試資訊。

4.連接配接器選項

用于連接配接OBJ檔案,輸出可執行檔案或庫檔案

(1)object-file-name

如果某些檔案沒有特别明确的字尾,GCC就認為他們是OBJ檔案或庫檔案(根據檔案内容,連接配接器能夠區分OBJ檔案和庫檔案)。如果GCC執行連接配接器操作,這些OBJ檔案将成為連接配接器的輸入檔案。比如上面的"gcc -o test main.o add.o"中,main.o、sub.o就是輸入檔案。

(2)-llibrary

連接配接名為library的庫檔案。

連接配接器再标準搜尋目錄中尋找這個庫檔案,庫檔案的真正名字是“liblibrary.a”。搜素目錄除了一些系統标準目錄外,還包括使用者以“-L”選項指定的路徑。一般說來用這個方法找到的檔案是庫檔案-即由OBJ檔案組成的歸檔檔案(archieve file)。連接配接器處理歸檔檔案的方法是:掃描歸檔檔案,尋找某些成員,這些成員的符号目前已被引用,不過還沒有被定義。但是如果連接配接器找到普通的OBJ檔案,而不是庫檔案,就把這個OBJ檔案按照平方式連接配接起來。指定“-l”選項和指定目錄名的唯一差別是,“-l”選項用“lib”和“.a"把library包裹起來,而且搜尋一些目錄。

5.目錄選項

目錄選項用于查找頭檔案、庫檔案或編譯器的某些成員。

(1)-Idir

在頭檔案的搜尋路徑清單中添加dir目錄。

頭檔案的搜尋方法為:如果以”#include<>“包含檔案,則隻在标準目錄開始搜尋(包括使用-Idir定義的目錄);如果以”#include“包含檔案,則先從使用者的工作目錄開始搜尋,在搜尋标準庫目錄。

(2)-I-

任何在”-I“前面用”-I“選項指定的搜尋路徑隻适用于“#include"file"“這種情況;它們不能搜尋”#include<>“包含的頭檔案。如果用”-I“選項指定的搜尋路徑位于”-I“選項後面,就可以在這些路徑中搜尋所有的”#include“指令(一般來說”-I“就是這麼用)。

(3)-Ldir

在”-I“選項的搜尋路徑清單中添加dir目錄。

2.4.2 ld選項

ld用于将多個目标檔案、庫檔案連接配接成可執行檔案,它的大多數選項和GCC相同。本節主要介紹”-T“選項,該選項可以直接用來指定代碼段、資料段、bss段的起始位址,也可以用來指定一個連接配接腳本在連接配接腳本中進行更複雜的位址設定。

”-T“選項隻用于連接配接沒有底層軟體支援的軟體(如核心,bootloader等);連接配接運作于作業系統之上的應用程式時,無需指定,它們使用預設的方式進行連接配接。

注:檢視預設ld腳本方法

ld --verbose
           

1.直接指定代碼段、資料段、bss段的起始位址

格式如下:

-Ttext startaddr
-Tdata startaddr
-Tbss  startaddr
           

 其中的"startaddr"分别表示代碼段、資料段和bss段的起始位址,它是一個16進制數。如:

ld -Ttext 0x00000000 -g led_on.o -o led_on_elf
           

它表示代碼段的運作位址為0x00000000,由于沒有定義資料段、bss段的起始位址,它們被依次放在代碼段的後面。

2.使用連接配接腳本設定位址

如下例:

ld -Ttimer.lds -o timer_elf head.o init.o interrupt.o main.o
           

它使用連接配接腳本timer.lds來設定可執行檔案timer_lef的位址資訊,timer_elf檔案内容如下:

SECTIONS{
    .=0x30000000;
    .text:{*(.text)}
    .rodata ALIGN(4):{*(.rodata)}
    .data ALIGN(4):{*(.data)}
    .bss ALIGN(4):{*(.bss) *(COMMON)}
}
           

 解析timer_elf檔案之前,先講解連接配接腳本的格式。連接配接腳本的基本指令是SECTIONS指令,它描述了輸出問哪的“映射圖”:輸出檔案中各段、各檔案怎麼放置。一個SECTIONS指令内部包含一個或多個段,段(Section)是連接配接腳本的基本單元,它表示輸入檔案中的某部分怎麼放置。

完整的連接配接腳本格式如下,它的核心部分是段(Section):

SECTIONS{
...
    secname start ALIGN(align) (NOLOAD): AT(ldadr)
    {contents}>region:phdr=fill
...
}
           

secname和contents是必需的,前者用來命名這個段,後者用來确定代碼中的什麼部分放在這個段中。

start是這個段重定位位址,也稱為運作位址。如果代碼中有位置無關的指令,程式在運作時,這個段必須放在這個位址上。

ALIGN(align):雖然start指定了運作位址,但是仍可以使用BLOCK(align)來指定對齊的要求-這個對齊的位址才是真正的運作位址。

(NOLOAD):告訴加載器,在運作時不用加載這個段。這個段隻有在有作業系統的情況下才有意義。

>region:通過使用>region把一個節賦給前面已經定義的一個記憶體區域比如下面的這個例子:

MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 }

SECTIONS {

ROM : { *(.text) } >rom

}
           

:phdr:通過使用`:PHDR'把一個節賦給前面已定義的一個程式段。如果一個節被賦給一個或多個段,那後來配置設定的節都會被賦給這些段,除非它們顯式使用了':PHDR'修飾符。你可以使用':NONE'來告訴連接配接器不要把節放到任何一個段中。看下面的例子:

PHDRS { text PT_LOAD ; }

SECTIONS {

.text : { *(.text) } :text

}
           

fill:你可以通過使用'=FILLEXP'為整個節設定填充樣式。FILLEXP是一個表達式。任何沒有指定的輸出段内的記憶體區域(比如,因為輸入段的對齊要求而産生的裂縫)會被填入這個值。如果填充表達式是一個簡單的十六進制值,比如,一個以'0x'開始的十六進制數字組成的字元串,并且尾部不是'k'或'M',那一個任意的十六進制數字長序列可以被用來指定填充樣式;前導零也變為樣式的一部分。對于所有其他的情況,包含一個附加的括号或一進制操作符'+',那填充樣式是表達式的最低四位元組的值。在所有的情況下,數值是big-endian.你還可以通過在輸出節指令中使用'FILL'指令來改變填充值。

現在可以解析前面的連接配接腳本timer.lds的含義了。

第2行表示設定“目前運作位址”為0x30000000

第3行定義了一個名為“.text”的段,它的内容為“*(.text)”表示所有輸入檔案的代碼段。這些代碼段被集合在一起,起始運作位址為0x30000000

第4行定義了一個名為".rodata"的段,在輸入檔案timer_elf中,它緊挨着“.text"段存放。其中的“ALIGN(4)”表示起始運作位址為4位元組對齊。

第5、6行的含義類似。

完整版的官網Gnulinkerscript

2.4.3 objcopy選項

objcopy被用來複制一個目标檔案的内容到另外一個檔案中,可以使用不同于源檔案的格式來輸出目的檔案,即可以進行格式轉換。在linux系統中,一般用于将ELF格式的可執行檔案轉換為二進制檔案。

使用格式如下:

objcopy [選項][參數] 源檔案  目标檔案
           

(1)-I bfdname

用來指明源檔案的格式,bfdname指的是源檔案的标準格式名。如果不指定源檔案格式名,objcopy會自己去分析元檔案的格式。

(2)-O bfdname

用來指定輸入檔案的格式

(3)-S

不從源檔案中複制重定位資訊和符号資訊到目标檔案中。

(4)-g

不從源檔案中複雜調試符号到目标檔案中去。

在編譯bootloader、核心時,常用arm-linux-objcopy指令将ELF格式的生成結果轉換為二進制檔案,比如:

$ arm-linux-objcopy -O binary -S elf_file bin_file
           

2.4.4 objdump選項

objdump用于顯示二進制檔案資訊,常用于檢視反彙編代碼。

格式如下:

objdump [選項][參數] 源檔案
           

(1) -b bfdname

指定目标碼格式。這不是必須的,objdump能自動識别許多格式。可以使用“objdump -i"指令檢視支援的目标碼格式清單。

(2)-d

反彙編可執行段

(3)-i

顯示支援的目标格式和CPU架構

4.-m

指定反彙編目标檔案時的架構

将ELF格式檔案轉換為反彙編檔案:

arm-linux-objdump -D elf_file>dis_file
           

将二進制檔案轉換為反彙編檔案:

arm-linux-objdump -D -b binary -m arm bin_file>dis_file
           

2.4.5 GDB調試器

無論多麼優秀的程式員,必須經常面對的一個問題就是調試。當程式編譯完成後,它可能無法正常運作;或許程式會崩潰;或許隻是不能正常地運作某些功能;或許它的輸出會被挂起;或許不會提示要求正常的輸入。無論在何種情況下,跟蹤這些問題,特别是在大的工程中,将是開發中最困難的部分。

linux系統中包含了GNU調試程式GDB,這是一個用來調試C/C++程式的調試器,可以使程式開發者在程式運作時觀察程式的内部結構和記憶體的使用情況。

GDB程式調試的對象時可執行檔案,而不是程式的源代碼檔案。然而,并不是所有的可執行檔案都可以用GDB調試。如果要對可執行檔案進行調試,需要在執行GCC指令編譯程式時,加上-g參數,指定程式在編譯時包含調試資訊。調試資訊寶航程式裡的每個變量的類型和在可執行檔案裡的位址映射以及源代碼的行号。GDB利用這些資訊時源代碼和機器碼相關聯。

1.GDB的啟動

在終端視窗中,有兩種方法運作GDB,即在終端視窗的指令行中直接輸入gdb指令或gdb filename指令啟動GDB。

方法1-啟動GBD後執行file filename 指令,即

gdb
file filename
           

執行上述兩條指令就可以啟動GDB,并裝入可執行的程式filename

方法2-啟動的同時裝入可執行的程式,即

gdb  filename
           

啟動GDB以後,就可以使用GDB的指令調試程式。

2.GDB的常用指令

GDB中的指令主要分為工作環境相關指令,設定斷點與恢複指令、源代碼檢視目錄,檢視運作資料相關指令即修改運作參數指令等。GDB可以通過查找指令所屬的種類(class),可以從相關class中找到相應指令。

 (1) help :此指令可列出目錄的種類

(2)help [command]:若使用者已知指令名,可以直接鍵入來檢視指令

(3) info  b: 檢視所設斷點

(4) break 行号或函數名:設定斷點

(5)delete[斷點号]:删除指定斷點号,其斷點号為info b中的第一欄。若為預設斷點号則删除所有斷點。

(6)disable[斷點号]:停止指定斷點,使用info b 仍然能檢視此斷點

(7)enable[斷點号]:激活指定斷點

(8)step:單步恢複程式運作,且進入函數調用

(9)next:單步恢複程式運作,但進入函不數調用

(10)finshi:運作程式,直到目前函數完成傳回

(11)continue:繼續執行函數,直到函數結束或遇到新的斷點

(12)list<行号>|<函數名>:檢視指定位置代碼

  (13) file[檔案名]:加載指定檔案

(14)print 表達式|變量:檢視程式運作時對應表達式和變量的值

  (15) x<n/f/u>:檢視記憶體變量例如。其中n為整數表示顯示記憶體的長度,f表示顯示的格式,u表示從目前位址往後請求的位元組長度。

(16)display 表達式:設定在單步運作或其他情況中,自動顯示的表達式的内容。

(17)run:執行目前被調試的程式

(18)kill:停止正在調試的程式

(19)set 變量=設定值:單步執行時,修改運作時的參數,并使該變量按照使用者目前輸入的值繼續運作。

(20)quit:退出GDB

要注意,在不引起歧義的情況下,輸入完整的指令和輸入指令的首字母效果是一樣的。

2.4.6GNU make指令和Makefile檔案

使用GCC的指令行進行程式編譯在單個檔案下是比較友善的,當工程中的檔案逐漸增多,甚至變得十分龐大時,使用GCC指令行編譯機會漸漸變得力不從心。Linux中得make工具提供了一種管理工程的能力,可以友善地進行程式的編譯,對更新的檔案進行重新編譯。

GNU make的主要功能時讀入一個文本檔案Makefile,并根據Makefile的内容執行一系列的工作。Makefile的預設檔案名為GNU makefile、makefile或makefile,也可以在make的指令行中指定别的檔案名。多數Linux程式員使用第三種檔案名,即Makefile。因為第一個字母是大寫,通常被列在一個目錄的檔案清單的最前面。

Makefile檔案包含一些規則,這些規則主要是描述哪些檔案(稱為target目标檔案,注意,不是指編譯時産生的目标檔案)是從哪些别的檔案(稱為dependency依賴檔案)中産生的,以及用什麼指令(command)來執行這個過程。

依靠這些資訊,make會對磁盤上的檔案執行檢查,如果目标檔案的生成或被改動的時間(稱為時間戳)至少比它的一個依賴檔案還舊的話,make就執行相應的指令,以更新目标檔案。目标檔案不一定是最後的可執行檔案,可以是任何一個中間檔案,并可以作為其他目标檔案的依賴檔案。

最簡單的Makefile檔案如下:

hello:hello.c
    gcc -o hello hello.c
clean:
    rm -f hello
           

将上述4行存入Makefile檔案(注意必須以Tab鍵縮進第2、4行,不能以空格縮進),儲存經目前工作目錄,然後直接執行make指令即可編譯程式,執行“make clean”即可清除編譯出來的結構。

一個簡單的Makefile檔案包含一系列的“規則”,規則一般是用來解釋怎樣和 何時重建目标,其樣式如下:

目标(target)...:依賴(prerequiries)...
<tab>指令(command)
           

目标(target)通常是要生成的檔案的名稱,可以是可執行檔案或OBJ檔案,也可以是一個執行的動作名稱,諸如“clean”。

依賴是用來産生目标的材料(比如源檔案),一個目标通常有幾個依賴。

指令是産生目标是執行的動作,一個給i則可以含有幾個指令,每個指令占一行。

注意:每個指令行前面必須是一個Tab字元,即指令行第一個字元是Tab,這是容易出錯的地方。

要想完整地了解Makefile的規則請參考《GNU Make 使用手冊》,也下面僅可以參看《跟我一起寫makefile》連結:https://pan.baidu.com/s/1VZUmMHwia6x0F1X--qybfQ 提取碼:r3a7

給出一個Makefile的模闆,一般的中小型工程可照此改寫。

# Project: pattern
CC        = gcc 
Target    = pattern
SRC_DIRS  = ./source ./com ./include ./westWorldWithWoman


SRC_FILE  = $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
OBJ       = $(patsubst %.c,%.o,$(subst /,\,$(SRC_FILE))) 
LINKOBJ=$(OBJ)

LIBS     = -L"D:\MinGW64\lib" -L"D:\MinGW64\x86_64-w64-mingw32\lib" -static-libgcc -g3
INCS     = -I"D:\MinGW64\include" -I"D:\MinGW64\x86_64-w64-mingw32\include"  -I"C:\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include"

CFLAGS   = $(INCS) -g3 -D__DEBUG__ 
RM       = rm -f
 
 
.PHONY: all all-before all-after clean clean-custom exam
 
all: all-before $(BIN) all-after
 
clean: clean-custom
	${RM} $(Target) $(OBJ) 
 
$(Target): $(OBJ)
	$(CC) $(LINKOBJ) -o $(Target) $(LIBS)
$(OBJ):%.o:%.c
	$(CC) -c $< -o [email protected] $(CFLAGS)
           

第2行表示編譯的工具為gcc

第3行表示編譯出的可執行檔案名

第4行表示源檔案所在的目錄

第7行利用make定義的函數,從原檔案中搜尋出所有的源檔案

第8行利用make定義的函數,從源檔案中列出所有的OBJ檔案

第9行表示需要連接配接的目标檔案

第11行定義了編譯時連接配接的庫檔案

第12行添加頭檔案了的搜尋路徑清單

第14行定義聲明了了編譯選項:包含的頭檔案,關閉了優化選項,定義了宏DEBUG

第15行定義一個了變量

第18行聲明了僞目标

第20行定義了all的規則

第22-23行定義clean目标規則:清除所有的OBJ檔案及編譯出的可執行檔案

第25-26行定義了可執行檔案的生成規則

第27-28行定義了OBJ檔案的生成規則

一般我們隻需要改3、4量行。

2.5 開發環境的建立

2.5.1主機與目标闆結合的交叉開發模式

開發PC機上的軟體時時,可以直接在PC機上編輯、編譯、調試軟體,最終釋出的軟體也在PC機上運作。對于嵌入式開發,最初的嵌入式裝置是一個空白的系統,需要通過主機為它建構基本的軟體系統,并燒寫到裝置中;另外,嵌入式裝置的資源一般并不足以開發軟體,是以需要用到交叉開發模式:在主機上編輯、編譯軟體,然後再目标闆上運作、驗證程式。

主機指PC機,目标闆指嵌入式裝置。

注意:目前市面上的卡片機,如樹莓派等已經可以看成是一個完整的計算機系統,軟體可以直接再目标闆上開發,可以不用交叉開發模式。

進行嵌入式Linux開發時一般可分為以下4個步驟:

(1)在主機編譯bootloader,讓後通過JATG燒寫如裝置。

通過JTAG接口燒寫程式的效率非常低,它适用于燒寫空白裝置。為友善開發,通常選用具有序列槽傳輸、網絡傳輸、燒寫Flash功能的Bootloader(如uboot),它可以快速地從主機擷取可執行代碼,然後燒入單闆,或直接運作。

(2)在主機上編譯嵌入式Linux核心,通過Bootloader燒入裝置,或直接運作。

一個可以在單闆上運作的嵌入式Linux核心是繼續後續開發的基礎,為友善調試,核心應該支援網絡檔案系統(NFS),即将應用程式放在主機上,單闆啟動嵌入式Linux核心後,通過網絡來擷取程式,然後運作。

(3)在主機上制作嵌入式根Linux檔案系統,通過Bootloader燒入裝置,或直接運作。

對于作業系統來說,檔案時至關重要的。核心啟動的最後步驟是挂載根檔案系統,包含init程序、shell、檔案系統、網絡系統等的工具集、系統配置檔案和連接配接庫等。在嵌入式系統中,檔案存儲的媒介通常時Flash(閃存)。如何在flash上建立高速、可靠、穩定、易于維護、可長期使用的檔案系統一直是嵌入式系統的一個熱門話題。按照不同類型的Flash的特點,出現了很多專門正對Flash的檔案系統,如jffs,yaffs,cramfs等。這些檔案系統需要燒寫單闆,在開發階段一般采用NFS檔案系統以避免頻繁燒寫。

另外嵌入式系統資源受限,其工具集一般采用BusyBox來生成,以減少自己的體積。

(4)在主機上編譯各類應用程式,并加入檔案系統,經驗證後燒入裝置。

在開發階段,主機上編譯的應用程式一般是嵌入式裝置啟動核心以後通過NFS運作它們,得到驗證以後,将其加入根檔案系統,然後随檔案系統一起燒入裝置。若嵌入式裝置的檔案系統不采用NFS,則應用程式可以通過網絡、序列槽,甚至是U盤等,拷貝到裝置上(前提是根檔案系統采用可讀寫檔案系統),也可以通過網絡,以NFS形式将應用程式挂載到嵌入式裝置上。

另外有時嵌入式系統需要一個圖形使用者界面,如Qtopia、MiniGUI等,這時也需要在這一步進行移植和配置。

以上的4個步驟是相對獨立的,每一步都可以相對獨立開發和燒寫。目前市面上的主流開發闆,其前3個步驟一般已經做好,第4步的GUI也有可能做好了,一般的開發者可以跳過,若不滿足要求,開發者可以重新建構和燒寫。

另外有部分晶片,比如支援從SD卡等方式啟動,可以将uboot、核心、檔案系統等燒寫進SD卡中,制成“啟動盤”,開發完成後将SD卡内容在燒寫入裝置,其本質和上述過程實際上一緻的,這種方式以samsung系列晶片為代表。

2.5.2軟體環境的建構

一般說來,不管是開發主機應用程式,還是嵌入式應用程式,我們采用的工具都是GCC,使用的方法都是一樣的,隻是生成的機器碼不一樣,主機是針對x86系統的,而嵌入式裝置一般針對的是諸如ARM,powerpc等。主機上一般已經安裝了gcc工具,我們還需要安裝另一套針對目标闆的gcc工具(有時也稱為工具鍊),包括gcc, gdb, ld, as, objcopy,objdump及有關庫等,這些可在工具在主機上運作,但生成目标機格式的機器代碼。

剛開始學習時,建議使用已經做好的工具鍊,當對系統很熟悉後,或系統資源受限,使用者也可以自己制作、編譯自己的工具鍊。

使用制作好的工具鍊

使用以下的指令解壓到

tar -xjf arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz
           

2.6常用工具的使用

2.6.1超級終端

基于Linux的嵌入式系統需要一個控制終端,這個終端通常是序列槽終端,一般我們在PC機上通過一個終端軟體通過序列槽與目标闆相連。盡管很多的教材推薦使用的終端軟體為minicom(Linux系統下的序列槽終端),secureCRT等序列槽終端,我還是推薦大家使用windows下的超級終端,原因就是超級終端使用簡單,而我們大家大部分習慣使用的主機系統還是windows系統。很遺憾的是在win7以前超級終端是系統自帶的小工具,之後就要大家下載下傳了。https://pan.baidu.com/s/17z3HGx2lJPhYaD5oYa_tVQ 提取碼:cz1h

需要注意的是序列槽通訊的參數一般波特率為115200 ,格式為8N1,無資料流控制。

2.6.2tftp伺服器

tftp用于通過網絡下載下傳和上傳檔案連結:https://pan.baidu.com/s/1TgFfrQRyXxYkBWo6LVKuKw 提取碼:xvzz

需要注意tftp和開發闆應該在同一個子網内。在windows查詢本機的ip位址方法為:

ipconfig
           

開發闆可以通過網線直連到PC機上,也可以PC機和開發闆都連接配接到同一個路由器上,建議采用第二種方式,不過要注意位址沖突,尤其是在實驗室,多個人同時需要設定時。

開發闆的ip位址根據不同的階段有不同的設定方式,在uboot下載下傳模式下的方式可參考下一節環境參數設定内容,linux啟動以後使用ifconfig指令進行設定。

2.6.3U-boot的使用

核心和檔案系統的更新、燒寫,啟動參數的配置等都要借助bootloader來進行,一般市面購買的開發闆其中的bootlaoder已經燒寫,這給開發人員以極大的便利。一些簡單程式,尤其是裸機程式,通過JTAG進行燒寫運作太複雜了,我們這時就可以借助uboot功能進行學習,這對于初學者非常有利。

将開發闆通過序列槽連接配接到主機,啟動主機的序列槽終端(如超級終端,secureCRT等),設定好通訊參數 (一般波特率為115200 ,格式為8N1)上電,按任意鍵,即進入U-boot控制界面,可以運作各種指令,比如下載下傳檔案到記憶體,擦除、讀寫Flash,運作記憶體、Nor Flash、Nand Flash中的程式,檢視、修改、比較記憶體在的資料等。U-boot接收的資料都是16進制,輸入時可以省略字首0x,0X。

(1)幫助指令help

運作help指令可以看到U-boot中所有指令的作用,如果要檢視某個指令的使用方法,運作“help 指令名”,比如“help boot m"。可以使用”?“來代替help,比如直接輸入”?“、”?bootm“。

(2)環境變量指令

printenv :指令列印差別環境變量

printenv name1 name2...:列印名字為name1、name2、...的環境變量

setenv name  value :設定名字為name的環境變量的值為value

setenv  name :删除名字為name的環境變量

saveenv :上面的設定、删除操作隻是在記憶體中進行,saveenv将更改後的所有環境變量寫入Flash中

常用環境變量清單

bootdelay 執行自動啟動(bootcmd中的指令)的等候秒數 

baudrate 序列槽控制台的波特率 

bootfile 預設的下載下傳檔案名 

bootargs 傳遞給Linux核心的啟動參數 

bootcmd 自動啟動時執行指令 

stdin 标準輸入裝置,  一般是序列槽  

stdout 标準輸出,  一般是序列槽,也可是LCD(VGA)

stderr   标準出錯,一般是序列槽,也可是LCD(VGA)

serverip TFTP伺服器端的IP位址 

ipaddr 本地的IP位址  

ethaddr 以太網的MAC位址 

netmask 以太網的網絡掩碼                                                                                                                                                 gatewayip 以太網的網關

(3)啟動指令

不帶參數的boot 、bootm指令都是執行環境變量bootcmd所指定的目錄

bootm[addr [arg...]]指令啟動存放在位址addr處的U-boot格式的映像檔案(使用u-boot目錄tools下的mkimage工具制作得到)

go addr [arg...]與bootm指令類似,啟動存放在位址addr處的二進制檔案,[arg...]表示參數

(4)序列槽下載下傳指令

loads [ off ] 通過序列槽,下載下傳S-Record格式檔案到off位置

loadb [ off ] [ baud ]通過序列槽,以baud速率,下載下傳binary到off位置(即:kermit protocol)。loadb指令可以通過序列槽線下載下傳二進制格式檔案。

loady [load address] [baud rate]支援Ymodem協定

(5)網絡指令

tftp addr filename 将檔案下載下傳到addr位置 //pc端需配置好tftp伺服器

nfs addr pc端IP:/帶路徑的檔案名   //pc端需配置好nfs伺服器

ping     ip  //檢測網絡是否通

執行個體:使用u-boot來執行程式

使用JTAG燒寫程式過程非常緩慢,如果用uboot來燒寫Flash效率會高很多,我們可以燒寫二進制檔案到Flash中,或直接下載下傳到記憶體中,然後使用go指令執行它,不需要将二進制檔案制作成u-boot格式(bootm啟動uboot格式程式)。假設有一個程式的二進制可執行檔案test.bin,連接配接位址為0x30000000.

1)使用網絡下載下傳

首先将它放在主機的tftp或nfs目錄下,確定已經開啟tftp或nfs服務;然乎将它下載下傳到記憶體0x30000000處,最後使用go指令執行它,如下所示:

tftp 0x30000000 test.bin 或nfs 0x30000000 192.168.1.55:/work/nfs_root/test.bin
go 0x30000000
           

2)使用序列槽下載下傳

loady 0x30000000 test.bin
go 0x30000000
           

執行個體:設定核心啟動參數

控制終端為序列槽,波特率為115200,檔案系統為jffs2

set bootargs 'console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=jffs2'
saveenv
           

表示控制台為ttys0,波特率為115200,根檔案系統的節點為/dev/mtblock2 類型為jfffs2

setenv bootargs 'console=ttyS0 root=/dev/nfs rw nfsroot=192.168.1.22:/nfsroot/rootfs ip=192.168.1.55 '
saveenv
           

表示控制台為ttys0,根檔案系統的節點為/dev/nfs nfs檔案系統,可讀可寫,該檔案系統位于主機192.168.1.22  的/nfsroot/rootfs檔案夾,目标闆的ip位址為192.168.1.55

繼續閱讀