linux 記憶體探測和初始化
linux在被bootloader載入到記憶體後, cpu最初執行的核心程式碼是arch/x86/boot/header.S彙編檔案中的_start例程,設定好頭部header,其中包括大量的bootloader引數。接著是其中的start_of_setup例程,這個例程在做了一些準備工作後會通過call main跳轉到arch/x86/boot/main.c:main()函式處執行,這就是眾所周知的x86下的main函式,它們都工作在真實模式下。在這個main函式中我們可以第一次看到與記憶體管理相關的程式碼,這段程式碼呼叫detect_memory()函式檢測系統實體記憶體。如下:
- void main(void)
- {
- /* First, copy the boot header into the "zeropage" */
- copy_boot_params(); /* 把頭部各引數複製到boot_params變數中 */
- /* End of heap check */
- init_heap();
- /* Make sure we have all the proper CPU support */
- if (validate_cpu()) {
-
puts("Unable to boot - please use a kernel appropriate "
- "for your CPU.\n");
- die();
- }
- /* Tell the BIOS what CPU mode we intend to run in. */
- set_bios_mode();
- /* Detect memory layout */
- detect_memory(); /* 記憶體探測函式 */
- /* Set keyboard repeat rate (why?) */
- keyboard_set_repeat();
-
/* Query MCA information */
- query_mca();
- /* Query Intel SpeedStep (IST) information */
- query_ist();
- /* Query APM information */
- #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
- query_apm_bios();
- #endif
- /* Query EDD information */
- #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
- query_edd();
- #endif
- /* Set the video mode */
- set_video();
- /* Parse command line for 'quiet' and pass it to decompressor. */
- if (cmdline_find_option_bool("quiet"))
- boot_params.hdr.loadflags |= QUIET_FLAG;
- /* Do the last things and invoke protected mode */
- go_to_protected_mode();
- }
- int detect_memory(void)
- {
- int err = -1;
- if (detect_memory_e820() > 0)
- err = 0;
- if (!detect_memory_e801())
- err = 0;
- if (!detect_memory_88())
- err = 0;
- return err;
- }
- #define SMAP 0x534d4150 /* ASCII "SMAP" */
- staticint detect_memory_e820(void)
- {
- int count = 0; /* 用於記錄已檢測到的實體記憶體數目 */
- struct biosregs ireg, oreg;
- struct e820entry *desc = boot_params.e820_map;
- staticstruct e820entry buf; /* static so it is zeroed */
- initregs(&ireg); /* 初始化ireg中的相關暫存器 */
- ireg.ax = 0xe820;
- ireg.cx = sizeof buf; /* e820entry資料結構大小 */
- ireg.edx = SMAP; /* 標識 */
- ireg.di = (size_t)&buf; /* int15返回值的存放處 */
- /*
- * Note: at least one BIOS is known which assumes that the
- * buffer pointed to by one e820 call is the same one as
- * the previous call, and only changes modified fields. Therefore,
- * we use a temporary buffer and copy the results entry by entry.
- *
- * This routine deliberately does not try to account for
- * ACPI 3+ extended attributes. This is because there are
- * BIOSes in the field which report zero for the valid bit for
- * all ranges, and we don't currently make any use of the
- * other attribute bits. Revisit this if we see the extended
- * attribute bits deployed in a meaningful way in the future.
- */
- do {
- /* 在執行這條內聯彙編語句時輸入的引數有:
- eax暫存器=0xe820
- dx暫存器=’SMAP’
- edi暫存器=desc
- ebx暫存器=next
- ecx暫存器=size
- 返回給c語言程式碼的引數有:
- id=eax暫存器
- rr=edx暫存器
- ext=ebx暫存器
- size=ecx暫存器
- desc指向的記憶體地址在執行0x15中斷呼叫時被設定
- */
- intcall(0x15, &ireg, &oreg);
- ireg.ebx = oreg.ebx; /* 選擇下一個 */
- /* BIOSes which terminate the chain with CF = 1 as opposed
- to %ebx = 0 don't always report the SMAP signature on
- the final, failing, probe. */
- if (oreg.eflags & X86_EFLAGS_CF)
- break;
- /* Some BIOSes stop returning SMAP in the middle of
- the search loop. We don't know exactly how the BIOS
- screwed up the map at that point, we might have a
- partial map, the full map, or complete garbage, so
- just return failure. */
- if (oreg.eax != SMAP) {
- count = 0;
- break;
- }
- *desc++ = buf; /* 將buf賦值給desc */
- count++; /* 探測數加一 */
- } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
- /* 將記憶體塊數保持到變數中 */
- return boot_params.e820_entries = count;
- }
這裡存放中斷返回值的e820entry結構,以及表示記憶體圖的e820map結構均位於arch/x86/include/asm/e820.h中,如下:
- struct e820entry {
- __u64 addr; /* 記憶體段的開始 */
- __u64 size; /* 記憶體段的大小 */
-
__u32 type;
相關推薦
linux 記憶體探測和初始化
1、記憶體探測 linux在被bootloader載入到記憶體後, cpu最初執行的核心程式碼是arch/x86/boot/header.S彙編檔案中的_start例程,設定好頭部header,其中包括大量的bootloader引數。接著是其中的start_
Linux環境變數和初始化配置
1.環境變數在 etc/profile 檔案中, PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/samba/bin 新增或者刪除 環境變數 也可以直接使用 PATH=$PATH:/usr/local
啟動期間的記憶體管理之初始化過程概述----Linux記憶體管理(九)
在記憶體管理的上下文中, 初始化(initialization)可以有多種含義. 在許多CPU上, 必須顯式設定適用於Linux核心的記憶體模型. 例如在x86_32上需要切換到保護模式, 然後核心才能檢測到可用記憶體和暫存器. 而我們今天要講的boot階段
linux C 結構體struct的定義和初始化
struct 定義: struct test { int a; long b; float c; char d; char e[]; }tt1,tt2;//物件宣告列表緊跟struct定義 struct test tt3,tt4;//單獨宣告物件列表 //宣告一個沒結構體名
C++學習之記憶體的分配和初始化
C++定義了2個運算子來分配和釋放動態記憶體。new分配記憶體,delete釋放記憶體。 1. 使用new動態分配和初始化物件 在自由空間分配的記憶體是無名的,new返回一個指向分配的物件的指標。 int *pi = new int; // pi指向一個動態分
linux動態庫的初始化和清理
a. Windows 中有 DllMain 入口函式, 而 Linux 中則沒有。 b. Linux 中有特殊函式 _init 和 _fini, 主要是分別用來初始化動態庫和關閉的時候 做一些必要的處理, 我們可以把自己認為需要的程式碼放到這兩個
C#中對於變量的聲明和初始化
最好 編譯 return 它的 con code 數據 類型安全 狀態 C#變量初始化是C#強調安全性的另一個例子。簡單地說,C#編譯器需要用某個初始值對變量進行初始化,之後才能在操作中引用該變量。大多數現代編譯器把沒有初始化標記為警告,但C#編譯器把它當作錯誤來看待。
c++中成員函數指針數組定義和初始化方法
fun all turn bsp ati const 成員函數指針 溢出 cat 實際項目中經常遇到很多類似操作,比如命令碼對應執行函數等,對於此類操作,比較好的方式是使用const數組,將命令碼和操作函數綁定在一起,通過查表方式找到操作函數,並執行操作函數。這樣可以簡化代
有關變量的聲明和初始化的問題
stat 對象實例 實例 [] ima als void img 比較 1.馬上就要考java了,於是刷幾道題,題目不難但是比較基礎,比較細節,其中一道題目如下: 為了弄明白那些變量需要提前聲明,我做了如下幾個小測試: 測試一: 1 package priv.xiaom
JAVA中對象創建和初始化過程
2.3 人的 cin 類型變量 認識 handle product window blank 1.Java中的數據類型 Java中有3個數據類型:基本數據類型(在Java中,boolean、byte、short、int、long、char、float、double這八種
nsq源碼閱讀筆記之nsqd(一)——nsqd的配置解析和初始化
con views pos 直接 rgba 函數調用 程序 spa 重命名 配置解析nsqd的主函數位於apps/nsqd.go中的main函數首先main函數調用nsqFlagset和Parse進行命令行參數集初始化, 然後判斷version參數是否存在,若存在,則打印版
金甲防線服務項目筆記:菜單和初始化
serial 16px http private ftdi fig user ping -i 1、首先數據庫jdbc配置:config路徑下,配置jdbc,數據庫名:jjfxxin,賬戶:root,密碼:123456 2、菜單初始化設置: //3.5.4服務中心--&
Java數組的創建和初始化
java 類 操作符 我們說到數組,可能有的人就會比較害怕了,其實,數組只是把對象序列(很多個對象)或者基本類型序列(很多個基本類型)放在一起而已。數組是通過方括號下標操作符[]來定義和使用的。如果要定義,創建一個數組,只需在類型名後加上一對方括號[]即可。如果要定義二維數組,那麽,就要加兩個方括
SpringMVC源碼解析-DispatcherServlet啟動流程和初始化
instant custom delegate bean 自己的 erro -- true long 在使用springmvc框架,會在web.xml文件配置一個DispatcherServlet,這正是web容器開始初始化,同時會在建立自己的上下文來持有Spring
hibernate_基本配置和初始化步驟
導入jar包 導入 eclips ips conf 數據 hiberna 持久化類 步驟 1.hibernate使用步驟: 1)創建hibernate配置文件 2)創建持久化類 3)創建對象-關系映射 4)通過hibernate api編寫訪問數據庫的代碼 2.ecli
linux文件系統 - 初始化(一)
成員函數 cat 文章 記錄 inf htm 源代碼 設備驅動模型 proxy 術語表: struct task:進程 struct mnt_namespace:命名空間 struct mount:掛載點 struct vfsmount:掛載項 struct file:文件
linux文件系統 - 初始化(三)
視圖 div 目錄遷移 oca script 方式 不能 輸出 str 一、目的 內核加載完initrd文件後,為掛載磁盤文件系統做好了必要的準備工作,包括掛載了sysfs、proc文件系統,加載了磁盤驅動程序驅動程序等。接下來,內核跳轉到用戶空間的init程序,
linux文件系統 - 初始化(二)
軟鏈接 復制代碼 模式 文件的 操作 pop 臨時 console mini 一、目的 本文主要講述linux3.10文件系統初始化過程的第二階段:加載initrd。 initrd是一個臨時文件系統,由bootload負責加載到內存中,裏面包含了基本的可執
SQLAlchemy數據庫連接和初始化數據庫
數據 即使 conf 執行 int rop windows use VR 查看版本 >>> import sqlalchemy >>> sqlalchemy.__version__ ‘1.0.9‘ 創建連接 from sqlclach
JVM基礎學習之類的加載、鏈接和初始化
條件 希望 運行 ring get 準備 AR return 復雜 本文我們一起討論Java類的加載、鏈接和初始化。 Java字節代碼的表現形式是字節數組(byte[]),而Java類在JVM中的表現形式是 java.lang.Class類 的對象。一個Java類從字節