2010年5月3日 星期一

linux study 重點截錄

深入理解 Linux 2.6 的 initramfs 機制
ARM Linux源代码分析(1) for :linux/arch/arm/kernel/head.S
基于arm的Linux的启动分析
linux内核配置系统分析
Kconfig语法_config.in的新格式
MCUOL.com
内核的 Kconfig & Makefile
arm kconfig Serach
内核启动源码分析
為什麼我要學習linux,到底又要學些什麼?至少要有個明確的目標,否則"study linux"這幾個英文字母可是會耗掉我很多的青春(其實我已經沒有青春)。不論是一窩蜂或是潮流影響所致,linux的確給人帶來很大的改變,當大家都在談論它時或許只是一時的流行趨勢;然而那不是我想跟隨的流行;我只想跟著我的想法前進。那麼我的想法是什麼呢?"as far as possible close to Low Level"儘可能的貼進底層。
唯有這樣才可能真正了解KERNEL,了解KERNEL的目的是什麼?說真的好處太多,但我只針對我的需求:1.了解KERNEL使我更符合企業需求. 2.通盤了解才可能創新(雖然很難辦到). 3.讓更多的硬體可正常的運作於Linux. 4.所謂通盤了解並不是指要把整個核心 Source Code全部看懂過一遍,當然那是不可能達成的,而是針對主架構的程式碼要懂.....如此內心才不致覺的空虛. 5.提升編程能力.6.消磨時間、使腦袋瓜不會空轉。
--> 閱讀更多...

2010年4月28日 星期三

2440init.s 2440slib.s說明

2440init.s 2440slib.s這兩個檔案相當於是在ADS1.2開發環境中的簡易bootloader,其實只要輸入這兩個檔名就可搜尋到相關的中文註解說明例如S3C2440 2440init.s分析 2440启动代码注解 ;由於它的組合語言語法與GNU上的組合語言雖然一樣,但是卻有一些假指令,因此我把假指令的相關說明貼於此:arm偽指令 ARM汇编伪指令介绍。
其實在2440init.s中很多代碼是可以拿掉的;特別是那些以左右方括號[ ]作為以if endif,以l做為else的那些判斷式,原因可參考上面連結的相關說明。
今天我們其實重點是擺在2440slib.s這個檔案;2440slib.s注解,然而我個人覺得這個註解寫的並不很清楚,因此我打算自己來搞一遍。
這個檔裡頭都定義了一些和MMU相關聯的底層Routine:例如MMU_EnableICache MMU_DisableICache MMU_EnableDCache MMU_EnableMMU‧‧這裡也列出一些相關連結說明:ARM处理器架构-内存映射 内存管理单元(MMU)介绍 、 FS2410 开发板上启用 MMU 实现虚拟内存管理 、 内存管理单元(MMU)和协处理器CP15介绍 、 s3c2410 MMU(存储器管理单元)讲解 、 ARM920T关闭MMU,cache以及写缓冲区,CP15详解 、 ARM920T的MMU与Cache之操作MMU和Cache的内核启动代码 、 嵌入式Linux学习笔记(四)-内存管理单元mmu。内核关键链接脚本。
在linux kernel有關mmu設定請參考linux/arch/arm/boot/compressed/head.S
對以上的連結看過後就知道其實就是在搞cp15協同處理器;2440slib.s代碼實際內容如下:
目前我只把code擺上來,未來會逐一update
;==========================================
; File Name : 2440slib.s
; Function : S3C2440 (Assembly)
; Date : March 09, 2002
; Revision : Programming start (February 26,2002) -> SOP
; Revision : 03.11.2003 ver 0.0 Attatched for 2440
;==========================================
;Interrupt, FIQ/IRQ disable
NOINT EQU 0xc0 ; 1100 0000
;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.
GBLL THUMBCODE ;宣告一個全域邏輯變數THUMBCODE 預設值為FALSE
[ {CONFIG} = 16 ;如果CONFIG=16
THUMBCODE SETL {TRUE} ;設定THUMBCODE為TRUE
CODE32 ;
假指令CODE32,表示以下的代碼段為ARM 32bit 編碼
l ;else
THUMBCODE SETL {FALSE} ; 設定THUMBCODE為FALSE
] ;
endif

MACRO ;巨集宣告
MOV_PC_LR ;巨集名稱
[ THUMBCODE ;如果THUMBCODE為TRUE,則執行下一行,否則跳到下二行else處
bx lr ;
同call r14
l ;else
mov pc,lr ;r15<-r14
] ;endif
MEND ;巨集結尾

AREA C$$code, CODE, READONLY ;段宣告 段名稱C$$code 段屬性為代碼段唯讀
EXPORT EnterCritical
EnterCritical
mrs r1, cpsr
str r1, [r0]
orr r1, r1, #NOINT
msr cpsr_cxsf, r1
MOV_PC_LR
;restore cpsr, r0 = address to restore cpsr
EXPORT ExitCritical
ExitCritical
ldr r1, [r0]
msr cpsr_cxsf, r1
MOV_PC_LR
;==============
; CPSR I,F bit
;==============
;int SET_IF(void);
;The return value is current CPSR.
EXPORT SET_IF
SET_IF
;This function works only if the processor is in previliged mode.
mrs r0,cpsr
mov r1,r0
orr r1,r1,#NOINT
msr cpsr_cxsf,r1
MOV_PC_LR

;void WR_IF(int cpsrValue);
EXPORT WR_IF
WR_IF
;This function works only if the processor is in previliged mode.
msr cpsr_cxsf,r0
MOV_PC_LR


;void CLR_IF(void);
EXPORT CLR_IF
CLR_IF
;This function works only if the processor is in previliged mode.
mrs r0,cpsr
bic r0,r0,#NOINT
msr cpsr_cxsf,r0
MOV_PC_LR

EXPORT outportw
outportw strh r0, [r1]
MOV_PC_LR

EXPORT inportw
inportw ldrh r0, [r0]
MOV_PC_LR


;====================================
; MMU Cache/TLB/etc on/off functions
;====================================
R1_I EQU (1<<12)>EXPORT MMU_EnableICache
MMU_EnableICache
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_I
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_DisableICache(void)
EXPORT MMU_DisableICache
MMU_DisableICache
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_I
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_EnableDCache(void)
EXPORT MMU_EnableDCache
MMU_EnableDCache
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_C
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_DisableDCache(void)
EXPORT MMU_DisableDCache
MMU_DisableDCache
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_C
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_EnableAlignFault(void)
EXPORT MMU_EnableAlignFault
MMU_EnableAlignFault
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_A
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_DisableAlignFault(void)
EXPORT MMU_DisableAlignFault
MMU_DisableAlignFault
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_A
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_EnableMMU(void)
EXPORT MMU_EnableMMU
MMU_EnableMMU
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_M
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_DisableMMU(void)
EXPORT MMU_DisableMMU
MMU_DisableMMU
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_M
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_SetFastBusMode(void)
; FCLK:HCLK= 1:1
EXPORT MMU_SetFastBusMode
MMU_SetFastBusMode
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_iA:OR:R1_nF
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;void MMU_SetAsyncBusMode(void)
; FCLK:HCLK= 1:2
EXPORT MMU_SetAsyncBusMode
MMU_SetAsyncBusMode
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
MOV_PC_LR

;=========================
; Set TTBase
;=========================
;void MMU_SetTTBase(int base)
EXPORT MMU_SetTTBase
MMU_SetTTBase
;ro=TTBase
mcr p15,0,r0,c2,c0,0
MOV_PC_LR

;=========================
; Set Domain
;=========================
;void MMU_SetDomain(int domain)
EXPORT MMU_SetDomain
MMU_SetDomain
;ro=domain
mcr p15,0,r0,c3,c0,0
MOV_PC_LR

;=========================
; ICache/DCache functions
;=========================
;void MMU_InvalidateIDCache(void)
EXPORT MMU_InvalidateIDCache
MMU_InvalidateIDCache
mcr p15,0,r0,c7,c7,0
MOV_PC_LR

;void MMU_InvalidateICache(void)
EXPORT MMU_InvalidateICache
MMU_InvalidateICache
mcr p15,0,r0,c7,c5,0
MOV_PC_LR

;void MMU_InvalidateICacheMVA(U32 mva)
EXPORT MMU_InvalidateICacheMVA
MMU_InvalidateICacheMVA
;r0=mva
mcr p15,0,r0,c7,c5,1
MOV_PC_LR

;void MMU_PrefetchICacheMVA(U32 mva)
EXPORT MMU_PrefetchICacheMVA
MMU_PrefetchICacheMVA
;r0=mva
mcr p15,0,r0,c7,c13,1
MOV_PC_LR

;void MMU_InvalidateDCache(void)
EXPORT MMU_InvalidateDCache
MMU_InvalidateDCache
mcr p15,0,r0,c7,c6,0
MOV_PC_LR

;void MMU_InvalidateDCacheMVA(U32 mva)
EXPORT MMU_InvalidateDCacheMVA
MMU_InvalidateDCacheMVA
;r0=mva
mcr p15,0,r0,c7,c6,1
MOV_PC_LR

;void MMU_CleanDCacheMVA(U32 mva)
EXPORT MMU_CleanDCacheMVA
MMU_CleanDCacheMVA
;r0=mva
mcr p15,0,r0,c7,c10,1
MOV_PC_LR

;void MMU_CleanInvalidateDCacheMVA(U32 mva)
EXPORT MMU_CleanInvalidateDCacheMVA
MMU_CleanInvalidateDCacheMVA
;r0=mva
mcr p15,0,r0,c7,c14,1
MOV_PC_LR

;void MMU_CleanDCacheIndex(U32 index)
EXPORT MMU_CleanDCacheIndex
MMU_CleanDCacheIndex
;r0=index
mcr p15,0,r0,c7,c10,2
MOV_PC_LR

;void MMU_CleanInvalidateDCacheIndex(U32 index)
EXPORT MMU_CleanInvalidateDCacheIndex
MMU_CleanInvalidateDCacheIndex
;r0=index
mcr p15,0,r0,c7,c14,2
MOV_PC_LR

;void MMU_WaitForInterrupt(void)
EXPORT MMU_WaitForInterrupt
MMU_WaitForInterrupt
mcr p15,0,r0,c7,c0,4
MOV_PC_LR

;===============
; TLB functions
;===============
;voic MMU_InvalidateTLB(void)
EXPORT MMU_InvalidateTLB
MMU_InvalidateTLB
mcr p15,0,r0,c8,c7,0
MOV_PC_LR

;void MMU_InvalidateITLB(void)
EXPORT MMU_InvalidateITLB
MMU_InvalidateITLB
mcr p15,0,r0,c8,c5,0
MOV_PC_LR

;void MMU_InvalidateITLBMVA(U32 mva)
EXPORT MMU_InvalidateITLBMVA
MMU_InvalidateITLBMVA
;ro=mva
mcr p15,0,r0,c8,c5,1
MOV_PC_LR

;void MMU_InvalidateDTLB(void)
EXPORT MMU_InvalidateDTLB
MMU_InvalidateDTLB
mcr p15,0,r0,c8,c6,0
MOV_PC_LR

;void MMU_InvalidateDTLBMVA(U32 mva)
EXPORT MMU_InvalidateDTLBMVA
MMU_InvalidateDTLBMVA
;r0=mva
mcr p15,0,r0,c8,c6,1
MOV_PC_LR

;=================
; Cache lock down
;=================
;void MMU_SetDCacheLockdownBase(U32 base)
EXPORT MMU_SetDCacheLockdownBase
MMU_SetDCacheLockdownBase
;r0= victim & lockdown base
mcr p15,0,r0,c9,c0,0
MOV_PC_LR

;void MMU_SetICacheLockdownBase(U32 base)
EXPORT MMU_SetICacheLockdownBase
MMU_SetICacheLockdownBase
;r0= victim & lockdown base
mcr p15,0,r0,c9,c0,1
MOV_PC_LR

;=================
; TLB lock down
;=================
;void MMU_SetDTLBLockdown(U32 baseVictim)
EXPORT MMU_SetDTLBLockdown
MMU_SetDTLBLockdown
;r0= baseVictim
mcr p15,0,r0,c10,c0,0
MOV_PC_LR

;void MMU_SetITLBLockdown(U32 baseVictim)
EXPORT MMU_SetITLBLockdown
MMU_SetITLBLockdown
;r0= baseVictim
mcr p15,0,r0,c10,c0,1
MOV_PC_LR

;============
; Process ID
;============
;void MMU_SetProcessId(U32 pid)
EXPORT MMU_SetProcessId
MMU_SetProcessId
;r0= pid
mcr p15,0,r0,c13,c0,0
MOV_PC_LR

END
--> 閱讀更多...

2010年4月20日 星期二

GRUB Tracing 2

先列出configure.ac的巨集:截錄自gcc/gdb/make/autotool 文件/教學
AC_INIT(FILE)這個巨集用來檢查原始碼所在的路徑,autoscan會自動產生,我們不必修改它。
AM_INIT_AUTOMAKE(PACKAGE,VERSION)使用 Automake 所必備的巨集,PACKAGE是我們所要產生軟體套件的名稱,VERSION 是版本編號。
AC_CONFIG_AUX_DIR(dir)configure 系統時所使用的所有檔案( install-sh,config.sub,config.guess )若不想放在 configure 所在的目錄下, 可以利用此巨集指定在子目錄中
AC_CONFIG_HEADER(header.h) autoheader 會根據 AC_CHECK_HEADERS、AC_DEFINE 等巨集,產生 header.h.in , configure 參考此檔產生 header.h, 套件中的 header files只要含入header.h,即可解決編譯時大量的 '-D' 選項 。
AC_PROG_CC檢查系統可用的 C 編譯器,如果原始程式是用 C 寫的就需要這個巨集。其他程式檢查巨集請查看 autoconf/acprograms
AC_PROG_INSTALL檢察系統內是否有 BSD 相容 install 工具程式, 否則以 automake 的install-sh 替代。
AC_SUBST(VARIABLE) configure 程式會將 AC_OUTPUT 巨集所列出檔案中與指定變數名稱相同的位置,取代為該變數的值。
AC_CHECK_HEADERS( header.h)檢查系統中是否存在 header.h
AC_DEFINE(variable, define , comment)定義 C preprocessor variable, 可省略後兩項參數, 但預先必須在acconfig.h 中定義。ex: #undef USE_DNS
AC_DEFINE_UNQUOTED(variable, 可展開的 definem, comment )類似 AC_DEFINE , 其中的 define 若包含變數, 則會以內容展開變數ex:
AC_CONFIG_HEADER( conf.h )
AC_CHECK_HEADERS( unistd.h )
AC_DEFINE(USE_DNS, 1 , 使用DNS)
AC_DEFINEi_UNQUOTED(EDITOR, "$EDITOR", editor 的路徑)

則 autoheader 產生 conf.h.in 內含:
------------------------------------------------------------
/* Define as 1 if you have unistd.h */
#define HAVE_UNISTD_H 0
/* 使用DNS */
#undef USE_DNS
/* editor 的路徑 */
#undef EDITOR
若 configure 時, 若有 unistd.h、及指定 EDITOR=/usr/bin/vi 則
產生之 conf.h 如下
-----------------------------------------------------------
/* Define as 1 if you have unistd.h */
#define HAVE_UNISTD_H 1
/* 使用DNS */
#define USE_DNS 1
/* editor 的路徑 */
#define EDITOR /usr/bin/vi
AC_CHECK_PROG(variable,program,value-if-found,value-if-found,path1:path2)依指定路徑 path1:path2 尋找指定的 program, 若找到將 variable指定為 value-if-found, 若沒有找到 variable 指定為value-if-not-found,設定 variable 使用檔案的絕對檔案名稱。
AC_PATH_PROG(variable, program, value-if-not-found, path1:path2)依指定路徑 path1:path2 尋找指定的 program, 若找到將 variable指定為其完整路徑, 若沒有找到 variable 指定為 value-if-not-found。
AC_CANONICAL_HOST檢查系統類型, 並將其值存入 $host 變數
AC_CHECK_FUNCS(funcs, action-if-found, action-if-not-found)找尋是否有指定的 function 存在, 若存在執行 active-if-found 之 shell command, 反之則執行 active-if-not-found。可被檢查函式請參考autoconf/acfunctions
AC_ARG_ENABLE( feature,help-string,action-if-given,action-if-not-given)如果執行 configure 給定 --enable-feature 或 --disable-feature, 則會啟動相關的 action , enable 會執行 action-if-given, disable 會執行action-if-not-given。通常與 AC_DEFINE 搭配, 定義是否編譯某一項功能。
AC_OUTPUT(FILE)設定 configure 所要產生的檔案,如果是 Makefile 的話,configure便會把它檢查出來的結果 Makefile.in 檔然後產生合適的 Makefile。
ex:
configure.in 片段 Makefile.in 片段
--------------------------------------------------------------
FOO="hello" CFLAGS = -D@FOO@
AC_SUBST(FOO)
則執行 configure 後會產生 Makefile 包含以下片段: CFLAGS = -Dhello
* 2. 編輯 Makefilea.am , automake 根據 configure.in 中的巨集,將 Makefile.am轉變成 Makefile.in, 執行 automake --add-missing --copy 即可。
--add-missing 將包裝好 configure 所需之檔案補齊( 預設為 link 的方式 )
--copy 所需的檔案以 copy 的方式補齊
automake 支援、認可的 configure.in 巨集
----------------------------------------------------------------------
AC_INIT_AUTOMAKE(package, version)定義 PACKAGE、VERSION 兩變數
AM_CONFIG_HEADER( header.h )讓 automake 產生可自動再生成 header.h 的規則,使用此巨集必須先定義stamp-h.in, 用於標記 header.h 產生的時間。
AC_CANONICAL_HOST
AC_CHECK_TOOL automake 會確認 config.guess 及 config.sub 的存在。config.guess 用於猜測系統類型、config.sub用於提供檢查工具。
Makefile.am 選項說明
----------------------------------------------------------------------------
AUTOMAKE_OPTIONS設定 automake 的選項。Automake 主要是幫助開發 GNU 軟體的人員維護軟體套件,所以在執行 automake 時,會檢查目錄下是否存在標準GNU 軟體套件中應具備的文件檔案,例如 'NEWS'、'AUTHOR'、'ChangeLog'等文件檔。設成 foreign 時,automake 會改用一般軟體套件的標準來檢查。
SUBDIRS automake 會產生能夠遞迴進入指定目錄的 Makefile 規則。
bin_PROGRAMS定義我們所要產生的執行檔檔名。如果要產生多個執行檔,每個檔名用空白字元隔開。
hello_SOURCES定義 'hello' 這個執行檔所需要的原始檔。如果 'hello' 這個程式是由多個原始檔所產生,必須把它所用到的原始檔都列出來,以空白字元隔開。假設 'hello' 這個程式需要 'hello.c'、'main.c'、'hello.h'三個檔案的話,則定義hello_SOURCES= hello.c main.c hello.h
如果我們定義多個執行檔,則對每個執行檔都要定義相對的 filename_SOURCES。
pkgdata_DATA將 pkgdata_DATA 所指定的檔案安裝到 pkgdatadir 指定的目錄,*_DATA 對應*dir,如 localstate_DATA 安裝至 localstatedir。
EXTRA_DIST在 make dist 時將指定的檔案一起打包。
AC_PREREQ確保使用的是足夠新的Autoconf版本。如果用於創建configure的Autoconf的版本比version 要早,就在標準錯誤輸出列印一條錯誤消息並不會創建configure。
AC_CONFIG_SRCDIR([main.c])用來偵測所指定的源碼檔是否存在,來確定源碼目錄的有效性。
AC_CONFIG_HEADER([config.h])用於生成config.h檔,以便autoheader使用。
* 3. 建構 GNU build 系統aclocal -> autoheader -> autoconf -> automake
GRUB中文指南
我想到此就可以知道大概了;可以直接到makefile
--> 閱讀更多...

原來....我也是生存在這種輪迴之中

今天爬文不小心看到以下這一小段:
標題:大學生不如美女值錢.
苦工-----資本家----美女----苦工
這樣的資金流動在中國比較流行.
苦工勞動生產產品,資本家得到最大利益,
得到最大利益的資本家,本性需求高,花錢包美女
美女,愛美,愛花錢,買產品,
在這個資產迴圈中美女,是一重要因素.當然核心不是資本家.

看了之後‧‧‧‧‧‧
我想人生中至少也有美好的事物,若是硬要以物質衡量,那心靈方面的滿足又算什麼?
--> 閱讀更多...

2010年4月15日 星期四

學習GRUB Programming初啼

GRUB(Gran Unified Bootloader)是個bootloader,為何我對它這樣著迷,其實應該說道理還是一樣,它看起來不大,而且目前已經可以支援ATA SATA USB CDROM 等開機,因此絕對可以學到很多實作及概念並認識各式檔案系統如何運作,未來將OS安裝在USB DEVICE的狀況將會越來越常見 .重點當然也是因為它和linux kernel比較起來小很多,我想trace code應該也會比較得心應手.說真的像linux kernel那麼大也別想用source insight來管理,就連U-Boot都有點吃力了.所以越大的project還是要在linux環境來trace code,較沒有效能上的疑慮.然而我實際編譯一次後才發現它的檔案量還真不少,install到系統的模組也有1百多個;網上相關的編程教學也少的可憐;看來是要自立自強了。
一開始只知道它的評價比LILO好,其他說真的還一無所知.首先先來點開味菜ㄅ:雖然本文並非討論GRUB如何使用,但trace code需要的狀況還是會稍微提到。
configure及makefile;這個makefile是執行configure shell script後產生的;這是很正常的程序,只是我覺得寫這個shell script的人不正常。
然而實際上configure這個shell script也是自動產生的;說著說著好像越來越模糊了。說真的我越來越怕看到(自動)這兩個字了;因為那表示又有一些相關技術要k了。果然網上隨便輸入"automake" "autoconf" "makefile" "makefile.am" "makefile.in"等關鍵字保證又是一堆資料等著你去把相關知識給整合起來。要完成一個自動產生的makefile,流程大概如下:
1.autoscan 產生一個 configure.scan,更名為 configure.in
2.修改 configure.in 的內容
3.執行 aclocal 和 autoconf,分別會產生 aclocal.m4 及 configure 兩個檔案
4.使用編輯器,建立 Makefile.am 檔
5.使用 automake --add-missing 將 Makefile.in 產生出來
6.執行 ./configure,產生makefile
然而在grub project裡頭將以上幾個步驟寫成autogen.sh shell script內容如下:而且它的實作方式稍微不同,它不採用makefile.am
#! /bin/sh
set -e
aclocal
autoconf #到此產生configure
autoheader
# FIXME: automake doesn't like that there's no Makefile.am
automake -a -c -f true
echo timestamp > stamp-h.in
python util/import_gcry.py lib/libgcrypt/ .
for rmk in conf/*.rmk ${GRUB_CONTRIB}/*/conf/*.rmk
do
if test -e $rmk ; then
ruby genmk.rb < $rmk > `echo $rmk sed 's/\.rmk$/.mk/'`
fi
done
sh gendistlist.sh > DISTLIST
exit 0
雖然不到20行,但是卻牽扯到python、sed、ruby,所以我說學習shell programming並不簡單,應該是說你不可能只學習一種script語言;這樣會使你創作能力降低,但要一下子就搞這麼多東西;我想我會瘋掉、會瘋掉。更何況有用的script還有像perl、awk‧‧‧就是說光想在linux上programming;並不是想像中那樣;但script畢竟是比較簡單;雖然很多人總寫出一堆令人費解的敘述;寫到這裡不禁感嘆:年事已高的我,未來的路還很長。
無論我們是否要搞懂這個autogen.sh,至少要知道這個檔是否對未來整個專案的理解有很大關聯;所以實際去執行./configure後直接把makefile打開來看;果不其然還真有寸步難行之感。所以還是要乖乖就範,把這個autogen.sh給搞懂;因為它和之前描述的那6個步驟作法不同,也沒有執行autoscan所以沒有configure.scan,因此就不會有configure.in。不使用makefile.am,有看到執行automake,但是卻早有makefile.in這個檔案;總之用ㄌ一些自動化的工具卻不走正統路線;所以只好再去找一些相關資訊,例如:GNU Coding Standards FreeBSD Porter 手册 autoconf 和 automake 生成 Makefile 文件。
原來GRUB使用configure.ac,我想接下來應該是把重點擺到這個檔案上。因為aclocal是一個perl 腳本程式,它的定義是:aclocal - create aclocal.m4 by scanning configure.ac 。
終於好不容易找到了以下連結可供參考:Configure Makefile.am Makefile.in Makefile文件之間關係 automake Introduction英文 簡體 GRUB 運作原理
--> 閱讀更多...

2010年4月14日 星期三

DOS記憶體管理

DOS不管電腦擴充了幾MB的記憶體, 當你用MEM.EXE 來觀察時, 傳統記憶體(Conventional memory) 固定都只有640K Bytes。這640KB 就是一般應用程式所能使用的範圍。如果你使用5.0 版以前的DOS,進入中文糸統, 再要執行其他較佔記憶體的應用程式時, 就有可能產生 "記憶體不足" 的訊息, 不管你在640K以外還有多少記憶體。而現在DOS 5.0 最為人稱道的地方, 就是它提供了許多管理記憶體的方法, 讓程式有更多的記憶體空間可以運用。
DOS 5.0 提供的記憶體管理, 指的是位址為640K以上的記憶體。如果你的電腦只有640K 的RAM, 那麼DOS 5.0 對你就沒有多大用處。一般電腦最基本配備有1 Mega的記憶體, 就有384 K 的延伸記憶體可以運用。記憶體容量愈大, 運用範圍愈廣。像WINDOW這類多工軟體, 就需要龐大的記憶體來增加其速度。
640K的傳統記憶體
640K的限制由何處來的? 這必須回顧PC和CPU 的歷史。CPU 的定址能力, 是由硬體線路所限定的。在早期APPLEⅡ 使用的6502 CPU, 它是8 位元的微處理機, 故具有8 條的資料線路。其資料處理是以位元組(Byte)為單位, 每一個Byte可表示2^8 = 256 種數字。同時它用兩個Byte的組合來指示記憶體的位址。因此它須具有16條的位址線路, 共可表達2^16 = 65536 =64K 種的位址。換句話說, 16條的位址線路的定址能力的最高限制就是64KB 。1978年Intel 公司推出16位元的8086微處理機, 以16位元的字組( Word,相當於兩個Byte) 為資料處理的單位。位址線路則增加到20條;因此必須用兩個Word來表示記憶體的位址。這兩個Word如果也採用線性對映的定址方式, 那麼共可表示: 2 ^32 = 2^2x2^10x2^10x2^10 = 4 x K x K x K = 4G 種的位址!這在當時看來是軟硬體皆不可能達成的數字。更何況位址線又沒有32條,只有20條而已, 就是說實際定址能力的最高限制是2^20 Bytes = 1MB。那時的RAM 也很昂貴, 所以認為1MB (是64KB 的16倍) 是夠大的了。
因此8086採取了重疊對映的定址方式 (悲劇的開始!)。由兩個Word以XXXX:YYYY 的方式來組成一個20位元的線性位址, 前者為節區段位址(Segment),後面稱偏移段位址(Offset)。
公式如下:Address = Segment * 16 + Offset
格式:Segment:offset =>(段位址):(偏移位址) =>1 2 3 4 : 2 3 4 5
1 2 3 4 0
+2 3 4 5
(真實記憶體位址) --------------
1 4 6 8 5 h
以上的記憶體位址是16進位數字, 在數字後面附加小寫h 來表示。例如: 640K (10進位) = A0000 h = A000:0000 等到1982年, 藍色巨人IBM 推出最早型的IBM PC XT,以Intel 8088微處理機作為CPU,8088與8086都只有20條位址線(A0~A19) 。IBM 對可定址的1MB 記憶體位址做個規劃, 其中最前面的640K RAM供DOS 與應用程式使用, 這塊區域叫主記憶體(Base Memory) 或傳統記憶體。640K到1MB 的記憶體區域保留給外加擴充的界面卡和BIOS使用, 這塊區域叫上層記憶體 (Upper Memory),一般應用程式不可輕易動用。這也就是DOS和一般應用程式最多只能控制640K的原因。
1983年Intel 推出了80286, IBM立刻選用為最新的CPU,於1984年底推出IBM PC AT(AT是Advanced Technology 先進技術之意) 。80286 是真正的16位元微處理機(CPU內部與I/O 均以16位元處理),運作速度更快。它有24條位址線, 故最多可存取2^24 = 16MB 的記憶體。
事實上80286 採用了兩種定址模式:一、真實模式 (Real Mode)在此模式下,286使用和8086/8088 相同的重疊對映的定址方式。這是為了讓原有的DOS 和應用程式能在PC AT 上相容使用。因此, 在真實模式下, 也只能控制1MB 記憶體而已。二、虛擬保護模式 (Virtual Protected Mode)在保護模式下, 才能隨意使用1MB 以上的記憶體。後來陸續推出32位元的80386和80486 (皆有32條位址線),又提供了功能更強的保護模式。但是也都保留了真實模式, 以滿足往前的相容。MS-DOS改版至今, 一直是在真實模式下運作。對於在286/386/486超過1024K 的記憶體, 只能拿來當虛擬磁碟機, 或硬碟快取程式(Disk cache), 或者使用一些其他的驅動程式 (如EMM或XMM) 來支援, 而不能像在傳統記憶體一樣方便的使用。 擴展記憶體和延伸記憶體早在XT時代, 一些大型軟體就有記憶體不足的困擾了。因此, Lotus/Intel/Microsoft三家公司共同制定了一個擴展記憶體規格(Expanded Memory Spec.;EMS),採用記憶庫切換(bank swapping) 的方式來指定位置段落。擴展記憶體規格(EMS) 包含了硬體的EMS 擴充界面卡, 和軟體的管理程式(Expanded Memory Manager ;EMM)。這種EMS 記憶體就是擴展記憶體 (Expanded Memory) 。
隨著PC AT 的普及, 程式可透過保護模式存取位址為1MB 以上的記憶體。這些位址為1MB 以上的記憶體就稱為延伸記憶體( Extended Memory) 。為了避免各程式取用的延伸記憶體的區域相衝突, Mircrosoft、Intel、Lotus等公司制定了一個延伸記憶體規格(Extended Memory Spec. ;XMS), 規定了高記憶區、上層記憶體與延伸記憶體的存取標準。一般的程式只要呼叫管理程式(eXtended Memory Manager ;XMM), 就能有效運用XMS 的資源。像MS-DOS 5.0的HIMEM.SYS 就是符合XMS 標準的管理程式。
Expanded(擴展)表示向橫的方向擴展, Extended則是縱向的延伸。EMS 和XMS 不同的地方是: EMS 是XT時代發展出的規格; 擴展記憶體、EMS 卡是隨著EMS 發表的, 它的重點是在1024K 的定址範圍內使用更多的記憶體, 實際的定址限制仍是1024K。
XMS 則是在有了延伸記憶體之後才訂定的規格, 用來管理640K以外的記憶體。延伸記憶體可用軟體方式模擬成EMS 標準, 讓只支援EMS 的較早期程式也能夠使用。如果你要擴充記憶體容量, 且你的主機板上仍有空的記憶體插槽,就可直接買RAM 來插, 即增加延伸記憶體, 就可做為XMS 或EMS 使用,也比EMS 卡便宜。若您的主機板上已無空的記憶體插槽, 那只好買EMS卡來插在擴充槽上了。有些EMS 卡上有開關, 可將卡上的記憶體調成延伸記憶體; 否則就只能當做擴展記憶體了。
EMS 使用記憶庫切換的方法, 在有限位址內使用更多的記憶體, 事實上只解決資料的問題, 要執行程式仍然很麻煩。這方法和SuperVGA的切頁方式類似, 若用SuperVGA則較容易理解 "切頁對映" 的觀念。PC分配給彩色螢幕的視訊對映位址只有64K (A0000h ~ AFFFFh),而SuperVGA若要顯示1024x768x256色的模式, 則需要768K 的記憶體(所以SuperVGA卡要有1MB RAM), 64K 的位址如何夠用呢? SuperVGA就把這1MB RAM 分成16個64K 等分,CPU每次可存取其中的64K,而用一個暫存器來選擇切換。
高記憶區 HMA 與 上層記憶區塊 UMB 雖然一般程式在真實模式下只能使用640K, 但DOS 5.0 提供了HMA和UMB 記憶區的使用, 在真實模式下突破了640K的限制。約64K 的高記憶區 ( HMA, High Memory Area )真實模式下的最大位址可達FFFF:FFFF = 10FFEF h的位址, 這已超過真實模式的1 Mega上限。所以多出來的100000h 到10FFEFh 就會捲繞(wrapping)重新對映到位址0 ~FFEFh 的地方。對286 以上的CPU,如果將位址線A20 致能(enable), 則不會發生捲繞, 多出來的這64K-16bytes就是HMA 。一般說HMA 有64K,其實是64K - 16 bytes 。上層記憶區塊 ( UMB, Upper Memory Block )PC把位址為640K到1MB (即A0000 h ~FFFFF h) 的上層記憶體, 規劃給界面卡和BIOS使用。這部分的ROM 除了系統BIOS是在主機母板之外, 其他的ROM (或RAM) 則是在使用該位址的界面卡上。
通常我們都只用到上層記憶體的位址的一部分而已, 其他可用的位址就浪費掉了。使用DOS 5.0 的EMM386.EXE, 可以將這些沒有使用到的上層記憶體位址, 改成對映到延伸記憶體上, 就叫做UMB 。這樣你在真實模式下, 就又多出一部分可使用的位址了。
這些多出來的UMB 記憶體, 通常用來存放各種佔記憶體的驅動程式和常駐程式, 儘量空出傳統記憶體空間來執行大型程式。
UMB 依據個人週邊配備和設定的不同, 約可多出60K~200K 左右的可使用位址。EMM386.EXE就是管理UMB 的工具。QEMM386 (Quarterdeck公司的軟體) 功能比EMM386強大,不用加參數即可規劃出最大的可用UMB, 因此很多人使用。但你還是要瞭解EMM386, 以便可隨時更替, 因為EMM386的功能較穩定。
使用EMM386必須自行指定可用位址。若不指定則EMM386自行規劃的UMB 空間有限。EMM386.EXE 可用的參數如下 :
NOEMS : 不模擬EMS 的功能, 但要使用UMB 。
RAM : 將記憶體模擬EMS , 且要使用UMB 。
RAM=xxxx-yyyy : 則將兩個段位址之間的記憶體留給UMB用。
size : 設定EMS 的大小, 需為16的倍數。自定值為256KB。
FRAME=xxxx : EMS 的映射頁框, 會佔用掉64KB的UMB 。
I=xxxx-yyyy : 指定段位址xxxx~yyyy可做為UMB 供LOADHI。
X=xxxx-yyyy : 避開段位址xxxx~yyyy不可做為UMB 。
EMM386自定的UMB 使用位址為C800~DFFF (共96K),若介面卡用到此位址, 則須以參數 X= 避開。
要瞭解I/O 界面卡的位址分配, 才知道那些位址可以使用或該避開。若是界面卡位址(如倚天卡版)是可調整的, 則可儘量留下最大可用的UMB 空間。
640K 到 1 Mega 的 I/O 位址分配 :
A0000 h ~ AFFFF h (64K) 彩色螢幕圖形介面
B0000 h ~ B7FFF h (32K) 單色螢幕圖文介面
B8000 h ~ BFFFF h (32K) 彩色螢幕文字介面
C0000 h ~ C7FFF h (32K) 彩色螢幕 BIOS 程式碼存放區
C8000 h ~ CFFFF h (32K) SCSI/ESDI 硬碟控制卡
D0000 h ~ DDFFF h
DE000 h ~ DFFFF h ( 8K) 倚天中文卡字型ROM 預設位址
*E0000 h ~ EFFFF h (64K) 通常是未使用, 可做UMB 。
F0000 h ~ FFFFF h (64K) 系統 ROM BIOS
顧名思義, EMM386.EXE只能用在386 或486 的PC, 若你使用286 的PC AT,就無法使用UMB 的功能了。 使用 HIMEM.SYS 和 EMM386.EXE 在原始情況下, DOS 5.0 大約佔60K 的傳統記憶體。你可以把根目錄下的CONFIG.SYS和AUTOEXEC.BAT刪除 (或用REN 更名),重新開機後,再用 MEM /C 來觀察, 則傳統記憶體的使用情況如下(註1):
> \dos\mem /c (未加config.sys和autoexec.bat的情況)
MSDOS 57184 ( 55.8K) DF60
COMMAND 4704 ( 4.6K) 1260
FREE 593328 (579.4K) 90DB0
接著如果你使用HMA,則可將約45K 的DOS 核心搬移至HMA 中, 而有約17K 的DOS 碼留在傳統記憶體中。要使用HMA,則須在CONFIG.SYS檔中加入HIMEM.SYS,和 DOS=HIGH 這兩行。作法和觀察步驟如下:
> copy con \config.sys device=\dos\himem.sys dos= high ^Z ( 按F6, Enter )
( 重新開機後 ) > \dos\mem /c
( 使用HMA 的情況 )
MSDOS 12.5K HIMEM.sys 1.2K
COMMAND.com 2.6K
FREE memory 623.6K
而且用MEM 觀察的結果, 可使用的XMS 記憶體剛好減少了64K,確實是被拿去當HMA 使用了。計算的方法, 是將全部(total) 連續延伸記憶體, 減掉可用(available) 之XMS 延伸記憶體, 則等於65536 bytes,再除以1024即為64K。 如果你使用HMA 並且在CONFIG.SYS檔中設定 BUFFERS=n 這個命令,那麼磁碟緩衝區(disk buffer) 也會自動置於HMA 中。磁碟緩衝區的設定個數, 一般是根據硬碟的容量大小來設定。大容量硬碟的BUFFERS 若太小, 則速度會變慢。以下是一些參考數據:
40 MB 以下 : BUFFERS=20
40 至 79 MB : BUFFERS=30
79 至119 MB : BUFFERS=40
120 MB 以上 : BUFFERS=50
如果HMA 不足以放下所有的磁碟緩衝區, 剩餘部分也會自動轉到傳統記憶體去儲存。事實上HMA 除了放DOS 核心程式外, 約可再放下44個BUFFERS,因此若你的硬碟容量不大, 則可設 BUFFERS=44。
接著要使用EMM386.EXE來管理UMB,則要加上 DOS=UMB 命令,且需在HIMEM.SYS 下使用。以下是使用HMA 和UMB 的CONFIG.SYS 基本內容:
device=\dos\himem.sys
dos=high umb
device=\dos\emm386.exe noems i=e000-efff
buffers=44
files=30
注意HIMEM.SYS 必須在第一行, 因為所有的XMS 功能都經由它處理。重新開機後, 由開機訊息或MEM/C 觀察, 發現增加了約160K 的UMB可以使用; 但可使用的XMS 記憶體竟然又少了245K。這是因為UMB 的位址並非連續可用的, 所以XMS 無法百分之百轉換為UMB 使用。
若你使用單色螢幕, 那麼趕快在EMM386這行後面再加個參數如下:
device=\dos\emm386.exe noems i=e000-efff i=a000-afff
重新開機後, 再以MEM 觀察, 發現傳統記憶體居然變成704K (多了64K), 連可執行的程式最大容量也增加了! 這是使用單色螢幕 386/486才有的特權。
以下再列出彩色/單色螢幕的CONFIG.SYS 設定實例 :
彩色 386/486
DEVICE=\DOS\HIMEM.SYS
DOS=HIGH UMB
DEVICE=\DOS\EMM386.EXE NOEMS I=C800-EFFF
BUFFERS=50,8
FILES=30
單色 386/486
DEVICE=\DOS\HIMEM.SYS
DOS=HIGH UMB
DEVICE=\DOS\EMM386.EXE NOEMS I=A000-AFFF I=C000-EFFF
BUFFERS=50,8
FILES=30(若只有384K延伸記憶體, 則不夠UMB 使用, 第二個I=要改成C600-EFFF)有了UMB 以後, 要執行常駐程式就可使用LOADHIGH (可簡寫為LH)命令來把常駐程式載入到UMB 了。同樣也可寫在AUTOEXEC.BAT等批次檔中。若是由CONFIG.SYS設定的驅動程式, 則把DEVICE= 改用DEVICEHIGH=來載入。但並非每個程式都可放到UMB,如 SMARTDRV 就不適合。使用UMB 的實例如下: DOS命令或用在.BAT檔中 :
LH DOSKEY
LH APPEND C:\TC\LIB;C:\JB;
CONFIG.SYS 檔的設定中 :
DEVICEHIGH=\DOS\ANSI.SYS
DEVICEHIGH=\MOUSE.SYS 2
若是UMB 客滿了, 常駐程式會自動轉置於傳統記憶體中。你可用MEM/C來觀察傳統記憶體和UMB 的使用情形。 節省記憶體的其他技巧 DOS 使用HMA 和UMB 在真實模式下作出最後的"掙扎", 但HMA和UMB增加的記憶體終究有限, 若是那天還是碰上"(傳統)記憶體不足"時要怎麼辦呢? 就只有找出下列的最後掙扎的最後技巧了。
1. 在CONFIG.SYS中加入下列命令: STACK=0,0
FCBS=1
一般應用程式很少用到STACK,設為0 可省下1K左右。而FCB 更是很落伍的軟體才用得上的。FCBS=1可省下176 bytes 。
2. 設定BUFFERS 值小一點, 例如44以下。
3. 減少FILES 值 (可開檔數目),每少一個可省下53 bytes 。
4. 檢討UMB 位址是否充分利用, 重新設定參數。或者改用QEMM386.SYS來代替 EMM386.EXE 和HIMEM.SYS 。
5. 審視所有的驅動程式和常驅程式, 沒用到的不要載入系統, 或是儘量LOADHI。如果你只在WINDOW中使用滑鼠, 可把外部的滑鼠驅動程式(如:MOUSE.COM)拿走, 因為WINDOW有自己的滑鼠驅動程式。 虛擬磁碟和磁碟快取用完了HMA 和UMB 剩下來的延伸記憶體, 對一般應用程式都用不著了, 要如何處理呢? 如果你只有384K的延伸記憶體, 也用得差不多了,就到此為止。如果你還有更多的記憶體, 就可拿來作虛擬磁碟, 或是作磁碟快取區, 來減少硬碟的讀取磨損, 並加速系統的運行。 但首先你要瞭解自己還剩下多少可使用的記憶體, 這可用MEM 來觀察, 再除以1024得到K 數。另外倚天中文3.1 版可將字型檔等載入延伸記憶體; 所以你要先執行中文系統(3.1版) 再執行MEM , 才能確定剩下多少延伸記憶體可以使用。如果還使用WINDOW等其他會使用延伸記憶體的軟體, 就需要再調整分配。 虛擬磁碟(Virtual Disk 或 RAM Disk)是以記憶體模擬磁碟, 存取檔案的速度比硬碟快, 適用於處理大量檔案或經常讀取的資料。但注意若是寫入資料到虛擬磁碟, 最後記得要轉存到硬碟上, 否則電源一關,記憶體的資料就消失了。磁碟快取(Disk Cache)是將較重要或經常讀取的硬碟資料, 存在磁碟快取區, 若有磁碟I/O 時, 就可直接從快取區拿取資料。一、虛擬磁碟工具: RAMDRIVE.SYS在 CONFIG.SYS 的設定實例:
DEVICE=\DOS\RAMDRIVE.SYS 320 512 120 /E
說明:
第一個參數: 320,使用虛擬磁碟的K 數。此值需是64(K) 的整數倍。
第二個參數: 512,每個磁區的bytes 數。512 與磁碟磁區大小一致。
第三個參數: 120,根目錄下最多可存放的檔案和子目錄個數。
參數 /E 表示使用延伸記憶體。若是 /A 則使用擴展記憶體。
不設定 /E 或 /A 則使用傳統記憶體。
二、磁碟快取工具: SMARTDRV.SYS在 CONFIG.SYS 的設定實例: DEVICE=\DOS\SMRATDRV.SYS 1024 說明:
第一個參數: 1024, 使用磁碟快取區的K 數。此值最少為128 (K)。
第二個參數: 沒設, 這是快取區的最小K 數。若使用WINDOW等會佔用延伸記憶體的軟體, 快取區會自動調成此值。另外,參數 /A 表示使用擴展記憶體,沒設則自定使用延伸記憶體。
若是你有PC-CACHE.COM或NCACHE.EXE等其他功能較強的磁碟快取程式, 可用來取代DOS 的SMARTDRV, 參數用法請參考相關的說明書。DOS 的RAMDRIVE.SYS和SMARTDRV.SYS都需配合HIMEM.SYS 使用。---------------------------------------------------------(註1) 表中MSDOS 的數值是只有一部硬碟C 的情況。若還有硬碟D,則 MSDOS 的大小是57312 Bytes,否則有可能是感染病毒。另外如果有AUTOEXEC.BAT, 則有64 Bytes的FREE區, 為環境變數區。 MEM/C 所觀察的UMB 第一項為64K ~160K 的SYSTEM, 是表示 UMB 分配給系統I/O 或ROM-BIOS使用之數量。
掛載EMM386.EXE時,碰到預期外的行為時,考慮以下列參數選項來解決:X = a000-f7ff
如果不包括整個上層記憶體區域 (UMA) 可以解決系統問題,EMM386.EXE 可能會太積極地掃描,以及設定上層記憶體區塊 (UMBs) 在一些介面卡的最上層 ROM 或 RAM。使用任何可用的硬體文件 (包括附加元件的硬體裝置,例如視訊、 網路,以及磁碟控制器卡上的文件),來識別任何 ROM 或 RAM 出現在 [UMA 中為該裝置,並排除所有相關的區域。如果硬體文件無法使用,或者並不會提供必要的資訊,您可以使用 [Microsoft 診斷公用程式 」 (MSD) 來識別記憶體區域。
NOEMS
如果 NOEMS 參數已修正與 EMM386.EXE 問題,EMM386.EXE 可能與某些硬體 ROM 或 [UMA 中的 RAM 位址不慎衝突時嘗試建立擴充的記憶體 (EMS) 頁面框架。如果執行檢查 DOS 為主的應用程式所需 EMS,使用參數框架 = 或 M (是已定義的十六進位位址) 明確地指定 nonconflicting 區域中的 [EMS 頁面框架的位置。如果沒有應用程式需要 EMS,只是繼續使用 NOEMS 參數。
NOVCPI
NOVCPI 切換控制會停用虛擬控制項程式介面 (VCPI) 支援,並且可以用於只能在配合 NOEMS 參數中。 如果使用 NOVCPI 更正問題,應用程式可能不是與 EMM386.EXE VCPI 配置配置完全相容。請繼續使用 NOVCPI] 參數,或使用應用程式時不要載入 EMM386.EXE。
NOMOVEXBDA某些機器使用最後的千位元組的傳統記憶體擴充的 BIOS 資料區域。預設情況下,EMM386.EXE remaps 這個記憶體區域到 UMA,而非傳統記憶體。如果這會導致未預期的系統行為,NOMOVEXBDA 參數必須用。
NOTR
EMM386.EXE 有偵測程式碼,以搜尋權杖環網路介面卡的存在。此偵測程式碼可能會造成某些電腦停止回應。NOTR 切換來停用此搜尋。


P.S. 回顧

在最初的x86的硬體結構下,真實模式下不能存取1M以上記憶體。這1M的記憶體可以分為前640K常設記憶體和640K到1M的高端記憶體(UMA)。但是在主機板設計人員的努力下,x86的真實模式可以通過頁切換機制把主機板上的1M以上的記憶體區(EMS/XMS)映射到高端記憶體區,從而可以實現真實模式下對EMS/XMS的讀寫。所以並不是只在保護模式下才能讀寫EMS。否則,很多較大的DOS應用都無法運行了。當然對於dos程式師來說,需要一些特定軟體的支援。EMS和XMS就是兩種1M以上記憶體存取軟體介面的規範。具體的產品就有我們熟悉的Himem.sys和emm386.exe。這兩種介面實際上都是OS的陷阱。當你調用這些介面時,陷入dos內核,himem或emm的代碼將負責把EMS/XMS映射到UMA中。這兩種介面具體的實現機制有一些差別,可以查看相關的資料。但是這種介面只能在EMS/XMS中存放資料,存放的代碼將無法運行。所以程式的程式碼片段仍然必須駐留在1M以下的常設記憶體中。所以前640K對於程式師仍然是一個潛在的障礙。如果你的程式碼段的長度超過了640K(實際上還要小一些),你就會得到在dos下最常見的資訊"not enough memory under 640K",儘管實際上你可能安裝了16M或更多的記憶體。當然,這些都是歷史了。不過瞭解一下這些歷史,會幫助你更好地理解今天的電腦。

--> 閱讀更多...

himem.sys及emm386說明


himem.sys及emm386說明轉載自http://club.it.sohu.com/r-os-239366-0-13-900.html
DOS的環境下,系統中存在以下四種記憶體:
   常規記憶體(Conventional Memory)
   高端記憶體(Upper Memory)
   延伸記憶體(Expanded Memory) EMS
   擴展記憶體(Extended Memory) XMS
DOS在實模式下,能直接定址的範圍是1MB。而這1MB分為640KB的常規記憶體和384KB的高端記憶體,加在一起就是1024KB也就是1MB。因為DOS使用16位段基址:偏移量格式(segment:offset),只能使用低端的640KB,這就是有名的640KB限制。其中最低端的1KB,即00000H~003FFH存放的是中斷(IRQ)向量表;接下來是256B(0FFH)的BIOS資料區;DOS及應用程式使用00500H~9FFFFH。這在開始使用DOS的20世紀80年代是完全能夠滿足要求的,因為當時PC上安裝的實體記憶體容量也是640KB,甚至更少。(前面地址中的H代表16進制)系統硬體使用的記憶體位於位址區域的高端,範圍是A0000H~FFFFFH,共384KB。其中有用於顯示的視頻緩衝區和BIOS程式空間,例如顯卡,網卡和主板BIOS。
地址FFFF0H在PC中有特別的用途。
電腦在加電啟動時,CPU中的CS=F000H,IP=FFF0H,即從位址FFFF0H處開始執行,這個區域屬於系統BIOS。F000:FFF0=EA5BE000F0(是JMP F000:E05B指令的十六進位表示),它立即跳轉到BIOS的初始化程式,開始系統自檢。(這段跟DOS沒有關係,只是查資料時看到了,就也寫上了。是想讓大家知道,在按下主機電源開關後,CPU都做了些什麼,為什麼BIOS開始工作,自檢硬體設備)
最後我附了一張圖,本來想自己畫的,可一搜發現已經有人畫好了,並且畫的肯定比我好,我就用人家的圖了,一看這個,肯定就清楚多了,比文字怎麼寫的都強。
上面說的延伸記憶體是一種硬體,那個年代的主板專門預留了擴展槽,可以插上,我是沒見過。擴展記憶體就是記憶體條上大於1M的部分,通過DOS下的一些驅動可以將XMS的一部分虛擬成EMS,以滿足一些為EMS開發的程式的需要。
中間有一段叫高端記憶體,指位於常規記憶體之上的384K記憶體。程式一般不能使用這個記憶體區域,但是EMM386.exe可以啟動高端記憶體的一部分,並且它允許用戶將某些設備驅動程式和用戶程式用Devicehigh或LH(即loadhigh)裝入高端記憶體。dos=high,umb也是把DOS的一部分裝到高端記憶體裏。這裏的umb是高端記憶體塊(Upper Memory Block)的縮寫。(以後我會專門寫config.sys的部分)
DOS的程式,主要還是要使用常規記憶體的,如我刷HP筆記本的BIOS的時候,連點Shift進入最小的DOS模式也就是為了節省640K這部分的空間,以便讓HP的刷寫程式有足夠的空間運行,不然刷寫程式就要報錯,就算XMS再大也沒用。
還有一個叫DOS4GW.EXE的程式,在DOS玩過一些大一些的遊戲如仙劍,紅警等,在啟動的時候,有時候能看到有個DOS4GW一閃而過,它可以使用CPU直接進入保護模式,直接訪問XMS,不過這時就已經脫離了DOS狀態。後來的Windows 3.x,95,98也都運行在保護模式下的,但都需要DOS帶一下。
有些東西要看一下計算機組成原理或彙編之類的書才能理解,尤其是記憶體的定址與CPU的寄存器(上面提到的CS,IP等)。提到了DOS的記憶體管理,從前文的圖中,大家也看到了EMM386.EXE與HIMEM.SYS,這是實際管理記憶體的模組。
EMM386.EXE從名稱上可以很真接的看出,這個是要在386以及之後的CPU上才可以使用的,它的作用是利用XMS創建出EMS,以前的DOS也有N多版本,有的叫EMM386.SYS有的叫EMM386.EXE,在我使用過的DOS我只見到過EMM386.EXE。像其他的擴展記憶體管理一樣EMM386使處理器虛擬8086的模式。而在386增強模式中,視窗會話期間會臨時關閉,同時在視窗保護模式中內核會接管它的角色。最終的作用是在UMA中,EMM386.EXE會把記憶體映射成未使用的塊。允許設備驅動和TSRs(我也不知道是什麼東西)被載入到UMA中,而保留那可憐的640K的常規記憶體。
HIMEM.SYS也是一個DOS設備驅動,他允許DOS程式把資料存到XMS中去。HIMEM.SYS實際上是非常重要的,後來的多種Windows作業系統(本質上底層是依賴於DOS)都需要先載入HIMEM.SYS之後才能正常運行。
從MSDOS 5.0起,HIMEM.SYS被用來把DOS內核的部分代碼載入到HMA中,目的同樣是為了節省那640K的常規記憶體。在config.sys用dos=high設置,config.sys的詳細資訊,後文會有涉及。
HIMEM.SYS提供了一種訪問超過1M實體記憶體的方法,而這正是windows 9x/me作業系統載入圖型化介面所必需的,看前面的圖很清楚,EMM386.EXE的管轄範圍是640K向上到1M之間這部分共384K被稱作上位記憶體UMA的區域。而HIMEM.SYS管轄的是1M再向上的部分,而從1M開始有一小段叫高位記憶體HMA,專門用來放一部分DOS內核。
--> 閱讀更多...

2010年4月12日 星期一

Novell Netware3.12安裝在VMware Workstation 6.5(中)

圖一
圖二
圖三
圖四
要安裝SYS卷及public公用程式的安裝比較簡單所以我只把圖show出來。流程大致上是1.check HD partition 2.create SYS volume產生系統卷 3.copy System and Public Files。設定過程使用預設值便可。首先進入system console後輸入load install。
--> 閱讀更多...

2010年4月11日 星期日

Novell Netware3.12安裝在VMware Workstation 6.5(下)

圖DONE
圖一圖二圖三圖四圖五 圖六 圖七 圖八 圖九 圖十 圖十一 圖十二圖十三
安裝312ptd patch
將312ptd.exe解壓縮後:312PTD.TXT及312PTD(directory),我列出312ptd.txt最重要的部分如下:注意312PTD資料夾包括PATCH312.NLM及NATIVE資料夾
INSTALLATION INSTRUCTIONS
1. Extract the file on the SYS Volume.將PATCH312.NLM及NATIVE資料夾存放到C:\server.312
2. At the server console prompt type "LOAD PATCH312".
3. At the prompt select "Copy OS Patches to Server".
4. At the prompt to Enter Patch Source Path type SYS:312PTC. (Or directorypath where the file was extracted.)
5. Select EXIT when the file copy is finished.
6. DOWN and EXIT the server and restart.
實際安裝Patch的畫面如上圖一~圖五;另外會出現圖四是正常,若在安裝完系統卷後有去create autoexec.ncf就不會有這個問題。但以後我們再來新增autoexec.ncf也沒關係。
安裝odi33g patch
將odi33g.exe解壓縮後:有ODI33G.TXT、ODIKIT.IPS、PI_ICMD.NLM、PI_IOCON.NLM、PI_IOMKD.NLM、SERVER資料夾、RPL資料夾。以下列出ODI33G.TXT的重要安裝資訊:
Installation Instructions on 3.1X/3.2 versions of NetWare:
1) Extract ODI33G to a Network drive on the file server. If you are using diskettes to install ODI33G, you will need to format two diskettes. Labelone diskette "SERVER" and the other "RPL" using the dos label command. Copy all of the files (including subdirectories and files) in the Serverdirectory of ODI33G to the diskette labeled "SERVER". Copy all of the files(including subdirectories and files) in the RPL directory of ODI33G to thediskette labeled"RPL".
這段話的意思是要使用兩塊磁片分別存放ODI33G.exe所解壓縮出來的資料,其中一個磁碟片標籤貼為"server"另一個為"RPL"。然而我們已經有硬碟了不要這麼搞就全部複製到c:\server.312;雖然我知道RPL資料夾現在用不到,因為這個資料夾存放的是和boot from network有關的資訊。有一點特別重要就是在這個server資料夾其絕對路徑是c:\server.312\server\33SPEC中將我們的AMD pcnet網卡drivers(pcntnw.lan及pcntnw.ldi)也存放到這裡來。
2) Load Install at the file server.在system console輸入load install命令
3) Select "Product Options".
4) Press "Ins".按下鑑盤上的insert按鍵
5) Enter the path to the location of the "SERVER" directory where ODI33G was extracted..ie SYS:\SERVER. 在此我輸入的路徑是C:\SERVER.312\SERVER
6) Select "Install Product".
7) Press "Enter" and select "Yes" to start the installation.
安裝過程如圖六 ~圖十三。以上兩個patches已安裝完成。
接下來已經接近尾聲,只剩下把autoexec.ncf設定完成就可以開始來測試連線了。AUTOEXEC.NCF:
FILE SERVER NAME BENSON
IPX INTERNAL NET 80862240
MOUNT ALL
LOAD C:\SERVER.312\NBI31X
LOAD C:\SERVER.312\MSM31X
LOAD C:\SERVER.312\ETHERTSM
LOAD PCNTNW PORT=2000 INT=A SLOT=10001 FRAME=ETHERNET_802.3
BIND IPX TO PCNTNW NET=540321
LOAD C:\SERVER.312\NW4-IDLE ;此行可以使整個CPU使用率下降
LOAD MONITOR
搞定,可參考連線畫面如圖DONE.顯示有兩個client以supervisor身分登入.
--> 閱讀更多...

2010年4月6日 星期二

Novell Netware3.12安裝在VMware Workstation 6.5(上)

圖十
圖九
圖八
圖七
圖六
圖五
圖四
圖三
圖二
圖一圖net
vmware有類似virtualbox的host-only網卡support;但是這兩套軟體實作方式不太一樣;應該說VMware比較簡單因為若是要使用physical network只要選擇設定如圖net,但vmware是實作為AMD PCNet Family Ethernet Adapter,因此若要在虛擬機中安裝網卡driver就必須到AMD的網站上download,網址如下http://villain.amd.com/us-en/ConnectivitySolutions/ProductInformation/0,,50_2330_6629_2452%5E2454%5E2467,00.html連結,然而我們主題是install Netware3.12因此也會包含clinrt端的DOS設定也一併介紹。
我們知道要安裝Netware3.12必需先安裝DOS,而且必須保留大部分的硬碟空間給SERVER使用,因此假設1GB的硬碟其實只要給DOS約50~100MB的partition就可以了;其餘的先不配置,因為這部分就是要留給Netware。
netware3.12 根本就是 DOS 系統的 File Sever;DOS 對 netware3.12 的 Sever 主機來說,只是借過一下的管道而己一但由 DOS 進入 Sever,整台 PC console 的運作在下 SHUTDOWN 指令之前,DOS 就完全管不著了; 而且,此時系統的運作,跟之前的 DOS 設定環境沒什麼關係。
以上這段話截錄自:http://www.pczone.com.tw/vbb3/archive/t-115616.html
由於在安裝的過程參考了一些相關網頁,雖然過程不可能完全一模一樣,但也有很多參考價值:例如NetWare 3.12的安裝配置 ;首先我們先把重點放在dos client(workststion)端,先把網卡driver ODI driver for DOS (LAPP) Workstations - Version 4.03, 167KB odiwkstn_lapp.exe給下載下來。注意client端的driver與server端不同。1.在VMware安裝一個DOS作業系統;方法參考在虛擬機下安裝DOS 6.22 2.把經常會用到的倚天、pe3等存放到DOS裡;這個步驟與主題無關,但因早期很多application都會使用到及dosidle.exe否則會很佔cpu使用率,所以還是很重要。3.以下是autoexec.bat及config.sys的範例您必須依照自己須求再增加自己的應用項目。
Autoexec.bat內容如下:
@ECHO OFF
PROMPT $P$G
mscdex.exe /d:mscd000
SET DIRCMD=/4
MODE CON RATE=32 DELAY=1
LSL.COM ;請自備此檔
PCLAPP.COM ;這就是vmware的網卡driver
IPXODI.COM ;請自備此檔
NETX.EXE ;請自備此檔
CONFIG.SYS內容如下:
DEVICE=C:\HIMEM.SYS
DEVICE=C:\Ide\Ide.sys /d:mscd000
LASTDRIVE=F
SHELL=COMMAND.COM /P /E:640
DOS=HIGH,UMB,AUTO
FCBS=4,0
FILES=30
BUFFERS=20,0
STACKS=9,256
NET.CFG內容如下:
Link Support
Max Stacks 8
Max Boards 4
Buffers 30, 1514
Link Driver PCLAPP
Frame Ethernet_802.3
NetWare DOS Requester
FIRST NETWORK DRIVE = X
NETWARE PROTOCOL = NDS BIND
4.當執行完autoexec.bat及config.sys也會試著連到netware server,若失敗會顯示:如圖一所示shell: A network server could not be found;這是正常,因為我們netware server還沒架起來。
接下來是Netware3.12 Install,我從網上截錄以下info,在此提供參考:
How To: install Novell Netware 3.x on VMware
You Need the following patch

http://support.novell.com/servlet/filedownload/pub/cdup5a.exe/
http://support.novell.com/servlet/filedownload/pub/312ptd.exe/
http://support.novell.com/servlet/filedownload/pub/odi33g.exe
http://support.novell.com/servlet/filedownload/pub/lib312d.exe/
http://support.novell.com/servlet/filedownload/pub/312y2kp2.exe/
http://support.novell.com/servlet/filedownload/pub/clibaux1.exe/
http://support.novell.com/servlet/filedownload/pub/ttsy2k.exe/
http://support.novell.com/servlet/filedownload/pub/ldr312ft.exe/
以上這些patches可從此處download
Driver
http://www.amd.com/us-en/assets/content_type/utilities/odi_ahsm_svr3x.exe
0) Configure a virtual machine with access to the CDROM drive and with a virtual/plain disk that it can use to store its MS-DOS boot files and its NetWare partition [which contains the SYS volume] configure in vm bios primary master DISK "LBA Mode COntrol" to DISABLE.
1) Use a MS-DOS v6.x bootable floppy disk to get started. Boot the virtual machine from the floppy disk.
2) Manually create the DOS partition on the hard drive. Format the partition, make it bootable and copy in the required MS-DOS files and dosidle.exe modify autoexec.bat for dosidle autostart.
3) Install Novell 3.12 how do you want, at question
"DO YOU WANT SPECIFY ANY SPECIAL STARTUP COMMANDS?" asnwer NO
"DO YOU WANT AUTOEXEC.BAT to load SERVER.EXE ?" asnwer NO
now shutdown netware and go to dos (Write DOWN and after EXIT on console)
4) now copy the extract cdup5a.exe file in novell dos directory (c:\SERVER.312) xcopy
5) create C:\SERVER.312\STARTUP.NCF
LOAD PM312.NLM
LOAD NPAPATCH.NLM
SET AUTO REGISTER MEMORY ABOVE 16 MEGABYTES = OFF
SET RESERVED BUFFERS BELOW 16 MEG = 200
LOAD IDEATA PORT=1F0 INT=E
6) Manually start SERVER.EXE, the system load the IDEATA.HAM driver , specifying the proper interrupt and I/O port information for the IDE controllers in the VM. the drive load twice to support emulated IDE devices on both the primary and secondary IDE adapters in the VM.
Don't worry about warning you need other library for silent warning
7) Insert a file name server and an IPX network number Load INSTALL.NLM and manually create the NetWare partition(s) and the SYS volume.
8) Once you have the SYS volume mounted, you can go about using INSTALL.NLM to copy the rest of the server files from the installation media. I enabled CDROM support to do this and completed the installation using the CDROM mounted as a NetWare volume. However, you
could leave a DOS CDROM driver and MSCDEX loaded and just access the installation CDROM via a drive letter such as D:.
9) uncompress odig33.exe and copy from FILE TO SERVER\33SPEC\312 MSM31X.NLM,NB31X.NLM
c:\server.312\SERVER\33SPEC ETHERTSM.NLM
c:\server.312
after Copy pcntnw.lan e pcntw.ldi ( AMD Network Driver) in c:\server.312
Start server and add to AUTOEXEC.NCF
load c:\server.312\pcntnw slot=2 BIND IPX TO pcntnw NET=xxxx
10) copy nw4-idle.nlm in SYS:\SYSTEM and modify AUTOEXEC.CNF to load
nw4-idle.nlm
11) Install the follow patch (follow instraction)
312ptd ,
dig33,
lib312d
312y2kp2
clibaux1
ttsy2k
ldr312ft
12) Be sure to get the NW4-IDLE.NLM file and load it on the 3.x server to keep the VM from consuming 100% of the host CPU while the NetWare server is idle.
從以上這篇英文說明,我們實際來安裝netware3.12如下:
在C:根目錄用DOS的MD命令生成SERVER.312目錄,並在該目錄下依次生成子目錄UNICODE,SYSTEM_1,SYSTEM_2,SYSTEM_3,SYSTEM_4,SYSTEM_5,SYSTEM_6,SYSTEM_7和SYSTEM_8,並用DOS的XCOPY命令把NetWare 3.12相應的盤拷貝到對應的子目錄下;(或許很多人不知道要去哪裡Download netware3.12,因為網路上能找到的資源真的不多,但是通常在一部novell server裡頭f其安裝檔都還存在著,若要重新安裝一部server只需將這些SYSTEM_1~SYSTEM_8及UNICODE和install資料夾複製到新機上即可;另外在此我把我找到的安裝碟及相關檔提供出來給大家。用DOS的COPY命令拷貝SYSTEM_1盤上的INSTALL.NLM,ISADISK.DSK,SERVER.EXE,KEYB.NLM文件和SYSTEM_3盤上的ETHERTSM.NLM,MSM31X.NLM,PCNTNW.NLM,PCNTNW.LDI(vmware 網卡driver)文件到SERVER.312目錄。接著下C:\CD SERVER.312\install\install.bat之後的安裝畫面如上面圖二~圖十所示。
其實到這裡已經差不多了,唯獨網卡DRIVERs掛載失敗,查一下網卡驅動的readme,得知:
For NetWare 3.12 Server, follow files should be installed before load this driver. 312PTD.EXE Nov. 22, 1999 ODI33G.EXE Mar. 30, 2000,但是接下來必須先安裝SYS卷及public公用程式庫然後才可以來update這兩個patches的安裝;待續‧‧‧請接續Novell Netware3.12安裝在VMware Workstation 6.5(中)
--> 閱讀更多...