1. linux內核完全注釋 linux0.11 怎麼編譯運行
目錄(?)[+] 本系列文章調試Linux-0.11,大部分都是一些新內容,小部分是對代碼的一些印證。 另寫了一些調試工具,比如readizone,readblock,readinode這些工具對學習linux-0.11操作系統很有幫助。當然還需要stat和hexmp工具的配合。 fdiskforlinux-0.11 開始到-13/3/15的文章導出的pdf文件下載 另寫了一些工具源代碼分析,比如mkfs.c源代碼分析和d
2. mysql卸載後怎麼找回原來建的資料庫
每個 DBA 是不是都有過刪庫的經歷?刪庫了沒有備份怎麼辦?備份恢復後無法啟動服務什麼情況?表定義損壞數據無法讀取怎麼辦?
我曾遇到某初創互聯網企業,因維護人員不規范的備份恢復操作,導致系統表空間文件被初始化,上萬張表無法讀取,花了數小時才搶救回來。
當你發現數據無法讀取時,也許並非數據丟失了,可能是 DBMS 找不到描述數據的信息。
背景
先來了解下幾張關鍵的 InnoDB 數據字典表,它們保存了部分表定義信息,在我們恢復表結構時需要用到。
SYS_TABLES 描述 InnoDB 表信息CREATE TABLE `SYS_TABLES` (`NAME` varchar(255) NOT NULL DEFAULT '', 表名`ID` bigint(20) unsigned NOT NULL DEFAULT '0', 表id`N_COLS` int(10) DEFAULT NULL,`TYPE` int(10) unsigned DEFAULT NULL,`MIX_ID` bigint(20) unsigned DEFAULT NULL,`MIX_LEN` int(10) unsigned DEFAULT NULL,`CLUSTER_NAME` varchar(255) DEFAULT NULL,`SPACE` int(10) unsigned DEFAULT NULL, 表空間idPRIMARY KEY (`NAME`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_INDEXES 描述 InnoDB 索引信息CREATE TABLE `SYS_INDEXES` ( `TABLE_ID` bigint(20) unsigned NOT NULL DEFAULT '0', 與sys_tables的id對應 `ID` bigint(20) unsigned NOT NULL DEFAULT '0', 索引id `NAME` varchar(120) DEFAULT NULL, 索引名稱 `N_FIELDS` int(10) unsigned DEFAULT NULL, 索引包含欄位的個數 `TYPE` int(10) unsigned DEFAULT NULL, `SPACE` int(10) unsigned DEFAULT NULL, 存儲索引的表空間id `PAGE_NO` int(10) unsigned DEFAULT NULL, 索引的root page id PRIMARY KEY (`TABLE_ID`,`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_COLUMNS 描述 InnoDB 表的欄位信息CREATE TABLE `SYS_COLUMNS` ( `TABLE_ID` bigint(20) unsigned NOT NULL, 與sys_tables的id對應 `POS` int(10) unsigned NOT NULL, 欄位相對位置 `NAME` varchar(255) DEFAULT NULL, 欄位名稱 `MTYPE` int(10) unsigned DEFAULT NULL, 欄位編碼 `PRTYPE` int(10) unsigned DEFAULT NULL, 欄位校驗類型 `LEN` int(10) unsigned DEFAULT NULL, 欄位位元組長度 `PREC` int(10) unsigned DEFAULT NULL, 欄位精度 PRIMARY KEY (`TABLE_ID`,`POS`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_FIELDS 描述全部索引的欄位列CREATE TABLE `SYS_FIELDS` ( `INDEX_ID` bigint(20) unsigned NOT NULL, `POS` int(10) unsigned NOT NULL, `COL_NAME` varchar(255) DEFAULT NULL, PRIMARY KEY (`INDEX_ID`,`POS`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;./storage/innobase/include/dict0boot.h 文件定義了每個字典表的 index id,對應 id 的 page 中存儲著字典表的數據。
3. C++臨走前奉獻:輸出自身的源代碼
雨落深山,該住手時就住手。
4. 如何創建自定義的 WPP 擴展格式規格字元串
有關如何使用此宏的詳細信息,請參閱復雜類型定義的語法是怎樣的?。本主題提供向你介紹如何執行下列操作的示例:通過自定義 WPP 擴展格式規格字元串跟蹤固定長度字元串通過自定義 WPP 擴展格式規格字元串跟蹤可變長度字元串每個示例都介紹了如何使用自定義 WPP 配置文件來定義 DEFINE_CPLX_TYPE 宏。在這些示例中,配置文件命名為 LocalWpp.ini。有關如何使用自定義 WPP 配置文件的詳細信息,請參閱如何定義自定義數據類型?。 通過自定義 WPP 擴展格式規格字元串跟蹤固定長度字元串 此示例介紹如何使用自定義 WPP 擴展格式規格字元串跟蹤 Internet 協議版本 6 (IPv6) 網路地址。IPv6 網路地址由 in6_addr 結構定義,具有 16 位元組的固定長度。在此示例中,定義了一個復雜數據類型,然後可在你的源代碼中將其用作 %!IPV6ADDR!格式規格字元串。要創建 IPV6ADDR 復雜數據類型,請將以下語句添加到 LocalWpp.ini 配置文件: DEFINE_CPLX_TYPE(IPV6ADDR, WPP_LOGIPV6, in6_addr *, ItemIPV6Addr, "s", _IPV6_, 0, 1); 此語句使用 DEFINE_CPLX_TYPE 宏定義復雜類型 (IPV6ADDR) 及其屬性,例如其參數類型 (in6_addr *) 和大小 (16)。此語句還指定了在 WPP 預處理器在跟蹤提供程序的源代碼中解析 IPV6ADDR 復雜類型時,該預處理器使用的幫助程序宏的名稱 (WPP_LOGIPV6)。 WPP_FLAGS(-DWPP_LOGIPV6(x) WPP_LOGPAIR( (16), (x))); 此語句定義在將 IPV6 參數的長度/地址對傳遞到 TraceMessage 函數時,用於對該長度/地址對設置格式的幫助程序宏。在Visual Studio 中,打開你的項目的屬性頁。在「WPP 跟蹤」、「文件選項」下,將 LocalWpp.ini 指定為「其他配置文件」。 有關詳細信息,請參閱 WPP 預處理器。以下示例源代碼介紹你的跟蹤提供程序如何可通過使用 %!IPV6ADDR! 格式規格字元串來跟蹤 IPv6 網路格式規格字元串: struct in6_addr IPAddressV6 = {0}; DoTraceMessage(Noise, "IN6_ADDR = %!IPV6ADDR!", &IPAddressV6); 注意�0�2�0�2你可以創建復雜類型 (MACADDR) 用於跟蹤固定長度的媒體訪問控制 (MAC) 地址。此復雜類型可通過按照用於 IPV6ADDDR 復雜類型的過程來指定。 通過自定義 WPP 擴展格式規格字元串跟蹤可變長度字元串 此示例介紹如何使用自定義 WPP 擴展格式規格字元串來跟蹤數據的可變長度緩沖區。在此示例中,定義了一個復雜數據類型 (HEXDUMP),然後可在你的源代碼中將其用作 %!HEXDUMP!格式規格字元串。要創建 HEXDUMP 復雜數據類型,請將以下語句添加到 LocalWpp.ini 配置文件: DEFINE_CPLX_TYPE(HEXDUMP, WPP_LOGHEXDUMP, const xstr_t&, ItemHEXDump,"s", _HEX_, 0, 2); 此語句使用 DEFINE_CPLX_TYPE 宏定義復雜類型 (HEXDUMP) 及其屬性,例如其參數類型 (const xstr_t&) 和傳遞到 TraceMessage 的參數數 (2)。因為此復雜類型將用於可變長度數據,所以將宏的 Size 元素設置為零。此語句還指定了在 WPP 預處理器在跟蹤提供程序的源代碼中解析 HEXDUMP 復雜類型時,該預處理器使用的幫助程序宏的名稱 (WPP_LOGHEXDUMP)。 struct xstr_t { CHAR * _buf; short _len; xstr_t(__in_ecount(len) char *buf, short len):_buf(buf),_len(len) {} }; 此語句定義用於保存可變長度緩沖區的長度和地址的結構。此結構在 LOG_LENSTR 宏中進行初始化,並且對在 FormatString 參數中使用 HEXDUMP 復雜類型的 DoTraceMessage 的每次調用都置於本地。 WPP_FLAGS(-DLOG_LENSTR(len,str)=xstr_t(str,len)); 此語句定義用於為可變長度緩沖區初始化 xstr_t 結構的宏。你必須使用此宏在 DoTraceMessage 的VariableList 參數中傳遞可變長度緩沖區。 WPP_FLAGS(-DWPP_LOGHEXDUMP(x) WPP_LOGPAIR(2,&(x)._len) WPP_LOGPAIR((x)._len, (x)._buf)); 此語句定義在將可變長度緩沖區參數的長度/地址對傳遞到 TraceMessage 函數時,用於對該長度/地址對設置格式的幫助程序宏。可變長度參數要求兩個長度/地址對。因此,WPP_LOGHEXDUMP 宏以下列方式定義對 WPP_LOGPAIR 的兩個調用:對WPP_LOGPAIR 的第一個調用傳遞可變長度緩沖區的大小。對WPP_LOGPAIR 的第二個調用傳遞緩沖區自身的地址。注意�0�2�0�2此宏要求,已經通過對 LOG_LENSTR 的調用為可變長度緩沖區初始化 xstr_t 結構。因此,你必須通過 LOG_LENSTR 宏將可變長度緩沖區傳遞到 DoTraceMessage。在Visual Studio 中,打開你的項目的屬性頁。在「WPP 跟蹤」、「文件選項」下,將 LocalWpp.ini 指定為「其他配置文件」。 有關詳細信息,請參閱 WPP 預處理器。以下示例源代碼介紹你的跟蹤提供程序如何可通過使用 %!HEXDUMP! 格式規格字元串來跟蹤數據格式規格字元串: CHAR HexDump[1024] = {0, 1, 2, 3, 4, 5, 6, 7} ; DoTraceMessage(Noise, "HEXDUMP: %!HEXDUMP! ", LOG_LENSTR(sizeof(HexDump),(PCHAR)HexDump)); 注意�0�2�0�2你可以創建復雜類型 (HEXBYTES) 用於跟蹤可變長度緩沖區。�0�2�0�2
5. 如何打開二進制文件 ubuntu
查看二進制有以下幾種方法:
方法一:hexmp
apt-get install libdata-hexmper-perl
安裝好之後就可以直接hexmp your_binary_file
也可以直接使用hd命令來代替hexmp
如果想要慢慢看 : hd your_binary_file | more
方法二:
Vim 可以用來查看和編輯二進制文件
vim -b egenea-base.ko 加上-b參數,以二進制打開
然後輸入命令 :%!xxd -g 1 切換到十六進制模式顯示
0000000: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 .ELF............
0000010: 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
0000020: 2c a7 03 00 00 00 00 00 34 00 00 00 00 00 28 00 ,.......4.....(.
0000030: 10 00 0d 00 55 89 e5 51 51 8b 45 08 85 c0 74 11 ....U..QQ.E...t.
0000040: 52 52 50 a1 00 00 00 00 50 e8 fc ff ff ff 83 c4 RRP.....P.......
0000050: 10 89 ec 5d c3 8d 76 00 55 89 e5 50 50 b8 01 00 ...]..v.U..PP...
0000060: 00 00 8b 55 08 39 d0 73 09 8d 76 00 01 c0 39 d0 ...U.9.s..v...9.
0000070: 72 fa 8b 55 04 51 52 50 a1 00 00 00 00 50 e8 fc r..U.QRP.....P..
0000080: ff ff ff 89 ec 5d c3 90 55 89 e5 50 50 b8 01 00 .....]..U..PP...
0000090: 00 00 8b 55 08 39 d0 73 09 8d 76 00 01 c0 39 d0 ...U.9.s..v...9.
00000a0: 72 fa 8b 4d 04 8b 55 10 51 52 50 a1 00 00 00 00 r..M..U.QRP.....
00000b0: 50 e8 fc ff ff ff 89 ec 5d c3 89 f6 55 89 e5 57 P.......]...U..W
00000c0: 56 53 81 ec 8c 00 00 00 8b 5d 1c 8b 45 10 85 db VS.......]..E...
00000d0: 75 7e 85 c0 75 71 50 8b 45 04 50 a1 00 00 00 00 u~..uqP.E.P.....
00000e0: 68 8c 00 00 00 50 e8 fc ff ff ff 83 c4 10 89 c2 h....P.........
然後就可以像修改文本文件一樣修改16進制的字元,可以用 / 查找指定的偏移等等。修改右邊的ascii字元應該無效。修改完成後再執行:%!xxd -r 切換會二進制模式,然後再 :wq 保存退出就可以了。在這vim裡面這樣編輯還是很方便的,注意一定要:%!xxd -r切換回來之後在保存才行。
方法三. Linux 上面也有十六進制編輯的GUI工具
jeex (http://www.hds619.NET/jeex.PHP)
ghex
bless (Bless is a Hex Editor for Gtk# http://home.gna.org/bless/)
UltraEdit
6. 如何在Ubuntu下使用TF/SD 卡製作Exynos 4412 u-boot啟動盤
U-Boot源代碼下載地址 http://www.linuxidc.com/Linux/2011-07/38897.htm
硬體:迅為iTop 4412精英版 & TF卡
軟體:系統自帶終端即可
首先,我們應該清楚TF/SD卡可以看作一張完全空白的「白紙」,之所以有分區、分區格式的區別不過是在在這張「白紙」的某些特定位置寫入了一些數據來指示分區、分區格式。
其次,我們還應該清楚,在TF/SD啟動模式下,exynos 4412一上電,內部iROM會從TF/SD的第1個Block(第512個位元組開始)讀取8KB的數據到內部iRAM,然後從內部iRAM的0地址開始運行。
原理搞清楚了,那麼首先需要把TF/SD低級格式化-所有Block全部寫0x00。
1、連接TF/SD卡,打開終端
使用ls /dev/sd* 命令查看所有連接到電腦上磁碟。
問題:在這里為什麼不用df命令?
原因是假設你的TF/SD卡只有一個分區但這個分區已損壞,或者有多個分區但是沒有一個可以識別的分區,那麼此時df命令無法查看到tf/sd卡,所以說直接列出dev下所有sd開頭的設備,是終極方案。
(1)假設你的tf/sd卡只有一個分區,無論這個分區是否損壞,現象應該是類似這樣的:
插上tf/sd卡之前:
插上tf/sd卡之後:
很明顯多出的/dev/sdb就是本文後續操作的對象。
(2)假設你的tf/sd卡已有多個分區,無論這些分區是否損壞,現象應該是類似這樣的:
插上tf/sd卡之前:
插上tf/sd卡之後:
這里多出5個設備,但是我們仍然將/dev/sdb作為本文後續操作的對象。
注意:我這里是/dev/sdb,但是還有可能是/dev/sdc等等其它符號,必須根據你實際出現的設備名稱進行以下操作,否則有可能損壞系統分區,非常重要,切記!!!
2、使用16進制模式打開TF卡查看數據(可跳過)
我們使用linux自帶命令hexmp查看tf/sd卡中的數據:
命令為:
sudo hexmp -n 1048576 /dev/sdb
其中-n 1048576代表列印出前1M=1024*1024=1048576位元組的數據。
執行結果(部分)如下:
*代表內容為0x00,為了節省空間故作省略。
3、清空TF卡上前1MB的數據
由於4412的uboot大小基本在幾百kB的量級,所以清空前1MB空間足夠用,注意這里的清空不是格式化,而是填充0x00。
我們利用系統/dev下的zero設備,清零tf/sd卡前1MB。
執行結果如下:
這里的count=2000代表清空2000個block,一個block=512B,2000個正好為1MB。
再次hexmp查看tf/sd卡數據,發現:
前1MB空間成功清0x00。
4、燒寫uboot啟動文件
在這里,我們待燒寫的文件為 u-boot-iTOP-4412.bin 這個文件。
終端執行命令:
if代表輸入文件地址,以你u-boot-iTOP-4412.bin 這個文件的實際地址為准,of代表輸出地址,以你tf/sd卡的實際設備號為准。
到這里,就可以將tf/sd卡插入開發板上電啟動了,為了證明我們燒寫無誤,我們執行後續操作。
5、確認燒寫正確(可跳過)
我們需要確定從tf/sd卡的第一個block開始處,確實正確燒寫了u-boot-iTOP-4412.bin這個文件,下面我們對比一下,用到的命令同樣還是hexmp。
在這里,我們為了顯示方便,只列印前5KB數據,發現bin文件被正確的復制到了sd卡的512位元組處:
6、將TF卡接到開發板上,撥碼開關選擇TF啟動,上電:
Done。
本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2015-02/113493.htm
7. Linux內核編程的目錄
目錄
第1章概述1
1.1UNIX的歷史2
1.2標准和通用介面3
1.3自由軟體和開放源碼3
1.4Linux發布版概覽3
1.41Debian4
1.42Red Hat/Fedora 4
1.43Mandriva4
1.44SUSE4
1.45Gentoo4
1.46Yellow Dog5
1.47其他發布版5
1.5內核版本信息5
1.6基於Power的Linux5
1.7什麼是操作系統6
1.8內核組織7
1.9Linux內核概述7
1.9.1用戶介面7
1.9.2用戶標識符8
1.9.3文件和文件系統8
1.9.4進程12
1.9.5系統調用15
1.9.6Linux調度程序15
1.9.7Linux設備驅動程序15
1.10可移植性和體系結構的相關性16
1.11小結16
1.12習題16
第2章內核探索工具集18
2.1內核中常見的數據類型18
2.1.1鏈表18
2.1.2查找21
2.1.3樹22
2.2匯編24
2.2.1PowerPC24
2.2.2x8627
2.3匯編語言示例29
2.3.1x86中的匯編示例30
2.3.2PowerPC中的匯編示例31
2.4內聯匯編33
2.4.1輸出操作數34
2.4.2輸入操作數34
2.4.3已修改過的寄存器(已修改的元素列表) 34
2.4.4參數的編號方式34
2.4.5約束條件34
2.4.6asm35
2.4.7__volatile__35
2.5特殊的C 語言用法38
2.5.1asmlinkage38
2.5.2UL39
2.5.3內聯39
2.5.4const和volatile39
2.6內核探索工具一覽40
2.6.1objmp/readelf40
2.6.2hexmp41
2.6.3nm41
2.6.4obj42
2.6.5ar42
2.7內核發言:傾聽來自內核的消息42
2.7.1printk()42
2.7.2dmesg42
2.7.3/var/log/messages42
2.8其他奧秘43
2.8.1__init43
2.8.2likely()和unlikely()43
2.8.3IS_ERR和PTR_ERR44
2.8.4通告程序鏈44
2.9小結45
2.9.1項目:Hellomod45
2.9.2第一步:構造Linux模塊的框架45
2.9.3第二步:編譯模塊46
2.9.4第三步:運行代碼47
2.10習題48
第3章進程:程序執行的基本模型49
3.1程序51
3.2進程描述符52
3.2.1與進程屬性相關的欄位54
3.2.2與調度相關的欄位55
3.2.3涉及進程間相互關系的欄位58
3.2.4與進程信任狀相關的欄位59
3.2.5與進程權能相關的欄位60
3.2.6與進程限制相關的欄位61
3.2.7與文件系統及地址空間相關的欄位63
3.3進程的創建:系統調用fork()、vfork 和clone()64
3.3.1fork()函數65
3.3.2vfork()函數66
3.3.3clone()函數67
3.3.4do_fork()函數68
3.4進程的生命周期70
3.4.1進程的狀態70
3.4.2進程狀態的轉換71
3.5進程的終止74
3.5.1sys_exit()函數75
3.5.2do_exit()函數75
3.5.3通知父進程和sys_wait4()77
3.6了解進程的動態:調度程序的基本構架80
3.6.1基本結構80
3.6.2從等待中醒來或者激活81
3.7等待隊列86
3.7.1添加到等待隊列88
3.7.2等待事件89
3.7.3喚醒進程91
3.8非同步執行流程93
3.8.1異常93
3.8.2中斷95
3.9小結114
3.9.1項目:系統變數current114
3.9.2項目源碼115
3.9.3運行代碼116
3.10習題116
第4章內存管理117
4.1頁119
4.2內存管理區121
4.2.1內存管理區描述符122
4.2.2內存管理區操作輔助函數124
4.3頁面124
4.3.1請求頁面的函數124
4.3.2釋放頁面的函數126
4.3.3夥伴系統126
4.4Slab分配器130
4.4.1緩存描述符133
4.4.2通用緩存描述符135
4.4.3Slab描述符136
4.5Slab分配器的生命周期138
4.5.1與Slab分配器有關的全局變數138
4.5.2創建緩存139
4.5.3創建slab與cache_grow()144
4.5.4Slab的銷毀:退還內存與kmem_cache_destroy()146
4.6內存請求路徑147
4.6.1kmalloc()147
4.6.2kmem_cache_alloc()148
4.7Linux進程的內存結構149
4.7.1mm_struct150
4.7.2vm_area_struct152
4.8進程映像的分布及線性地址空間153
4.9頁表155
4.10缺頁156
4.10.1x86缺頁異常156
4.10.2缺頁處理程序157
4.10.3PowerPC缺頁異常164
4.11小結164
4.12項目:進程內存映射165
4.13習題166
第5章輸入/輸出167
5.1匯流排、橋、埠和介面的硬體實現167
5.2設備171
5.2.1塊設備概述172
5.2.2請求隊列和I/O 調度173
5.2.3示例:「通用」塊設備驅動程序180
5.2.4設備操作182
5.2.5字元設備183
5.2.6網路設備184
5.2.7時鍾設備184
5.2.8終端設備184
5.2.9直接存儲器存取184
5.3小結185
5.4項目:創建並口驅動程序185
5.4.1並口的硬體185
5.4.2運行在並口上的軟體187
5.5習題192
第6章文件系統194
6.1文件系統的基本概念194
6.1.1文件和文件名194
6.1.2文件類型195
6.1.3文件的附加屬性195
6.1.4目錄和路徑名196
6.1.5文件操作197
6.1.6文件描述符197
6.1.7磁碟塊、磁碟分區以及實現197
6.1.8性能198
6.2Linux虛擬文件系統198
6.2.1VFS的數據結構200
6.2.2全局鏈表和局部鏈表的引用211
6.3與VFS相關的結構212
6.3.1fs_struct結構212
6.3.2files_struct結構213
6.4頁緩存216
6.4.1address_space結構217
6.4.2buffer_head結構219
6.5VFS的系統調用和文件系統層221
6.5.1open()221
6.5.2close()227
6.5.3read()229
6.5.4write()244
6.6小結246
6.7習題246
第7章進程調度和內核同步247
7.1Linux的調度程序248
7.1.1選擇下一個進程248
7.1.2上下文切換253
7.1.3讓出CPU261
7.2內核搶佔269
7.2.1顯式內核搶佔269
7.2.2隱式用戶搶佔270
7.2.3隱式內核搶佔270
7.3自旋鎖和信號量272
7.4系統時鍾:關於時間和定時器274
7.4.1實時時鍾:現在幾點了274
7.4.2讀取PPC的實時時鍾276
7.4.3讀取x86的實時時鍾278
7.5小結280
7.6習題280
第8章內核引導281
8.1BIOS和Open Firmware282
8.2引導載入程序282
8.2.1GRUB283
8.2.2LILO286
8.2.3PowerPC和Yaboot286
8.3與體系結構相關的內存初始化287
8.3.1PowerPC的硬體內存管理287
8.3.2基於Intel x86體系結構的硬體內存管理296
8.3.3PowerPC和x86的代碼匯集305
8.4原始的RAM盤305
8.5開始:start_kernel()306
8.5.1調用lock_kernel()307
8.5.2調用page_address_init()309
8.5.3調用printk(linux_banner)311
8.5.4調用setup_arch311
8.5.5調用setup_per_cpu_areas()315
8.5.6調用smp_prepare_boot_cpu()316
8.5.7調用sched_init()317
8.5.8調用build_all_zonelists()319
8.5.9調用page_alloc_init319
8.5.10調用parse_args()320
8.5.11調用trap_init()322
8.5.12調用rcu_init()323
8.5.13調用init_IRQ()323
8.5.14調用softirq_init()324
8.5.15調用time_init()325
8.5.16調用console_init()326
8.5.17調用profile_init()326
8.5.18調用local_irq_enable()327
8.5.19配置initrd327
8.5.20調用mem_init()327
8.5.21調用late_time_init()333
8.5.22調用calibrate_delay()333
8.5.23調用pgtable_cache_init()334
8.5.24調用buffer_init()335
8.5.25調用security_scaffolding_startup()336
8.5.26調用vfs_caches_init()336
8.5.27調用radix_tree_init()343
8.5.28調用signal_init()344
8.5.29調用page_writeback_init()344
8.5.30調用proc_root_init()346
8.5.31調用init_idle()347
8.5.32調用rest_init()348
8.6init線程(或進程1)349
8.7小結353
8.8習題353
第9章構建Linux內核354
9.1工具鏈354
9.1.1編譯程序355
9.1.2交叉編譯355
9.1.3鏈接程序356
9.1.4ELF二進制目標文件356
9.2內核源代碼的構建360
9.2.1解釋源代碼360
9.2.2構建內核映像364
9.3小結369
9.4習題369
第10章向內核添加代碼371
10.1瀏覽源代碼371
10.11熟悉文件系統371
10.12filp和fops372
10.13用戶空間和內核空間374
10.14等待隊列375
10.15工作隊列及中斷378
10.16系統調用380
10.17其他類型的驅動程序380
10.18設備模型和sysfs文件系統383
10.2編寫代碼386
10.2.1設備基礎386
10.2.2符號輸出388
10.2.3IOCTL388
10.2.4輪詢與中斷391
10.2.5工作隊列和tasklet395
10.2.6增加系統調用的代碼396
10.3構建和調試398
10.4小結399
10.5習題400
8. 如何在Ubuntu下使用TF/SD 卡製作Exynos 4412 u-boot啟動盤
/**
******************************************************************************
* @author Maoxiao Hu
* @version V1.0.1
* @date Feb-2015
******************************************************************************
* < COPYRIGHT 2015 ISE of SHANDONG UNIVERSITY >
******************************************************************************
**/
如果你的系統是Mac OS X,請移步這里《如何在Mac下使用TF/SD 卡製作Exynos 4412 u-boot啟動盤》 http://www.linuxidc.com/Linux/2015-02/113494.htm。
U-Boot源代碼下載地址 http://www.linuxidc.com/Linux/2011-07/38897.htm
硬體:迅為iTop 4412精英版 & TF卡
軟體:系統自帶終端即可
首先,我們應該清楚TF/SD卡可以看作一張完全空白的「白紙」,之所以有分區、分區格式的區別不過是在在這張「白紙」的某些特定位置寫入了一些數據來指示分區、分區格式。
其次,我們還應該清楚,在TF/SD啟動模式下,exynos 4412一上電,內部iROM會從TF/SD的第1個Block(第512個位元組開始)讀取8KB的數據到內部iRAM,然後從內部iRAM的0地址開始運行。
原理搞清楚了,那麼首先需要把TF/SD低級格式化-所有Block全部寫0x00。
1、連接TF/SD卡,打開終端
使用ls /dev/sd* 命令查看所有連接到電腦上磁碟。
問題:在這里為什麼不用df命令?
原因是假設你的TF/SD卡只有一個分區但這個分區已損壞,或者有多個分區但是沒有一個可以識別的分區,那麼此時df命令無法查看到tf/sd卡,所以說直接列出dev下所有sd開頭的設備,是終極方案。
(1)假設你的tf/sd卡只有一個分區,無論這個分區是否損壞,現象應該是類似這樣的:
插上tf/sd卡之前:
NewImage
插上tf/sd卡之後:
NewImage
很明顯多出的/dev/sdb就是本文後續操作的對象。
(2)假設你的tf/sd卡已有多個分區,無論這些分區是否損壞,現象應該是類似這樣的:
插上tf/sd卡之前:
NewImage
插上tf/sd卡之後:
NewImage
這里多出5個設備,但是我們仍然將/dev/sdb作為本文後續操作的對象。
注意:我這里是/dev/sdb,但是還有可能是/dev/sdc等等其它符號,必須根據你實際出現的設備名稱進行以下操作,否則有可能損壞系統分區,非常重要,切記!!!
2、使用16進制模式打開TF卡查看數據(可跳過)
我們使用linux自帶命令hexmp查看tf/sd卡中的數據:
命令為:
sudo hexmp -n 1048576 /dev/sdb
其中-n 1048576代表列印出前1M=1024*1024=1048576位元組的數據。
執行結果(部分)如下:
NewImage
*代表內容為0x00,為了節省空間故作省略。
3、清空TF卡上前1MB的數據
由於4412的uboot大小基本在幾百kB的量級,所以清空前1MB空間足夠用,注意這里的清空不是格式化,而是填充0x00。
我們利用系統/dev下的zero設備,清零tf/sd卡前1MB。
執行結果如下:
NewImage
這里的count=2000代表清空2000個block,一個block=512B,2000個正好為1MB。
再次hexmp查看tf/sd卡數據,發現:
NewImage
前1MB空間成功清0x00。
4、燒寫uboot啟動文件
在這里,我們待燒寫的文件為 u-boot-iTOP-4412.bin 這個文件。
終端執行命令:
NewImage
if代表輸入文件地址,以你u-boot-iTOP-4412.bin 這個文件的實際地址為准,of代表輸出地址,以你tf/sd卡的實際設備號為准。
到這里,就可以將tf/sd卡插入開發板上電啟動了,為了證明我們燒寫無誤,我們執行後續操作。
5、確認燒寫正確(可跳過)
我們需要確定從tf/sd卡的第一個block開始處,確實正確燒寫了u-boot-iTOP-4412.bin這個文件,下面我們對比一下,用到的命令同樣還是hexmp。
在這里,我們為了顯示方便,只列印前5KB數據,發現bin文件被正確的復制到了sd卡的512位元組處:
NewImage
6、將TF卡接到開發板上,撥碼開關選擇TF啟動,上電:
NewImage
Done。
9. 如何交叉編譯mkfs.jffs2等工具鏈mtd-utils
首先說明一下:
在YAFFS2源文件的utils目錄下,執行make就可以生成 mkyaffs2image工具,執行
.(要製作yaffs2的目錄) (目標鏡像)/mkyaffs2image
acl_2.2.47.orig.tar.gz
lzo-2.03.tar.gz
mtd-utils_20080508.orig.tar.gz
zlib-1.2.3.tar.gz
mkfs.jffs2.for.arm-linux-gcc.3.4.1平台.tar.bz2
mkfs.jffs2.for.arm-linux-gcc.4.3.2平台.tar.bz2
mkfs.jffs2.for.pc平台.tar.bz2
如果只需要mkfs.jffs2工具,那麼ubuntu 8.10下直接安裝jffnms軟體包即可,
luther@gliethttp:~$ sudo apt-get install jffnms
如果需要將jffs2移植到arm開發板上,那麼就需要下載源碼進行交叉編譯了,這就是本文的內容.
1.下載工具軟體源碼包
luther@gliethttp:~$ wget http://ftp.de.debian.org/debian/pool/main/m/mtd-utils/mtd-utils_20080508.orig.tar.gz
luther@gliethttp:~$ wget http://www.zlib.net/zlib-1.2.3.tar.gz
luther@gliethttp:~$ wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.03.tar.gz
luther@gliethttp:~$ mkdir libs 用來存放下面生成的lib庫.
2.編譯zlib庫
luther@gliethttp:~/zlib-1.2.3$ ./configure --prefix=~/libs --shared
對於交叉編譯輸入如下指令
luther@gliethttp:~/zlib-1.2.3$ CC=arm-linux-gcc ./configure --prefix=~/libs --shared
luther@gliethttp:~/zlib-1.2.3$ make -j4
luther@gliethttp:~/zlib-1.2.3$ make install
luther@gliethttp:~$ tree ~/libs
/home/ubuntu/libs
|-- include
| |-- zconf.h
| `-- zlib.h
|-- lib
| |-- libz.so -> libz.so.1.2.3
| |-- libz.so.1 -> libz.so.1.2.3
| `-- libz.so.1.2.3
`-- share
`-- man
`-- man3
`-- zlib.3
5 directories, 6 files
這就表示完成了.
3.編譯lzo庫
luther@gliethttp:~/lzo-2.03$ ./configure --prefix=/home/ubuntu/libs --enable-shared
對於交叉編譯輸入如下指令
luther@gliethttp:~/lzo-2.03$ CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/home/ubuntu/libs --enable-shared --disable-static
這個還必須要絕對路徑才行.
luther@gliethttp:~/lzo-2.03$ make
luther@gliethttp:~/lzo-2.03$ make install
luther@gliethttp:~$ tree ~/libs
.
|-- include
| |-- lzo
| | |-- lzo1.h
| | |-- lzo1a.h
| | |-- lzo1b.h
| | |-- lzo1c.h
| | |-- lzo1f.h
| | |-- lzo1x.h
| | |-- lzo1y.h
| | |-- lzo1z.h
| | |-- lzo2a.h
| | |-- lzo_asm.h
| | |-- lzoconf.h
| | |-- lzodefs.h
| | `-- lzoutil.h
| |-- zconf.h
| `-- zlib.h
|-- lib
| |-- liblzo2.a
| |-- liblzo2.la
| |-- liblzo2.so -> liblzo2.so.2.0.0
| |-- liblzo2.so.2 -> liblzo2.so.2.0.0
| |-- liblzo2.so.2.0.0
| `-- libz.a
`-- share
`-- man
`-- man3
`-- zlib.3
6 directories, 22 files
手工將靜態庫刪掉就行了,
如果是arm平台還需要strip優化.
4.編譯mtd-utils-20080508前的准備工作.
編譯之前的代碼工作
luther@gliethttp:~$ wget http://ftp.de.debian.org/debian/pool/main/a/acl/acl_2.2.47.orig.tar.gz
luther@gliethttp:~$ mkdir libs/include/sys -p
luther@gliethttp:~$ cp acl-2.2.47/include/acl.h libs/include/sys
luther@gliethttp:~/mtd-utils-20080508$ export LD_LIBRARY_PATH=~/libs/lib:$LD_LIBRARY_PATH
如果還找不到-llzo2,那麼把他拷到/usr/lib下,對於交叉編譯器,就是拷貝到
比如
luther@gliethttp:~/libs/lib$ sudo cp -a * /vobs/tools/arm-tools/arm-linux-gcc-3.4.1/arm-linux/lib/
luther@gliethttp:~/mtd-utils-20080508$ vim Makefile
修改安裝路徑
DESTDIR=.
SBINDIR=gliethttp/sbin
MANDIR=gliethttp/share/man
INCLUDEDIR=gliethttp/include
修改CFLAGS變數
CFLAGS := -I./include -I/home/ubuntu/libs/include $(OPTFLAGS)
如果是arm-linux-gcc定義為
CFLAGS := -I./include -I/home/ubuntu/libs/include -DAI_ADDRCONFIG=0x0020 $(OPTFLAGS)
來自/usr/include/netdb.h
luther@gliethttp:~/mtd-utils-20080508$ vim ubi-utils/Makefile
DESTDIR := ~/mtd-utils-20080508
SBINDIR=gliethttp/sbin
MANDIR=gliethttp/share/man
INCLUDEDIR=gliethttp/include
luther@gliethttp:~/mtd-utils-20080508$ vim recv_image.c
拷貝/usr/include/netinet/in.h文件中
arm-linux-gcc中不需要拷貝它.
struct ip_mreq
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
結構體數據到頭部,否則在u盤版的ubuntu 8.10上老是提示沒有ip_mreq定義,雖然上面明明寫了#define _USE_MISC
arm-linux-gcc中還需要創建如3下個目錄
luther@gliethttp:~/mtd-utils-20080508$ mkdir arm-linux
luther@gliethttp:~/mtd-utils-20080508$ cp -r ubi-utils arm-linux/
luther@gliethttp:~/mtd-utils-20080508$ cp -r include arm-linux/
luther@gliethttp:~/mtd-utils-20080508$ vim ubi-utils/src/libpfiflash.c
將所有EBUF(PFIFLASH_ERRSTR[-rc]);全部替換為EBUF("%s", PFIFLASH_ERRSTR[-rc]);
vim下替換腳本為
:%s/EBUF(PFIFLASH_ERRSTR\[-rc\]);/EBUF("\%s", PFIFLASH_ERRSTR\[-rc\]);/g
luther@gliethttp:~/mtd-utils-20080508$ vim ubi-utils/src/ubimirror.c
將第206行的
fprintf(stderr, err_buf);
改為
fprintf(stderr, "%s", err_buf); // 想法是好的,因為err_buf中含有%d等format信息,這樣介面更加統一,但是編譯器似乎還並不支持這樣的操作.[luther.gliethttp]
luther@gliethttp:~/mtd-utils-20080508$ vim ubi-utils/src/unubi.c
將第898行
char fname[PATH_MAX];
改為
char fname[PATH_MAX+1];
luther@gliethttp:~/mtd-utils-20080508$ cd ubi-utils/new-utils
因為-O2優化的原因,會導致如下log信息
error: ignoring return value of 『scanf』, declared with attribute warn_unused_result
所有手工先編譯.o
luther@gliethttp:~/mtd-utils-20080508/ubi-utils/new-utils$ gcc -Iinclude -Isrc -I../../include -Wall -Werror -Wall src/ubiformat.c -c -o ubiformat.o
對於交叉編譯執行如下1條語句
luther@gliethttp:~/mtd-utils-20080508/ubi-utils/new-utils$ arm-linux-gcc -Iinclude -Isrc -I../../include -Wall -Werror -Wall src/ubiformat.c -c -o ubiformat.o
luther@gliethttp:~/mtd-utils-20080508/ubi-utils/new-utils$ cd -
好了,上面的所有修改完成之後,就可以執行make成功編譯了[luther.gliethttp].
luther@gliethttp:~/mtd-utils-20080508$ make
如果是交叉編譯,執行
luther@gliethttp:~/mtd-utils-20080508$ make CROSS=arm-linux-
luther@gliethttp:~/mtd-utils-20080508$ make install
對於交叉編譯,執行
luther@gliethttp:~/mtd-utils-20080508$ make CROSS=arm-linux- install
luther@gliethttp:~/mtd-utils-20080508$ tree gliethttp/
gliethttp/
|-- sbin
| |-- bin2nand
| |-- doc_loadbios
| |-- docfdisk
| |-- flash_erase
| |-- flash_eraseall
| |-- flash_info
| |-- flash_lock
| |-- flash_otp_mp
| |-- flash_otp_info
| |-- flash_unlock
| |-- flashcp
| |-- ftl_check
| |-- ftl_format
| |-- jffs2mp
| |-- mkbootenv
| |-- mkfs.jffs2
| |-- mkpfi
| |-- mtd_debug
| |-- nand2bin
| |-- nandmp
| |-- nandtest
| |-- nandwrite
| |-- nftl_format
| |-- nftlmp
| |-- pddcustomize
| |-- pfi2bin
| |-- pfiflash
| |-- recv_image
| |-- rfdmp
| |-- rfdformat
| |-- serve_image
| |-- sumtool
| |-- ubiattach
| |-- ubicrc32
| |-- ubicrc32.pl
| |-- ubidetach
| |-- ubigen
| |-- ubimirror
| |-- ubimkvol
| |-- ubinfo
| |-- ubinize
| |-- ubirmvol
| |-- ubiupdatevol
| `-- unubi
`-- share
`-- man
`-- man1
`-- mkfs.jffs2.1.gz
4 directories, 45 files
ep9312開發板上沒有任何文件系統flash數據讀取
# ./mtd_debug read /dev/mtd0 0 100 gliethttp.bin
Copied 100 bytes from address 0x00000000 in flash to gliethttp.bin
# hexmp gliethttp.bin
0000000 03ff ea00 350c e59f 001c e583 410e e3a0
0000010 4004 e583 4a03 e3a0 4001 e254 fffd 1aff
0000020 4106 e3a0 4004 e583 420f e202 5000 e594
0000030 4001 e084 5000 e594 4001 e084 5000 e594
0000040 4001 e084 5000 e594 4010 e3a0 4008 e583
0000050 4050 e3a0 4001 e254 fffd 1aff 4e1e e3a0
0000060 4008 e583
0000064
#
# ./mtd_debug read /dev/mtd2 0 100 gliethttp.bin;hexmp gliethttp.bin -Cv
Copied 100 bytes from address 0x00000000 in flash to gliethttp.bin
00000000 1f 8b 08 00 ca 14 7d 4a 02 03 e4 5a 0f 70 93 e7 |......}J...Z.p..|
00000010 79 7f 3f 49 36 b2 31 41 80 a0 0e 38 cd 57 70 16 |y.?I6.1A...8.Wp.|
00000020 93 18 f3 19 3b 60 12 9a d9 60 08 09 4e 22 c0 a4 |....;`...`..N"..|
00000030 b4 81 ca 42 92 6d 0d 59 d2 49 72 02 2b 4d dd 60 |...B.m.Y.Ir.+M.`|
00000040 72 84 e1 86 03 a7 21 01 8a d2 b2 4b 2e f3 56 76 |r.....!....K..Vv|
00000050 63 b7 34 0b 1d cd b1 1d 6b b3 95 36 dc 95 db d1 |c.4.....k..6....|
00000060 8b 90 d1 ea |....|
00000064