編輯:關於android開發
前面分析完了copy_strings函數,這裡來分析另一個注意的函數change_ldt。
先來看調用處:
// 根據a_text 修改局部表中描述符基址和段限長,並將參數和環境空間頁面放置在數據段末端。 // 執行下面語句之後,p 此時是以數據段起始處為原點的偏移值,仍指向參數和環境空間數據開始處, // 也即轉換成為堆棧的指針。 p += change_ldt (ex.a_text, page) - MAX_ARG_PAGES * PAGE_SIZE;
解釋的很清楚,也就是說p指向的是相當於在圖9-23的左方添加了64M-MAX_ARG_PAGES * PAGE_SIZE的大小容量。總容量為64M。
struct exec
{
unsigned long a_magic; /* 執行文件魔數。使用N_MAGIC 等宏訪問。 */
unsigned a_text; /* 代碼長度,字節數。 */
unsigned a_data; /* 數據長度,字節數。 */
unsigned a_bss; /* 文件中的未初始化數據區長度,字節數。 */
unsigned a_syms; /* 文件中的符號表長度,字節數。 */
unsigned a_entry; /* 執行開始地址。 */
unsigned a_trsize; /* 代碼重定位信息長度,字節數。 */
unsigned a_drsize; /* 數據重定位信息長度,字節數。 */
};
// 下面對執行文件的頭結構數據進行處理,首先讓ex 指向執行頭部分的數據結構。
ex = *((struct exec *) bh->b_data); /* read exec-header *//* 讀取執行頭部分 */
這裡的ex為讀取的可執行二進制文件頭部分。下面進入change_ldt函數:
//// 修改局部描述符表中的描述符基址和段限長,並將參數和環境空間頁面放置在數據段末端。
// 參數:text_size - 執行文件頭部中a_text 字段給出的代碼段長度值;
// page - 參數和環境空間頁面指針數組。
// 返回:數據段限長值(64MB)。
static unsigned long
change_ldt (unsigned long text_size, unsigned long *page)
{
unsigned long code_limit, data_limit, code_base, data_base;
int i;
// 根據執行文件頭部a_text 值,計算以頁面長度為邊界的代碼段限長。並設置數據段長度為64MB。
code_limit = text_size + PAGE_SIZE - 1;
code_limit &= 0xFFFFF000;
data_limit = 0x4000000;
// 取當前進程中局部描述符表代碼段描述符中代碼段基址,代碼段基址與數據段基址相同。
code_base = get_base (current->ldt[1]);
data_base = code_base;
// 重新設置局部表中代碼段和數據段描述符的基址和段限長。
set_base (current->ldt[1], code_base);
set_limit (current->ldt[1], code_limit);
set_base (current->ldt[2], data_base);
set_limit (current->ldt[2], data_limit);
/* make sure fs points to the NEW data segment */
/* 要確信fs 段寄存器已指向新的數據段 */
// fs 段寄存器中放入局部表數據段描述符的選擇符(0x17)。
__asm__ ("pushl $0x17\n\tpop %%fs"::);
// 將參數和環境空間已存放數據的頁面(共可有MAX_ARG_PAGES 頁,128kB)放到數據段線性地址的
// 末端。是調用函數put_page()進行操作的(mm/memory.c, 197)。
data_base += data_limit;
for (i = MAX_ARG_PAGES - 1; i >= 0; i--)
{
data_base -= PAGE_SIZE;
if (page[i]) // 如果該頁面存在,
put_page (page[i], data_base); // 就放置該頁面。
}
return data_limit; // 最後返回數據段限長(64MB)。
}
第一二行的意思是code_limit最少也要有一內存頁的長度。
data_limit賦值為64M。
緊接著設置當前進程的LDT的代碼段和數據段的基址和段限長。
注意最後一段比較關鍵,從數據段末尾data_base開始放置參數和環境空間已存放數據的頁面。page是參數環境空間所有頁面地址的數組。如果page[i]該頁面存在,就調用put_page函數:
/*
* 下面函數將一內存頁面放置在指定地址處。它返回頁面的物理地址,如果
* 內存不夠(在訪問頁表或頁面時),則返回0。
*/
//// 把一物理內存頁面映射到指定的線性地址處。
// 主要工作是在頁目錄和頁表中設置指定頁面的信息。若成功則返回頁面地址。
// 在缺頁異常的C 函數do_no_page()中會調用此函數。對於缺頁引起的異常,由於任何缺頁緣故而
// 對頁表作修改時,並不需要刷新CPU 的頁變換緩沖(或稱Translation Lookaside Buffer,TLB),
// 即使頁表項中標志P 被從0 修改成1。因為無效頁項不會被緩沖,因此當修改了一個無效的頁表項
// 時不需要刷新。在此就表現為不用調用Invalidate()函數。
unsigned long
put_page (unsigned long page, unsigned long address)
{
unsigned long tmp, *page_table;
/* NOTE !!! This uses the fact that _pg_dir=0 */
/* 注意!!!這裡使用了頁目錄基址_pg_dir=0 的條件 */
// 如果申請的頁面位置低於LOW_MEM(1Mb)或超出系統實際含有內存高端HIGH_MEMORY,則發出警告。
if (page < LOW_MEM || page >= HIGH_MEMORY)
printk ("Trying to put page %p at %p\n", page, address);
// 如果申請的頁面在內存頁面映射字節圖中沒有置位,則顯示警告信息。
if (mem_map[(page - LOW_MEM) >> 12] != 1)
printk ("mem_map disagrees with %p at %p\n", page, address);
// 計算指定地址在頁目錄表中對應的目錄項指針。
page_table = (unsigned long *) ((address >> 20) & 0xffc);
// 如果該目錄項有效(P=1)(也即指定的頁表在內存中),則從中取得指定頁表的地址??page_table。
if ((*page_table) & 1)
page_table = (unsigned long *) (0xfffff000 & *page_table);
else
{
// 否則,申請空閒頁面給頁表使用,並在對應目錄項中置相應標志7(User, U/S, R/W)。然後將
// 該頁表的地址??page_table。
if (!(tmp = get_free_page ()))
return 0;
*page_table = tmp | 7;
page_table = (unsigned long *) tmp;
}
// 在頁表中設置指定地址的物理內存頁面的頁表項內容。每個頁表共可有1024 項(0x3ff)。
page_table[(address >> 12) & 0x3ff] = page | 7;
/* no need for invalidate */
/* 不需要刷新頁變換高速緩沖 */
return page; // 返回頁面地址。
}
首先通過data_base獲取到相對應的頁目錄項指針,如果有效則獲取頁表地址。比較關鍵的是最後一句,address>>12表示data_base/4k,再與0x3ff(1024個項),因為這裡不是字節而是索引,所以不是0xffc。然後用這個索引和page(參數和環境空間已存放數據的頁面地址)綁定。
最後返回64M。
andoird軟件開發之一個記錄賬號密碼的APP--bmob後台,andoirdapp--bmob
andoird軟件開發之一個記錄賬號密碼的APP--bmob後台,andoirdapp--bmob1.app功能:通過注冊登錄賬戶,擁有一個賬戶本,能夠將平時自己容易的忘
專門搞android,android
專門搞android,android在android中,線程可以分為MainThread(UI線程)和WorkerThread(除了MainThread之外的線程)。從原
實現Discuz論壇客戶端應用源碼,discuz源碼
實現Discuz論壇客戶端應用源碼,discuz源碼通過使用該源碼,開發者可以迅速地將Discuz論壇遷移到Android客戶端中。不需要任何的開發工作即可擁有屬於自己論
genymotion的安裝和使用,genymotion安裝
genymotion的安裝和使用,genymotion安裝 一、簡介 相信大家用eclipse上的模擬器會覺得很慢很卡,這裡給大家介紹個好東西安卓模擬器gen