交叉編譯、軟硬鏈接

什么是交叉編譯?交叉編譯是一個行為,是在一個平臺上生成另一個平臺上的可執行代碼。

  • 本地編譯:本地編譯可以理解為,在當前編譯平臺下,編譯出來的程序只能放到當前平臺下運行。平時我們常見的軟件開發,都是屬于本地編譯:比如,我們在 x86 平臺上,編寫程序并編譯成可執行程序。這種方式下,我們使用 x86 平臺上的工具,開發針對 x86 平臺本身的可執行程序,這個編譯過程稱為本地編譯。
  • 交叉編譯:交叉編譯可以理解為,在當前編譯平臺下,編譯出來的程序能運行在體系結構不同的另一種目標平臺上,但是編譯平臺本身卻不能運行該程序:比如,我們在 x86 平臺上,編寫程序并編譯成能運行在 ARM 平臺的程序,編譯得到的程序在 x86 平臺上是不能運行的,必須放到 ARM 平臺上才能運行。
  • 宿主機(host) :編輯和編譯程序的平臺,一般是基于X86的PC機,通常也被稱為主機。
  • 目標機(target):用戶開發的系統,通常都是非X86平臺。host編譯得到的可執行代碼在target上運行。
  • prefix:交叉編譯器的安裝位置。
  • 比如:我們在windows上面編寫51和32的代碼,并編譯成可執行代碼,如xx.hex,是在C51上面運行不是在windows上面運行,交叉編譯的發生在keil(集成環境上面)。同樣:我們在ubuntu(linux)上面編寫樹莓派的代碼,并編譯成可執行代碼,如xx.out,是在樹莓派上面運行不是在ubuntu(linux)上面運行。

為什么要交叉編譯?

  • 有時是因為目的平臺上不允許或不能夠安裝我們所需要的編譯器,而我們又需要這個編譯器的某些特征

  • 有時是因為目的平臺上的資源貧乏,無法運行我們所需要編譯器

  • 有時又是因為目的平臺還沒有建立,連操作系統都沒有,根本談不上運行什么編譯器。

  • 在項目的起始階段,目的平臺尚未建立,因此需要做交叉編譯,以生成我們所需要的bootloader(啟動引導代碼)以及操作系統核心

  • 其次,當目的平臺能啟動之后,由于目的平臺上資源的限制,當我們編譯大型程序時,依然可能需要用到交叉編譯。

  • Speed: 目標平臺的運行速度往往比主機慢得多,許多專用的嵌入式硬件被設計為低成本和低功耗,沒有太高的性能

  • Capability: 整個編譯過程是非常消耗資源的,嵌入式系統往往沒有足夠的內存或磁盤空間

  • Availability: 即使目標平臺資源很充足,可以本地編譯,但是第一個在目標平臺上運行的本地編譯器總需要通過交叉編譯獲得

  • Flexibility: 一個完整的Linux編譯環境需要很多支持包,交叉編譯使我們不需要花時間將各種支持包移植到目標板上

交叉編譯工具鏈(交叉編譯器)是什么?一般由編譯器、連接器、解釋器和調試器組成,就是為了編譯、鏈接、處理和調試跨平臺體系結構的程序代碼。

要進行交叉編譯,我們需要在主機平臺上安裝對應的交叉編譯工具鏈(cross compilation tool chain),然后用這個交叉編譯工具鏈編譯我們的源代碼,最終生成可在目標平臺上運行的代碼。常見的交叉編譯例子如下:

  • 在Windows PC上,利用ADS(ARM開發環境),使用armcc編譯器,則可編譯出針對ARM CPU的可執行代碼
  • 在Linux PC上,利用arm-linux-gcc編譯器,可編譯出針對Linux ARM平臺的可執行代碼
  • 在Windows PC上,利用cygwin環境,運行arm-elf-gcc編譯器,可編譯出針對ARM CPU的可執行代碼
  • 樹莓派有flash和運行內存(RAM隨機存儲器),但是樹莓派有時因為目標平臺沒有建立,連操作系統都沒有,根本談不上編譯器。因此需要做交叉編譯,以生成平臺至少所需要的:bootloader(啟動引導代碼) 以及 操作系統核心

交叉編譯工具鏈的安裝:

不同的平臺用的交叉比編譯器不同,就像我們在用keil編譯51的代碼時要選擇對應的芯片,編譯32的代碼時也要選擇對應的芯片,這其實都是在間接地選擇了編譯器。如果目標機是樹莓派,那么我們將會用到樹莓派的交叉編譯工具鏈。

  • 首先下載樹莓派的交叉編譯工具鏈,下載地址點這里,點擊download下載即可。
    在這里插入圖片描述

  • 交叉編譯工具鏈的安裝有兩種方法:①臨時有效 ②永久有效

  • 臨時有效:將路徑加入PATH環境變量(將命令加入終端,使命令使用更加方便,不用敲很長的路徑),echo $PATH 顯示當下的環境變量,然后使用指令:export PATH=設置新的環境變量
    在這里插入圖片描述

  • 永久有效:vi .bashrc打開工作目錄下的.bashrc (隱藏文件),用來配置命令終端的,每次啟動終端都會執行這個腳本。將上面的配置命令添加在這個文件的最后一行即可。然后source /home/CLC/.bashrc使用這個指令是設置立即生效
    在這里插入圖片描述

  • 下面記錄在ubuntu上面安裝樹莓派的交叉編譯工具,首先在上方的那個網址下載交叉編譯工具到與虛擬機共享的文件夾,然后將壓縮包拷貝到虛擬機使用指令cp /mnt/hgfs/Sharefromwindows/tools-master.zip .
    在這里插入圖片描述

  • 然后使用指令進行解壓:unzip tools-master.zip,解壓完成后會出現tool-master這個文件夾,進入這個文件夾,可以看到arm-bcm2708,所需要的交叉編譯工具就是在這里,進入這個文件夾gcc-linaro-arm-linux-gnueabihf-raspbian-x64因為我的虛擬機(宿主機)是64位的所以選擇這個文件夾,如果是32位的用gcc-linaro-arm-linux-gnueabihf-raspbian這個文件夾夾里面的。進入自己對應的文件夾,然后進入bin目錄下,可以看到很多綠色的可執行文件
    在這里插入圖片描述

  • 我們要用的交叉編譯工具就是淺藍色的那個軟連接(相當于windows下面的快捷方式)arm-linux-gnueabihf-gcc,可以使用指令:./arm-linux-gnueabihf-gcc -v查看交叉編譯1器的版本相關信息,和查看gcc版本的指令類似:gcc -v

  • 在ubuntu里面編譯一個可執行代碼,可以通過file testone來查看文件的屬性,如下圖所示:x86-64 表示只能運行在64位的X86的機子上,這樣在可執行程序就不能在樹莓派上面跑。
    在這里插入圖片描述

  • 如果想要在樹莓派上面運行,就要使用指令編譯:arm-linux-gnueabihf-gcc testone.c -o testone這樣生成的testone就可以在ARM平臺上面運行。
    在這里插入圖片描述

  • 可以使用指令:scp testone pi@192.168.43.136:/home/pitestone是要移動到樹莓派的可執行文件,192.168.43.136是樹莓派的ip地址,冒號后面是將文件放到樹莓派的哪一個位置。可以看到綠色的可執行文件testone然后可執行。
    在這里插入圖片描述

  • 如果將一個只能在x86運行的代碼,移動到樹莓派上面,則會報錯:-bash: ./testone: cannot execute binary file: Exec format error表示不能解析這個二進制文件。同樣我們可以將項目二代碼的服務端移到樹莓派上面運行,客戶端在虛擬機上面運行。

客戶端:
在這里插入圖片描述
服務端:
在這里插入圖片描述

帶WiringPi庫的代碼如何在上位機進行交叉編譯?

  • 需要先在宿主機上面(這里是ubuntu)安裝wiringPi庫

  • wiringPi庫百度網盤:鏈接:https://pan.baidu.com/s/1cPIt-xZLye1DAQjq2yKzeg提取碼:35vt

  • 進入解壓后的WiringPi文件夾,然后打開INSTALL這個文件夾,查看如何下載,這里顯示直接執行build文件即可(編譯wiringPi庫生成動態庫,編譯時需要鏈接,但是它是使用的gcc編譯器,編譯出來庫是只能運行在x86平臺上的),然后將會下載到/usr/local/lib這個目錄下,然后可以使用指令:arm-linux-gnueabihf-gcc demo.c -I /home/fhn/wringPi/WiringPi/wiringPi -lwiringPi但是會發現報錯,是因為鏈接wiringPi庫的時候是鏈的/usr/local/lib這個目錄下的libwiringPi.so
    在這里插入圖片描述

  • 但是file libwiringPi.so去查看這個文件的屬性,發現這個文件的屬性是在x86上面運行的,然而我們需要在ARM上面運行,所以是不兼容的,會報錯:/home/fhn/arm-tool/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lwiringPi collect2: error: ld returned 1 exit status
    在這里插入圖片描述

  • 正常情況下我們先要交叉編譯wiringPi庫,編譯出適合樹莓派的庫,這時候交叉編譯可執行程序的時候,鏈接庫的格式也是正確的。那么我們可以將樹莓派的wiringPi庫拿到虛擬機,libwiringPi.so就這個動態庫,但是這是個軟連接(相當于快捷方式)
    在這里插入圖片描述

  • 使用指令:ls -l |grep libwiringPi.so可以看出這個文件是指向libwiringPi.so.2.50這個動態庫的。所以我們需要將這個動態庫發送到ubuntu里面,使用指令:scp libwiringPi.so.2.50 fhn@192.168.43.112:/home/fhn/wringPi/WiringPi,就算將軟連接發送到ubuntu也不會指向這個動態庫,還需要我們自己創建動態庫。如果傳輸過程中出現錯誤:ssh: connect to host 192.168.43.112 port 22: Connection refused lost connection表示ubuntu沒有安裝ssh,在ubuntu里面下載ssh即可:sudo apt-get install ssh
    在這里插入圖片描述

  • 使用指令:ln -s libwiringPi.so.2.50 libwiringPi.so 創建軟連接,下面有詳細的講解軟硬鏈接,創建軟連接后使用指令:arm-linux-gnueabihf-gcc hc.c -I /home/fhn/wringPi/WiringPi/wiringPi -L . -lwiringPi -o hc進行編譯,其中:-I /home/fhn/wringPi/WiringPi/wiringPi是鏈接的wiringPi庫的頭文件,-L是指定動態庫在當前目錄下去查找庫文件。

  • 學習指令:grep gcc * -nir在所有文件里面查找gcc字眼,n表示顯示行號、i表示不區分大小寫、n表示遞歸查找、*表示在所有文件里面去查找。

硬盤:

在介紹硬鏈接和軟鏈接之前,首先介紹下硬盤相關的知識,主要是了解下 inode 。

  • 硬盤設備是由大量的扇區組成的。以 MBR 分區為例。每個扇區的容量為 512 字節。其中第一個扇區最重要。它里面保存著主引導記錄與分區表信息。就第一個扇區來講,主引導記錄需要占用 446 字節,分區表為 64 字節,結束符占用 2 字節。其中分區表每記錄一個分區信息就需要 16 字節,這樣一來,最多就只有4個分區信息可以寫到第一扇區中,這4個分區就是4個主分區。

  • 第一個扇區最多只能創建出4個分區 ?
    為了解決分區個數不夠的問題,可以將第一個扇區的分區表中16個字節(原本要寫入主分區信息)的空間(稱之為擴展分區)拿出來指向另一個分區。

  • 也就是說,擴展分區并不是一個真正的分區,而像是有一個占用 16
    字節的分區表空間的指針,一個指向另外一個分區的指針。這樣一來,用戶一般會選擇使用3個主分區+1個擴展分區的方法,然后在擴展分區中創建無數個邏輯分區,從而來滿足多分區(大于4個)的需求。

  • Linux 系統中有一個名為 superblock 的 “硬盤地圖”。 Linux 并不是把文件內容直接寫入到 superblock 中,而是在里面記錄著整個文件系統的信息。Linux 把每個文件的權限與屬性記錄在 inode("索引節點:index node ") 中,而且每個文件占用一個獨立的 inode 表格,該表格的默認大小為 128 字節。里面記錄著如下信息 :文件的訪問權限(read、write、execute)該文件的所有者與所屬組(owner、group)該文件的大小(size)該文件的創建或內容修改時間(ctime)該文件的最后一次訪問時間(atime)該文件的修改時間(mtime)文件的特殊權限(SUID、SGID、SBIT)該文件的真實數據地址(point)

  • 在 Linux 系統中 ,inode 號才是文件的唯一標識而非文件名。文件名只是為了方便人們的記憶和適用。
    在這里插入圖片描述

  • 如上述命令 “ls -li” 結果中的第一列就是文件的 inode 號。系統是通過 inode 號尋找正確的文件數據塊。

  • 文件的實際內容則保存在 block 中(大小可以是 1KB、2KB 或 4KB),一個 inode 的默認大小為 128KB (在 Ext3 文件系統中),記錄一個 block 則消耗 4B 。當文件的 inode 被寫滿后,Linux 系統會自動分配出一個 Block 塊,專門用于像 innode 那樣記錄其他 block 塊的信息,這樣能把各個 block 塊的內容串到一起,就能夠讓用戶讀到完整的文件內容了。

  • 對于存儲文件內容的的 Block 塊,有以下兩種常見情況,以 4KB 的 block 大小為例說明情況 : 文件很小(1KB) , 但依然會占用一個 block ,因此會潛在占用 3kb。 文件很大(5kb) , 那么會占用兩個 block。

總結:

  • superBlock : 存儲整個文件系統的信息。
  • inode : 存儲文件的權限與屬性。
  • data block : 真正存儲文件內容。

軟硬連接:
在 Windows 系統中,快捷方式是指向原始文件的一個鏈接文件。可以讓用戶從不同的位置來訪問原始的文件;原文件一旦被刪除或剪切到其他地方后,會導致鏈接文件失效。但是在 Linux 系統中,"快捷方式"就不太一樣 ,在 Linux 系統存在硬鏈接和軟鏈接兩種文件。

  • 硬鏈接(hard link) : 可以將它理解為一個 “指向原始文件 inode(儲存原始文件信息) 的指針”,系統不為它分配獨立的 inode 和 文件。所以,硬鏈接文件與原始文件其實是同一個文件,只是名字不同。我們每添加一個硬鏈接,該文件的 innode 連接數就會增加 1 ; 而且只有當該文件的 inode 連接數為 0 時,才算徹底將它刪除。因此即便刪除原始文件,依然可以通過硬鏈接文件來訪問。需要注意的是,我們不能跨分區對文件進行鏈接。可以使用指令:ln fileName newFileName為原文件fileName 創建硬鏈接newFileName
  • 軟鏈接(symbolic link) : 等同于 Windows 系統下的快捷方式。僅僅包括所含鏈接文件的路徑名字。因此能鏈接目錄,也能跨文件系統鏈接。但是,當刪除原始文件后,鏈接文件也將失效。
  • 總結:硬鏈接是指向原始文件 inode的指針,而軟連接則是僅僅包括所含鏈接文件的路徑名字

ln - 新建鏈接:ln 用于創建軟或硬鏈接。
在這里插入圖片描述

  • 軟鏈接示例 :ln -s helloWorld sHelloWorld
  • 硬鏈接示例 :ln helloWorld hardHelloWorld

問題:

  • 硬鏈接占據空間嗎 ? 比如我有一個 1G 的文件,現在我給這個文件建了一個硬鏈接。那么會占據 2G 空間嗎?
    不會,之前我們說了硬鏈接是一個指針或者說是文件的引用,只占一點點空間,軟連接不占用磁盤空間。

軟硬連接參考博文、交叉編譯參考博文、軟硬連接精彩博文、交叉編譯工具鏈下載的另一種方法

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272162.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272162.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272162.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

掃地機器人狗毛_掃地機器人:我是清理狗毛的!不是清理狗屎的!

原標題:掃地機器人:我是清理狗毛的!不是清理狗屎的!掃地機器人可以清潔地面和角落里的垃圾,對于滿是毛毛的鏟屎官家庭來說,簡直就是福音吶!不過最近,槽點卻有點多:家里買…

Linus下安裝maven

下載maven安裝包 wget http://mirror.bit.edu.cn/apache/maven/binaries/apache-maven-3.2.2-bin.tar.gz 解壓 tar -zxvf apache-maven-3.2.2-bin.tar.gz 配置maven環境變量 查看maven解壓后安裝包目錄 vi /etc/profile 進入最底部,按insert,添加環境變量&#x…

linux內核開發基礎(linux內核源碼、樹莓派源碼編譯、SD卡掛載)

首先下載樹莓派linux內核源碼: 下載網址:https://github.com/raspberrypi/linux在樹莓派使用指令:uname -r查看當前樹莓派的版本號,然后選擇對應的linux內核版本號進行下載。 將linux內核源碼從共享文件夾拷貝到SYSTEM文件夾&am…

Linux實時查看進程命令top筆記

top命令是Linux下常用的性能分析工具,能夠實時顯示Linux系統中各個進程的資源占用狀況,類似于Windows系統的任務管理器功能。 top命令的語法格式: top [-] [d] [p] [q] [c] [C] [S] [s] [n] 常用參數說明 d 指定每兩次屏幕信息刷新之間的時間…

C#基礎之Equals和Dispose

1.equal()和運算符的區別 由于C#中有值類型和引用類型,那么相等也分為值相等和引用相等。先來看一個值類型簡單的例子,順便也寫了string類型的比較。 static void Main(string[] args){int n1 1;int n2 1;Console.WriteLine(n1n2);Console.WriteLine(n…

mysql 時間chuo格式化_Mysql時間戳與時間格式轉換問題匯總

一、時間戳的定義時間戳指格林威治時間1970年01月01日00時00分00秒起至現在的總秒數。二、時間格式轉時間戳的方法使用unix_timestamp函數,如下:SELECT UNIX_TIMESTAMP();//返回當前時間戳SELECT UNIX_TIMESTAMP(2017-12-16 17:29:56) AS t; //返回指定時…

文件系統(文件系統目錄結構、磁盤分區、虛擬文件系統)、linux內核結構框圖

什么是文件系統? 常規認知就是根目錄下那些文件,但其實并不是那樣。文件系統是操作系統用于明確存儲設備(常見的是磁盤,也有基于NAND Flash的固態硬盤)或分區上的文件的方法和數據結構;即在存儲設備上組織…

dockerq啟動報錯(iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9876 -j DNAT --t

docker啟動報錯 (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9876 -j DNAT --to-destination 172.17.0.2:9876 ! -i docker0: iptables: No chain/target/match by that name. 解決方案:重啟docker systemctl restart docker

Linux進程終止命令kill或kill all?筆記

在linux命令下,如果需要終止某個進程,可以使用kill或者killall等命令來實現。終止命令的原理都是向linux內核發送一個系統操作的信號以及某個進程的ID,然后系統內核會根據指定的進程ID進行相應的處理。 kill命令典型的用法:首先使…

linux驅動(驅動編譯、字符設備驅動框架、交叉編譯樹莓派驅動、樹莓派驅動本地編譯)

什么是驅動: 驅動就是對底層硬件設備的操作進行封裝,并向上層提供函數接口。 設備分類: linux系統將設備分為3類:字符設備、塊設備、網絡設備。 字符設備:指只能一個字節一個字節讀寫的設備,不能隨機讀取…

docker啟動報錯 ?(iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9876 -j DNAT --

docker啟動報錯 : (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9876 -j DNAT --to-destination 172.17.0.2:9876 ! -i docker0: iptables: No chain/target/match by that name. 解決方案: systemctl restart docker

第一個Spark程序

1、Java下Spark開發環境搭建(from http://www.cnblogs.com/eczhou/p/5216918.html)1.1、jdk安裝安裝oracle下的jdk,我安裝的是jdk 1.7,安裝完新建系統環境變量JAVA_HOME,變量值為“C:\Program Files\Java\jdk1.7.0_79”…

arduino判斷是否連接串口_Arduino-串口通信

Serial”系列函數,所以我們要對其有所了解,下面介紹幾個常“Serial”函數。1、Serial.begin()—設置串行每秒傳輸數據的速率(波特率)。在同計算機通訊時,使用下面這些值:300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400…

最詳細的docker安裝rocketMQ教程來了

RocketMQ是一款分布式、隊列模型的消息中間件,是由阿里巴巴設計的,具有以下特點: 支持嚴格的消息順序 支持Topic與Queue兩種模式 億級消息堆積能力 比較友好的分布式特性 同時支持Push與Pull方式消費消息 歷經多次天貓雙十一海量消息考驗…

樹莓派IO口驅動代碼的編寫、微機總線地址、物理地址、虛擬地址、BCM2835芯片手冊

地址總線: 百度百科解釋: 地址總線 (Address Bus;又稱:位址總線) 屬于一種電腦總線 (一部份),是由CPU 或有DMA 能力的單元,用來溝通這些單元想要存取(讀取/寫入&#xff…

奪命雷公狗---DEDECMS----26dedecms面包屑導航的實現

我們在很多項目里面都會用到面包屑導航,而dedecms里面也是給我們封裝好面包屑導航的了,如下圖所示: 在dede里面實現面包屑導航主要用到{dede:field.position/}標簽,我們首先來修改下article_movie.htm內容頁的模版文件: 我們修改成…

rust油桶用什么打_草莓用什么膨大素好?草莓膨大劑什么時間打?草莓用什么肥料膨大...

農資365公眾號,了解更多生根、根腐、重茬、土傳、枯黃萎、根爛病、防治根結線蟲、微生物菌肥、膨大坐果、抗病增產的防治方法!草莓含有豐富的營養,并且種植效益較高,其種植范圍也比較廣。草莓種植期間有很多因素影響草莓果實膨大&…

docker安裝kafka,超級簡單的

簡介 kafka是一個分布式消息隊列。具有高性能、持久化、多副本備份、橫向擴展能力。生產者往隊列里寫消息,消費者從隊列里取消息進行業務邏輯。一般在架構設計中起到解耦、削峰、異步處理的作用。 kafka對外使用topic的概念,生產者往topic里寫消息&…

Linux中常見的環境變量筆記

1、變量:BASHBash Shell的全路徑比如:echo $BASH2、變量:BASH_VERSIONBash Shell的版本號3、變量:EUID記錄當前用戶的UID。root用戶值為0。4、FUNCNAME在用戶函數體內部,記錄當前函數體的函數名。5、變量:H…

消防信號二總線有沒電壓_春曉161#地塊人防工程消防電源監控系統的設計與應用...

涂志燕安科瑞電氣股份有限公司,上海 嘉定 201801;摘要:本文簡述了消防設備電源的組成原理,分析了消防設備電源監控系統在應用中的設計依據和相關規范。通過安科瑞消防設備電源監控系統在春曉161#地塊項目的實例介紹,闡…