在编译GCC之前,先介绍一个概念——bootstrap。
bootstrap就是自己编译自己,或者说用GCC编译GCC本身。GCC的bootstrap分三个阶段,具体如下:
- 用系统提供的编译器编译GCC源代码,得到GCC编译器;
- 用步骤1得到的GCC编译同一份GCC源代码,又得到一套GCC编译器
- 用步骤2得到的GCC编译同一份GCC源代码,第三次得到一套GCC编译器
最后比较步骤2和步骤3得到的两套编译器是否相同,如果相同,则bootstrap成功;否则失败。
在编译GCC之前,先介绍一个概念——bootstrap。
bootstrap就是自己编译自己,或者说用GCC编译GCC本身。GCC的bootstrap分三个阶段,具体如下:
最后比较步骤2和步骤3得到的两套编译器是否相同,如果相同,则bootstrap成功;否则失败。
來源出處WIKI -> https://zh.wikipedia.org/wiki/%E5%87%BD%E5%BC%8F%E...
在電腦科學中,庫(英語:library)是用於開發軟體的子程式集合。庫和執行檔的區別是,庫不是獨立程式,他們是向其他程式提供服務的代碼。
庫連結是指把一個或多個庫包括到程式中,有兩種連結形式:靜態連結和動態連結,相應的,前者連結的庫叫做靜態庫後者的叫做動態庫。
靜態連結是由連結器在連結時將庫的內容加入到可執行程式中的做法。連結器是一個獨立程式,將一個或多個庫或目的檔(先前由編譯器或組譯器生成)連結到一塊生成可執行程式。
靜態連結的最大缺點是生成的執行檔太大,需要更多的系統資源,在裝入記憶體時也會消耗更多的時間。
動態連結,在執行檔裝載時或執行時,由作業系統的裝載程式載入庫。大多數作業系統將解析外部參照(比如庫)作為載入過程的一部分。在這些系統上,執行檔包含一個叫做import directory的表,該表的每一項包含一個庫的名字。根據表中記錄的名字,裝載程式在硬碟上搜尋需要的庫,然後將其載入到記憶體中預先不確定的位置,之後根據載入庫後確定的庫的位址更新可執行程式。可執行程式根據更新後的庫資訊呼叫庫中的函式或參照庫中的資料。這種類型的動態載入稱為裝載(load-time)時載入,被包括Windows和Linux的大多數系統採用。裝載程式在載入應用軟體時要完成的最複雜的工作之一就是載入時連結。
其他作業系統可能在執行時解析參照。在這些系統上,可執行程式呼叫作業系統API將庫的名字、函式在庫中的編號和函式參數一同傳遞。作業系統負責立即解析然後代表應用呼叫合適的函式。這種動態連結叫做執行時連結。因為每個呼叫都會有系統開銷,執行時連結要慢得多,對應用的效能有負面影響。現代作業系統已經很少使用執行時連結。
Hello.c:
#include <stdio.h>
int main ()
{
printf ("hello,world");
return 0;
}
在這裡先幫某些讀者解釋一下何謂「開發板」 。某些廠商,會把目前在嵌入式業界流行的 CPU,搭配上各式各樣的周邊,做成一塊電路板,賣給嵌入式教育市場,或有志學習嵌入式系統的學生,作為實驗平台之用。這種板子,我們就稱它為「開發板」、「評估版」。英文叫做「Evaluation Board」,或簡稱「EVB」。
其實這個名詞最早來自業界。一些想推廣自家產品的晶片商,為了展現產品優點,吸引下游系統廠商使用,會自己「兜」出一塊「Demo」用的板子。雖然把產品配合其它電路,把整個系統做到好,並非晶片廠商該做之事(有點撈過界,一口氣把下游廠商該做的電路整合工作全包了)。但為了吸引買家,不得不這麼做。這就是業界口中的「評估板(EVB)」、「開發板」、或「Demo Board」。
開發板為了展示主晶片的最大能耐,通常集合了最多的周邊電路。真正的產品,會把不需要的周邊拿掉,以減低成本。不過這種情況在嵌入式教育領域,就跟業界作法相反。每位老師無不希望拿到的板子上,有最多的周邊,能夠用一塊板子教所有課程。這就是為什麼一塊開發板會貴到讓同學買不下手的原因。
32位元環境涉及"ILP32"数据模型,是因为C数据类型为32位的int、long、指標。而64位元環境使用不同的資料模型,此时的long和指標已為64位元,故稱作"LP64"資料模型。
现今所有64位的类Unix平台均使用LP64数据模型,而64位Windows使用LLP64数据模型,除了指针是64位,其他基本类型都没有变。
TYPE LP32 ILP32 LP64 ILP64 LLP64
CHAR 8 8 8 8 8
SHORT 16 16 16 16 16
INT 16 32 32 64 32
LONG 32 32 64 64 32
Linux 下的終端機畫面不是只能換換背景而已,顯示出來的顏色也是能控制的。使用的顏色就像以前的DOS 時代,或者現在的BBS 顏色控制方式一樣。
以shell 的顯示為例,顯示的格式如下:
\033[ 亮度 ; 文字顏色 ; 背景顏色 m
文字內容………………
\033[0m
亮度是0 或1
文字及背景顏色有色碼有查 (以後附上),而背景顏色是可省略的。
[以上文章來自http://flykof.pixnet.net/blog/post/]
What is tty?
終端是一種字元裝置(Char Device),它有多種類型,通常使用tty(Teletype)來簡稱各種類型的終端設備。Teletype是最早出現的一種終端設備,很象電傳打字機(或者說就是),是由Teletype公司生產的。設備名放在特殊檔案目錄/dev/下,終端特殊設備檔案一般有以下幾種︰
1.串行端口終端(/dev/ttySn)
串行端口終端(Serial Port Terminal)是使用計算機串行端口連接的終端設備。計算機把每個串行端口都看作是一個字符設備。有段時間這些串行端口設備通常被稱為終端設備,因為 那時它的最大用途就是用來連接終端。這些串行端口所對應的設備名稱是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev /ttyS1)等,設備號分別是(4,0)、(4,1)等,分別對應於DOS系統下的COM1、COM2等。若要向一個端口發送數據,可以在命令行上把標 準輸出重定向到這些特殊檔案名上即可。例如,在命令行提示符下鍵入︰echo test > /dev/ttyS1會把單字”test”發送到連接在ttyS1(COM2)端口的設備上。
當然這些設備名稱不是固定的,標示設備最為重要的major number和minor number,然後是基於此的設備驅動程式。如:/dev/ttyAM0來代替/dev/ttyS0,/dev/ttyAM1來代替/dev/ttyS1。
2.偽終端(/dev/pty/)
转载感言:发现一篇还不错的文章,跟大家分享一下。该文简单介绍了Futex机制,并有一些简单的例子,浅显易懂。
Linux中的同步机制(一)--Futex引子
在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢?
1. 什么是Futex
Futex 是Fast Userspace muTexes的缩写,由Hubertus Franke, Matthew Kirkwood, Ingo Molnar and Rusty Russell共同设计完成。几位都是linux领域的专家,其中可能Ingo Molnar大家更熟悉一些,毕竟是O(1)调度器和CFS的实现者。
Futex按英文翻译过来就是快速用户空间互斥体。其设计思想其实 不难理解,在传统的Unix系统中,System V IPC(inter process communication),如 semaphores, msgqueues, sockets还有文件锁机制(flock())等进程间同步机制都是对一个内核对象操作来完成的,这个内核对象对要同步的进程都是可见的,其提供了共享 的状态信息和原子操作。当进程间要同步的时候必须要通过系统调用(如semop())在内核中完成。可是经研究发现,很多同步是无竞争的,即某个进程进入 互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互斥区或者请求同一同步变量的。但是在这种情况下,这个进程也要陷入内核去看看有没有人 和它竞争,退出的时侯还要陷入内核去看看有没有进程等待在同一同步变量上。这些不必要的系统调用(或者说内核陷入)造成了大量的性能开销。为了解决这个问 题,Futex就应运而生,Futex是一种用户态和内核态混合的同步机制。首先,同步的进程间通过mmap共享一段内存,futex变量就位于这段共享 的内存中且操作是原子的,当进程尝试进入互斥区或者退出互斥区的时候,先去查看共享内存中的futex变量,如果没有竞争发生,则只修改futex,而不 用再执行系统调用了。当通过访问futex变量告诉进程有竞争发生,则还是得执行系统调用去完成相应的处理(wait 或者 wake up)。简单的说,futex就是通过在用户态的检查,(motivation)如果了解到没有竞争就不用陷入内核了,大大提高了low-contention时候的效率。 Linux从2.5.7开始支持Futex。
steps:
1. 從 http://sourceforge.net/projects/strace/files/strace/ 下載strace source code, 目前最新版為4.5.20 (strace-4.5.20.tar.bz2)
2. tar -jxv -f strace-4.5.20.tar.bz2
3. ./configure --host=arm-linux CC=arm-linux-gcc LD=arm-linux-ld , 配置makefile
4. make CFLAGS="-static" , 產生靜態可執行檔
5. (可做可不做) arm-linux-strip strace , 縮減strace的size
完成, 之後就可以把strace copy到ARM 的 linux平台上執行了
在網路中,不少伺服器使用的是Linux系統。為了進一步提高伺服器的效能,可能需要根據特定的硬體及需求重新編譯Linux核心。編譯Linux核心,需要根據規定的步驟進行,編譯核心過程中涉及到幾個重要的檔案。比如對於RedHat Linux,在/boot目錄下有一些與Linux核心有關的檔案。編譯過RedHat Linux核心的人對其中的System.map 、vmlinuz、initrd-2.4.7-10.img印象可能比較深刻,因為編譯內核過程中涉及到這些檔案的建立等操作。那麼這幾個文件是怎麼產生的?又有什麼作用呢?本文對此做些介紹。
vmlinuz是可引導的(可引導意味著它有能力把作業系統載入至記憶體而使電腦能夠使用並且軟體程序可以運作)、壓縮過的核心。“vm”代表“Virtual Memory”。Linux 支援虛擬記憶體,不像古老的作業系統譬如DOS有640KB記憶體的限制。Linux能夠使用硬碟空間作為虛擬記憶體,因此得名“vm”。vmlinuz是可執行的Linux核心,它位於/boot/vmlinuz,它一般是一個軟鏈接(soft-link)。
vmlinuz的建立有兩種方式。一是編譯核心時通過“make zImage”產生,然後通過: “cp /usr/src/linux-2.4/arch/i386/linux/boot/zImage /boot/vmlinuz”複製。zImage適用於小核心的情況,它的存在是為了向後的兼容性。二是核心編譯時通過命令"make bzImage"建立,然後通過:“cp /usr/src/linux-2.4/arch/i386/linux/boot/bzImage /boot/vmlinuz”複製。bzImage是壓縮的核心映像檔案,需要注意,bzImage不是用bzip2壓縮的,bzImage中的bz容易引起誤解,bz表示“big zImage”。 bzImage中的b是“big”意思。
zImage(vmlinuz)和bzImage(vmlinuz)都是使用gzip壓縮的。它們不僅是一個壓縮檔案,而且在這兩個檔案的開頭部分內嵌有gzip解壓縮原始碼。所以你不能用gunzip 或 gzip -dc來解壓縮vmlinuz來得到vmlinux。
核心檔案中包含一個微型(小型)的gzip解壓縮程式碼用於解壓縮核心並引導它(可引導意味著它有能力把作業系統載入至記憶體而使電腦能夠使用並且軟體程序可以運作)。兩者的不同之處(zImage)在於,老的zImage解壓縮內核到低端內存(第一個640K),bzImage解壓縮內核到高端內存(1M以上)。如果內核比較小,那麼可以采用zImage 或bzImage之一,兩種方式引導的系統運行時是相同的。大的內核采用bzImage,不能采用zImage。 ( vmlinux是未壓縮的核心,vmlinuz是vmlinux的壓縮核心。 )
vmlinux 是ELF格式檔案,也就是編譯出来的最原始的檔案。
vmlinuz應該是由vmlinux經過arm-linux-objcopy後,並且經過壓縮後的核心檔案
zImage是vmlinuz經過gzip壓縮後的檔案,適用於小核心
uImage & zImage 差異
kernel 編譯完會產生 zImage。
uImage 是 zImage 在加上一個 64 Bytes 的 header。這是給 uboot 載入 kernel 用的。(利用 bootm )
uImage 如何產生? 利用 mkimage 來產生。
mkimage 參數說明:
[root@localhost tools]# ./mkimage
Usage: ./mkimage -l image
SA_RESTART
Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.
1, 訊號將中斷慢阻塞调用, 导致这些调用返回-1并且errno=EINTR表示被信号中断.
2, 部分函数是自启动的, 即永远不会返回-1与errno=EINTR, 它们在信号函数处理返回后继续执行完成, 而不是以彻底的失败告终.
这里很明确的说明, 这个flag只是为了兼容BSD, 明确的指定让能够自启动的慢阻塞调用能够从信号中断中恢复并继续, 它并没有令所有调用都恢复的本事, 要搞清楚.
楼主貌似疑惑的点很普通... 假设调用sleep(10):
1, 假设它不能自启动, 那么sleep(10)被信号中断, 等信号函数返回后sleep(10)立即失败返回-1, errno=EINTR. 也许此时才睡了5秒而已.
2, 假设它能够自启动, 并通过SA_RESTART设置信号处理函数明确的帮助慢阻塞调用重启动, 那么sleep(10)在5秒被中断, 信号函数结束后会继续睡另外5秒, 然后正常返回.
Cross Compiler
從工作以來就一直使用Cross Compiler
可是現在終於知道為何這樣稱呼
我試著用口語來解釋
當我們使用compiler來編譯某個程式
該程式一定只能執行在與你編譯的機器相同的平台
但是現在Cross Compiler編譯出來的不是相同平台
而是要執行在你的target平台上,例如ARM
所以Cross Compiler for ARM就是編譯出來的程式
得由ARM CPU才能執行
碰到过,是因为man
和头文件不一致(可能是版本导致也可能就是mistake
),
最后结果当然以实际的头文件为准。
vim /usr/include/string.h
:
#if defined __USE_GNU
extern char *strndup (__const char *__string, size_t __n)
__THROW __attribute_malloc__ __nonnull ((1));
#endif
所以显然这时候应该#define __USE_GNU
而不是#define _GNU_SOURCE
..
更新
关于_GNU_SOURCE
宏,它同时也是是在
它同时也是features.h
中用于特性控制的一个功能测试宏
/user/include/features.h
/* If _GNU_SOURCE was defined by the user, turn on all the other features. */
#ifdef _GNU_SOURCE
# undef _ISOC99_SOURCE
# define _ISOC99_SOURCE 1
# undef _POSIX_SOURCE
# define _POSIX_SOURCE 1
# undef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200809L
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 700
# undef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED 1
# undef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE 1
# undef _BSD_SOURCE
# define _BSD_SOURCE 1
# undef _SVID_SOURCE
# define _SVID_SOURCE 1
# undef _ATFILE_SOURCE
# define _ATFILE_SOURCE 1
#endif
其中_ISOC99_SOURCE
, _POSIX_SOURCE
, _XOPEN_SOURCE
都是功能测试宏,
用于指示是否包含对应标准的特性,
而这些不同的特性源于过去20多年来进行的各种标准化工作(ANSI, ISO, POSIX, FIPS等),
引言:
Embedded Linux技術基於開放原始碼的資源,並且已經是當今最重要的嵌入式應用技術之一。Embedded Linux是燒錄在目標裝置上(特定硬體)的系統,1個Embedded Linux系統包含Linux kernel(核心)與 root filesystem(檔案系統) 2大部分,Embedded Linux系統到底由哪些組成要素構成,本文將由概念的層面進行分析。
本文:
由於目前的目標裝置(特定硬體),都必須嵌入極為複雜的功能,所以「嵌入式作業系統(Embedded system)」成為嵌入式系統不可或缺的要素。由於嵌入式系統是功能導向的系統,因此必須設計、選擇或購買正確(或適合)的目標裝置,才能開始實作並嵌入「嵌入式系統」。因此,嵌入式系統技術是以功能、與目標裝置為分類的1種技術。
例如,與PDA相關的目標裝置(即硬體)、與MP3播放器相關的目標裝置、與3G手機相關的目標裝置...等等;使用這些目標裝置所開發的特定功能系統,便是PDA的嵌入式系統、MP3音樂播放的嵌入式系統、3G手機的嵌入式系統。
Embedded Linux其實並不是1個作業系統,而是代表「應用Linux系統於Embedded system」的名詞。Embedded Linux的技術核心主軸是在研究「如何將Linux系統嵌入至嵌入式目標裝置裡」。
GCC configure : --build
--host --target
char proc_fd_path[255];
char fd_des_buf[255];
ssize_t fd_des_len;
/* Get fd descriptions, fd is the input parameter */
sprintf(proc_fd_path, "/proc/%d/fd/%d", getpid(), fd);
if ((fd_des_len = readlink(proc_fd_path, fd_des_buf, sizeof(fd_des_buf)-1)) != -1)
[此篇文章並非原創若有冒犯敬請來信告知]
kogeiman
我們都知道,行程就是正在執行的程序。而在Linux中,可以使用一個行程來建立另外一個行程。這樣的話,Linux的行程的組織結構其實有點像Linux目錄樹,是有層次結構的,可以使用pstree命令來查閱。在最上面是init程序的執行行程。它是所有行程的祖先。Linux提供了兩個函數來建立行程。
1.fork()
fork()提供了建立行程的基本操作,可以說它是Linux系統多任務(multi-task)的基礎。該函數在unistd.h中聲明。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{