1. 求助:關於linux內核GDT大小問題
list_entry(ptr, type, member)這個函數的功能就是:從結構體(type)某成員變數(member)指針(ptr)來求出該結構體(type)的首指針。 因為內核鏈表,一般你只能知道鏈表指針域的地址和指針域的名稱
2. linux下,gcc提示「段錯誤 (核心已轉儲)」,ubuntu剛上手不大會用,誰說一下是啥問題
主要有以下幾個方面的原因:
一、內存訪問出錯
這類問題的典型代表就是數組越界。
二、非法內存訪問
出現這類問題主要是程序試圖訪問內核段內存而產生的錯誤。
三、棧溢出
Linux默認給一個進程分配的棧空間大小為8M。c++申請變數時,new操作申請的變數在堆中,其他變數一般在存儲在棧中。
因此如果數組開的過大變會出現這種問題。
注意事項
段錯誤一般就是指訪問的內存超出了系統所給這個程序的內存空間,通常這個值是由gdtr來保存的,他是一個48位的寄存器,其中的32位是保存由它指向的gdt表,後13位保存相應於gdt的下標,最後3位包括了程序是否在內存中以及程序的在cpu中的運行級別,指向的gdt是由以64位為一個單位的表,在這張表中就保存著程序運行的代碼段以及數據段的起始地址以及與此相應的段限和頁面交換還有程序運行級別還有內存粒度等等的信息。
一旦一個程序發生了越界訪問,cpu就會產生相應的異常保護,於是segmentation fault就出現了。在編程中基本是是錯誤地使用指針引起的。
3. Linux 格式化硬碟方法教程
我們使用Linux過程中,和Windows也一樣。使用硬碟的時候,出現了問題,需要對硬碟進行格式化。那 Linux 如何格式化硬碟呢?下面就和大家說一下 Linux 格式化硬碟的方法和步驟。
步驟如下:
1、硬碟的介面類型
硬碟的介面一般分為兩種,一種是IDE並行介面,一種是SATA串列介面, 在 Linux 上面IDE介面的硬碟被識別為/dev/hd[a-z]這樣的設備,其中hdc表示光碟機設備,這是因為主板上面一般有兩個IDE插槽,一個IDE插槽可以接兩個硬碟,而光碟機是接著IDE的第二個插槽上面的第一個介面上面。其他諸如SCSI,SAS,SATA,USB等介面的設備在linux識別為/dev/sd[a-z]。
2、 Linux 硬碟的分區
磁碟的分區分為: primary(主分區)、extended(擴展分區)、Logical (邏輯分區)且主分區加上擴展分區的個數小於等於4個。且擴展分區最多隻有一個,擴展分區是不能直接在裡面寫入數據的,擴展分區裡面新建邏輯分區才能讀寫數據。如果看見一個硬碟有很多分區,則其實是在擴展分區裡面新建的邏輯分區。
主分區從 sdb1--sdb4
邏輯分區是從 sdb5--sdbN
如果所示linux硬碟分區之間的關系
第一種情況為:四個主分區
第二種情況為:三個主分區+一個擴展分區(擴展分區裡麵包括邏輯分區)
4、使linux內核識別分區信息
cat /proc/partitions 查看內核識別的分區信息
[root@Redhat5 ~]# cat /proc/partitions
major minor #blocks name
8 0 125829120 sda
8 1 104391 sda1
8 2 41945715 sda2
8 3 1052257 sda3
253 0 30703616 dm-0
253 1 5111808 dm-1
讓內核重新讀取硬體分區表有兩個命令
partprobe /dev/sda ------》 redhat 5.x ,redhat 6.x需要重啟
partx -a /dev/sda5 /dev/sda-------》redhat 6.x
內核載入分區信息之後再查看
[root@Redhat5 ~]# cat /proc/partitions
major minor #blocks name
8 0 125829120 sda
8 1 104391 sda1
8 2 41945715 sda2
8 3 1052257 sda3
8 4 0 sda4
8 5 1959898 sda5
8 6 3911796 sda6
253 0 30703616 dm-0
253 1 5111808 dm-1
5、格式化分區
格式化分區的命令
mkfs -t fstype /dev/part -t選擇格式化的類型,然後是那個分區
mkfs.ext2 /dev/part 格式化為ext2的類型,然後是接那個分區
mkfs.ext3 /dev/part 格式化為ext3的類型,然後是接那個分區
mkfs.ext4 /dev/part 格式化為ext4的類型,然後是接那個分區
mke2fs 比之前幾個更加強大的格式化分區的命令
這幾個命令之間相關的關系
mkfs -t ext4 = mkfs.ext4 = mke2fs -t ext4
mkfs -t ext3 = mkfs.ext3 = mke2fs -j = mke2fs -t ext3
mkfs -t ext2 = mkfs.ext2 = mke2fs = mke2fs -t ext2
mke2fs (man mke2fs):創建文件類型---》/etc/mke2fs.conf 配置文件
-t:文件類型
-j:相當於 ext3
-b:指定塊大小{1024”2048|4096byte},塊大小取決cpu對內存頁框大小的支持,x86系統默認頁
大小是4096,4k
-L: label 設定卷標
-m: #預留給管理使用的塊所佔的比率 一般用在分區很大的時候,#為數字
mke2fs -t ext3 /dev/sda5 #把分區格式為ext3格式的
mke2fs -t ext3 -b 2048 /dev/sda5 # 把分區的塊改成2048位元組,一般用於系統中小文件很多的情況
mke2fs -t ext3 -m 3 /dev/sda5 #把分區預留的空間改為所佔總空間的3%,默認為5%,因為當某個分區足夠大的時候,可以減少空間
mke2fs -t ext3 -L DATE /dev/sda5 #把分區的卷標設置為DATE
tune2fs 命令可以查看分區的詳細信息,mke2fs 與 tune2fs的關系和useradd與usermod的關系很類似。mke2fs支持的參數tune2fs大多數都支持,詳情請man tune2fs查看相關的幫助。
option
-l: 顯示文件系統超級塊信息;
-L label:重新設定卷標;
-m #: 調整預留給管理使用的塊所佔據總體空間的比例;
-r #: 調整預留給管理使用的塊個數;
-o:設定掛載默認選項
-O: 設定文件系統默認特性
-E: 調整文件系統的擴展屬性
tune2fs不支持-b參數改變塊的大小。
tune2fs -l /dev/sda5 可以詳細查看分區的信息
[root@Redhat5 ~]# tune2fs -l /dev/sda5 | grep “^Block size” //顯示sda5分區塊的大小
Block size: 4096
[root@Redhat5 ~]# tune2fs -l /dev/sda5 | grep “^Reserved” //顯示sda5預留空間
Reserved block count: 24498
Reserved GDT blocks: 119
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
tune2fs -L DATE /dev/sda5 #修改卷標
tune2fs -m 3 /dev/sda5 #修改預留給管理使用的塊所佔據總體空間的比例
e2label:顯示或設定卷標
e2label /dev/sda5 MYDATE
blkid :顯示設備的UUID及文件系統類型,及卷標
6、掛載
mount 掛載------》顯示的是/etc/mtab文件裡面的內容
mount [-t fstype] DEVICE MOUNT_POINT
命令 設備 掛載點
mount [-t fstype] LABEL=“卷標” MOUNT_POINT --》e2label查看標簽
mount [-t fstype] UUID=“UUID” MOUNT_POINT ----》blkid可以查看UUID
options:
-o:用於指定掛著選項,常用的掛著選項,選項有很多用逗號隔開
ro:只讀掛載
rw:讀寫掛載(默認)
noatime:關閉更新訪問時間
auto:是否能夠由“mount -a”掛載
defaults:相當於rw, suid, dev, exec, auto, nouser, async.
sync:同步
async:非同步
noexec:不容易設備中的二進制直接運行
remount:重新掛載
loop:本地回環設備: 掛載系統已經存在的鏡像
-t:
-v:verbose 顯示詳細信息
-n:掛載文件系統時,不更新/etc/mtab文件
-r:只讀掛載相當於“-o ro”
掛載的幾種方式
顯示系統已經掛載的文件
掛載分區sda5到/mnt/sda5目錄下
[root@Redhat5 ~]# mkdir /mnt/sda5 #創建一個掛載目錄
[root@Redhat5 ~]# mount /dev/sda5 /mnt/sda5/ #把分區掛載到新建的目錄裡面
[root@Redhat5 ~]# mount “ grep ”/dev/sda5“ #查看分區是否掛載
/dev/sda5 on /mnt/sda5 type ext3 (rw) #顯示分區已經掛載
[root@Redhat5 ~]# umount /dev/sda5 #卸載分區
[root@Redhat5 ~]#mount | grep ”/dev/sda5“ #發現分區已經被卸載
[root@Redhat5 ~]# blkid #顯示設備的UUID及文件系統類型,及卷標
/dev/mapper/vol0-home: UUID=”d1aeef77-bb47-4718-a91c-d4870b536440“ TYPE=”ext3“
/dev/sda3: LABEL=”SWAP-sda3“ TYPE=”swap“
/dev/sda1: LABEL=”/boot“ UUID=”5e5eaaac-cc56-42da-81eb-9adebff0fa2e“ TYPE=”ext3“
/dev/vol0/root: UUID=”4302a528-e88e-43d3-b3cc-1c2b29cda656“ TYPE=”ext3“
/dev/sda5: LABEL=”DATE“ UUID=”8f4f9b53-0bf0-4ce9-9665-bd4c7ae9ce59“ TYPE=”ext3“
[root@Redhat5 ~]# mount LABEL=”DATE“ /mnt/sda5/ #可以查到到分區5的標簽為DATE,通
過掛載標簽來掛載分區
[root@Redhat5 ~]# mount | grep ”/dev/sda5“ #查看分區是否掛載
/dev/sda5 on /mnt/sda5 type ext3 (rw)
[root@Redhat5 ~]# umount /dev/sda5 #卸載分區
[root@Redhat5 ~]#mount | grep ”/dev/sda5“
[root@Redhat5 ~]# mount UUID=”8f4f9b53-0bf0-4ce9-9665-bd4c7ae9ce59“ /mnt/sda5/
#通過掛載UUID來掛載分區
[root@Redhat5 ~]#mount | grep ”/dev/sda5“
/dev/sda5 on /mnt/sda5 type ext3 (rw)
用mount命令掛載的文件在系統開機的時候是不能自動掛載的,想要系統開機就掛載寫到配置文件即可/etc/fstab
echo ”LABEL=DATE /mnt/sde5 ext3 defaults 0 0“ 》》 /etc/fstab
/etc/fstab文件的格式
[root@Redhat5 ~]# cat /etc/fstab
/dev/vol0/root / ext3 defaults 1 1
/dev/vol0/home /home ext3 defaults 1 2
LABEL=/boot /boot ext3 defaults 1 2
tmpfs /dev/shm tmpfs defaults 0 0
欄位以空格分隔
1、掛載的設備:設備文件、卷標、UUID
2、掛載點: 與跟相關聯的目錄
3、文件系統類型:ext3,ext4
4、掛載選項:defaults表示使用默認選項,多個選項彼此間逗號分隔
5、轉儲頻率:0:從不備份、1:每日備份、2:每隔一日備份
6、自檢次序:0:不檢測、1:第一個檢測,一般只能為根文件系統第一個檢測 2 。。.9
補充:系統常用維護技巧
1,在 “開始” 菜單中選擇 “控制面板” 選項,打開 “控制面板” 窗口,單擊 “管理工具” 鏈接
2,在打開的 “管理工具” 窗口中雙擊 “事件查看器” 圖標
3, 接著會打開 “事件查看器” 窗口
4,在右側窗格中的樹狀目錄中選擇需要查看的日誌類型,如 “事件查看器本地--Win日誌--系統日誌,在接著在中間的 “系統” 列表中即查看到關於系統的事件日誌
5,雙擊日誌名稱,可以打開 “事件屬性” 對話框,切換到 “常規” 選項卡,可以查看該日誌的常規描述信息
6,切換到 “詳細信息” 選項卡,可以查看該日誌的詳細信息
7,打開 “控制面板” 窗口,單擊 “操作中心” 鏈接,打開 “操作中心” 窗口,展開 “維護” 區域
8,單擊 “查看可靠性歷史記錄” 鏈接,打開 “可靠性監視程序” 主界面,如圖所示, 用戶可以選擇按天或者按周為時間單位來查看系統的穩定性曲線表,如果系統近日沒出過什麼狀況, 那麼按周來查看會比較合適。觀察圖中的曲線可以發現,在某段時間內,系統遇到些問題,可靠性指數曲線呈下降的趨勢,並且在這段時間系統遇到了三次問題和一次警告,在下方的列表中可以查看詳細的問題信息。
相關閱讀:系統故障導致死機怎麼解決
1、病毒原因造成電腦頻繁死機
由於此類原因造成該故障的現象比較常見,當計算機感染病毒後,主要表現在以下幾個方面:
①系統啟動時間延長;
②系統啟動時自動啟動一些不必要的程序;
③無故死機
④屏幕上出現一些亂碼。
其表現形式層出不窮,由於篇幅原因就介紹到此,在此需要一並提出的是,倘若因為病毒損壞了一些系統文件,導致系統工作不穩定,我們可以在安全模式下用系統文件檢查器對系統文件予以修復。
2、由於某些元件熱穩定性不良造成此類故障(具體表現在CPU、電源、內存條、主板)
對此,我們可以讓電腦運行一段時間,待其死機後,再用手觸摸以上各部件,倘若溫度太高則說明該部件可能存在問題,我們可用替換法來診斷。值得注意的是在安裝CPU風扇時最好能塗一些散熱硅脂,但我在某些組裝的電腦上卻是很難見其蹤影,實踐證明,硅脂能降低溫度5—10度左右,特別是P Ⅲ 的電腦上,倘若不塗散熱硅脂,計算機根本就不能正常工作,曾遇到過一次此類現象。該機主要配置如下:磐英815EP主板、PⅢ733CPU、133外頻的128M內存條,當該機組裝完後,頻繁死機,連Windows系統都不能正常安裝,但是更換賽揚533的CPU後,故障排除,懷疑主板或CPU有問題,但更換同型號的主板、CPU後該故障也不能解決。後來由於發現其溫度太高,在CPU上塗了一些散熱硅脂,故障完全解決。實踐證明在賽揚533以上的CPU上必須要塗散熱硅脂,否則極有可能引起死機故障。
3、由於各部件接觸不良導致計算機頻繁死機
此類現象比較常見,特別是在購買一段時間的電腦上。由於各部件大多是靠金手指與主板接觸,經過一段時間後其金手指部位會出現氧化現象,在拔下各卡後會發現金手指部位已經泛黃,此時,我們可用橡皮擦來回擦拭其泛黃處來予以清潔。
4、由於硬體之間不兼容造成電腦頻繁死機
此類現象常見於顯卡與其它部件不兼容或內存條與主板不兼容,例如SIS的顯卡,當然其它設備也有可能發生不兼容現象,對此可以將其它不必要的設備如Modem、音效卡等設備拆下後予以判斷。
5、軟體沖突或損壞引起死機
此類故障,一般都會發生在同一點,對此可將該軟體卸掉來予以解決。
4. linux最多可以有多少個進程
LINUX中進程的最大理論數計算:
每個進程的局部段描述表LDT都作為一個獨立的段而存在,在全局段描述表GDT中要有一個表項指向這個段的起始地址,並說明該段的長度以及其他一些 參數。除上之外,每個進程還有一個TSS結構(任務狀態段)也是一樣。所以,每個進程都要在全局段描述表GDT中占據兩個表項。那麼,GDT的容量有多大 呢?段寄存器中用作GDT表下標的位段寬度是13位,所以GDT中可以有8192個描述項。除一些系統的開銷(例如GDT中的第2項和第3項分別用於內核 的代碼段和數據段,第4項和第5項永遠用於當前進程的代碼段和數據段,第1項永遠是0,等等)以外,尚有8180個表項可供使用,所以理論上系統中最大的 進程數量是4090。
5. linux中一個數跟上ULL是什麼意思
好像是數據類型 unsigned long long 的縮寫吧
6. 誰能教教我linux eclipse gdt怎麼配置啊,總是錯誤不能寫代碼,求指導
在Ubuntu中安裝了JDK就不用再安裝JRE了,如安裝了JRE,再安裝JDK會重新再裝一個JRE。打開Ubuntu終端,使用命令:
sudo apt-get install sun-java6-jre //安裝jre
sudo apt-get install sun-java6-jdk //安裝jdk
讓終端的當前目錄為想要安裝Eclipse的目錄,本人安裝在/usr/share 目錄下, 可以通過在想要安裝Eclipse的目錄下打開終端,這時終端的當前目錄就是我們要安裝的目錄了。
sudo tar -zxvf /PATH/eclipse-SDK-3.7.1-linux-gtk.tar.gz
將PATH替換成eclipse壓縮包存放的目錄,這時eclipse就會解壓縮到終端的當前目錄了。
添加Eclipse桌面快捷方式
在Ubuntu桌面或Linuxmint桌面,應用程序的編程菜單中添加Eclipse快捷方式圖標:
sudo gedit /usr/share/applications/eclipse.desktop
/usr/share/applications/ 目錄下有很多到快捷方式圖標,可以將它們拖到桌面,這樣就可以直接在桌面打開相應的程序了。
在Gedit打開的文件中加入下面的代碼:
[Desktop Entry]
Encoding=UTF-8
Name=Eclipse
Comment=Eclipse IDE
#改成自己安裝Eclipse可執行文件的目錄路徑
Exec=/usr/share/eclipse/eclipse
#改成自己的Eclipse 圖標路徑
Icon=/usr/share/eclipse/icon.xpm
Terminal=false
StartupNotify=true
Type=Application
#類別:應用程序;編程;IDE;Java
Categories=Application;Development;IDE;Java
7. 誰知道Linux啟動時的idt、gdt、ldt是起什麼作用的
idt中斷向量表,切換進程,虛擬內存,硬體驅動,系統調用等都要用到它
8. Linux系統開機時啟動內核步驟是什麼
實模式,並開始執行位於地址0xFFFF0處
的代碼,也就是ROM-BIOS起始位置的代碼。BIOS先進行一系列的系統自檢,然後初始化位
於地址0的中斷向量表。最後BIOS將啟動盤的第一個扇區裝入到0x7C00,並開始執行此處
的代碼。這就是對內核初始化過程的一個最簡單的描述。
最初,linux核心的最開始部分是用8086匯編語言編寫的。當開始運行時,核心將自
己裝入到絕對地址0x90000,再將其後的2k位元組裝入到地址0x90200處,最後將核心的其餘
部分裝入到0x10000。
當系統裝入時,會顯示Loading...信息。裝入完成後,控制轉向另一個實模式下的匯
編語言代碼boot/Setup.S。Setup部分首先設置一些系統的硬體設備,然後將核心從
0x10000處移至0x1000處。這時系統轉入保護模式,開始執行位於0x1000處的代碼。
接下來是內核的解壓縮。0x1000處的代碼來自於文件Boot/head.S,它用來初始化寄
存器和調用decompress_kernel( )程序。decompress_kernel( )程序由Boot/inflate.c,
Boot/unzip.c和Boot../misc.c組成。解壓縮後的數據被裝入到了0x100000處,這也是
linux不能在內存小於2M的環境下運行的主要原因。
解壓後的代碼在0x1010000處開始執行,緊接著所有的32位的設置都將完成: IDT、
GDT和LDT將被裝入,處理器初始化完畢,設置好內存頁面,最終調用start_kernel過程。
這大概是整個內核中最為復雜的部分。
[系統開始運行]
linux kernel 最早的C代碼從匯編標記startup_32開始執行
startup_32:
start_kernel
lock_kernel
trap_init
init_IRQ
sched_init
softirq_init
time_init
console_init
#ifdef CONFIG_MODULES
init_moles
#endif
kmem_cache_init
sti
calibrate_delay
mem_init
kmem_cache_sizes_init
pgtable_cache_init
fork_init
proc_caches_init
vfs_caches_init
buffer_init
page_cache_init
signals_init
#ifdef CONFIG_PROC_FS
proc_root_init
#endif
#if defined(CONFIG_SYSVIPC)
ipc_init
#endif
check_bugs
smp_init
rest_init
kernel_thread
unlock_kernel
cpu_idle
・startup_32 [arch/i386/kernel/head.S]
・start_kernel [init/main.c]
・lock_kernel [include/asm/smplock.h]
・trap_init [arch/i386/kernel/traps.c]
・init_IRQ [arch/i386/kernel/i8259.c]
・sched_init [kernel/sched.c]
・softirq_init [kernel/softirq.c]
・time_init [arch/i386/kernel/time.c]
・console_init [drivers/char/tty_io.c]
・init_moles [kernel/mole.c]
・kmem_cache_init [mm/slab.c]
・sti [include/asm/system.h]
・calibrate_delay [init/main.c]
・mem_init [arch/i386/mm/init.c]
・kmem_cache_sizes_init [mm/slab.c]
・pgtable_cache_init [arch/i386/mm/init.c]
・fork_init [kernel/fork.c]
・proc_caches_init
・vfs_caches_init [fs/dcache.c]
・buffer_init [fs/buffer.c]
・page_cache_init [mm/filemap.c]
・signals_init [kernel/signal.c]
・proc_root_init [fs/proc/root.c]
・ipc_init [ipc/util.c]
・check_bugs [include/asm/bugs.h]
・smp_init [init/main.c]
・rest_init
・kernel_thread [arch/i386/kernel/process.c]
・unlock_kernel [include/asm/smplock.h]
・cpu_idle [arch/i386/kernel/process.c]
start_kernel( )程序用於初始化系統內核的各個部分,包括:
*設置內存邊界,調用paging_init( )初始化內存頁面。
*初始化陷阱,中斷通道和調度。
*對命令行進行語法分析。
*初始化設備驅動程序和磁碟緩沖區。
*校對延遲循環。
最後的function'rest_init' 作了以下工作:
・開辟內核線程'init'
・調用unlock_kernel
・建立內核運行的cpu_idle環, 如果沒有調度,就一直死循環
實際上start_kernel永遠不能終止.它會無窮地循環執行cpu_idle.
最後,系統核心轉向move_to_user_mode( ),以便創建初始化進程(init)。此後,進程0開始進入無限循環。
初始化進程開始執行/etc/init、/bin/init 或/sbin /init中的一個之後,系統內核就不再對程序進行直接控制了。之後系統內核的作用主要是給進程提供系統調用,以及提供非同步中斷事件的處理。多任務機制已經建立起來,並開始處理多個用戶的登錄和fork( )創建的進程。
[init]
init是第一個進程,或者說內核線程
init
lock_kernel
do_basic_setup
mtrr_init
sysctl_init
pci_init
sock_init
start_context_thread
do_init_calls
(*call())-> kswapd_init
prepare_namespace
free_initmem
unlock_kernel
execve
[目錄]
--------------------------------------------------------------------------------
啟動步驟
系統引導:
涉及的文件
./arch/$ARCH/boot/bootsect.s
./arch/$ARCH/boot/setup.s
bootsect.S
這個程序是linux kernel的第一個程序,包括了linux自己的bootstrap程序,
但是在說明這個程序前,必須先說明一般IBM PC開機時的動作(此處的開機是指
"打開PC的電源"):
一般PC在電源一開時,是由內存中地址FFFF:0000開始執行(這個地址一定
在ROM BIOS中,ROM BIOS一般是在FEOOOh到FFFFFh中),而此處的內容則是一個
jump指令,jump到另一個位於ROM BIOS中的位置,開始執行一系列的動作,包
括了檢查RAM,keyboard,顯示器,軟硬磁碟等等,這些動作是由系統測試代碼
(system test code)來執行的,隨著製作BIOS廠商的不同而會有些許差異,但都
是大同小異,讀者可自行觀察自家機器開機時,螢幕上所顯示的檢查訊息。
緊接著系統測試碼之後,控制權會轉移給ROM中的啟動程序
(ROM bootstrap routine),這個程序會將磁碟上的第零軌第零扇區讀入
內存中(這就是一般所謂的boot sector,如果你曾接觸過電腦病
毒,就大概聽過它的大名),至於被讀到內存的哪裡呢? --絕對
位置07C0:0000(即07C00h處),這是IBM系列PC的特性。而位在linux開機
磁碟的boot sector上的正是linux的bootsect程序,也就是說,bootsect是
第一個被讀入內存中並執行的程序。現在,我們可以開始來
看看到底bootsect做了什麼。
第一步
首先,bootsect將它"自己"從被ROM BIOS載入的絕對地址0x7C00處搬到
0x90000處,然後利用一個jmpi(jump indirectly)的指令,跳到新位置的
jmpi的下一行去執行,
第二步
接著,將其他segment registers包括DS,ES,SS都指向0x9000這個位置,
與CS看齊。另外將SP及DX指向一任意位移地址( offset ),這個地址等一下
會用來存放磁碟參數表(disk para- meter table )
第三步
接著利用BIOS中斷服務int 13h的第0號功能,重置磁碟控制器,使得剛才
的設定發揮功能。
第四步
完成重置磁碟控制器之後,bootsect就從磁碟上讀入緊鄰著bootsect的setup
程序,也就是setup.S,此讀入動作是利用BIOS中斷服務int 13h的第2號功能。
setup的image將會讀入至程序所指定的內存絕對地址0x90200處,也就是在內存
中緊鄰著bootsect 所在的位置。待setup的image讀入內存後,利用BIOS中斷服
務int 13h的第8號功能讀取目前磁碟的參數。
第五步
再來,就要讀入真正linux的kernel了,也就是你可以在linux的根目錄下看
到的"vmlinuz" 。在讀入前,將會先呼叫BIOS中斷服務int 10h 的第3號功能,
讀取游標位置,之後再呼叫BIOS 中斷服務int 10h的第13h號功能,在螢幕上輸
出字串"Loading",這個字串在boot linux時都會首先被看到,相信大家應該覺
得很眼熟吧。
第六步
接下來做的事是檢查root device,之後就仿照一開始的方法,利用indirect
jump 跳至剛剛已讀入的setup部份
第七步
setup.S完成在實模式下版本檢查,並將硬碟,滑鼠,內存參數寫入到 INITSEG
中,並負責進入保護模式。
第八步
操作系統的初始化。
9. 誰能教教我linux eclipse gdt怎麼配置啊,總是錯誤不能寫代碼,求指導
在Ubuntu中安裝了JDK就不用再安裝JRE了,如安裝了JRE,再安裝JDK會重新再裝一個JRE。打開Ubuntu終端,使用命令:
sudo
apt-get
install
sun-java6-jre
//安裝jre
sudo
apt-get
install
sun-java6-jdk
//安裝jdk
讓終端的當前目錄為想要安裝Eclipse的目錄,本人安裝在/usr/share
目錄下,
可以通過在想要安裝Eclipse的目錄下打開終端,這時終端的當前目錄就是我們要安裝的目錄了。
sudo
tar
-zxvf
/PATH/eclipse-SDK-3.7.1-linux-gtk.tar.gz
將PATH替換成eclipse壓縮包存放的目錄,這時eclipse就會解壓縮到終端的當前目錄了。
添加Eclipse桌面快捷方式
在Ubuntu桌面或Linuxmint桌面,應用程序的編程菜單中添加Eclipse快捷方式圖標:
sudo
gedit
/usr/share/applications/eclipse.desktop
/usr/share/applications/
目錄下有很多到快捷方式圖標,可以將它們拖到桌面,這樣就可以直接在桌面打開相應的程序了。
在Gedit打開的文件中加入下面的代碼:
[Desktop
Entry]
Encoding=UTF-8
Name=Eclipse
Comment=Eclipse
IDE
#改成自己安裝Eclipse可執行文件的目錄路徑
Exec=/usr/share/eclipse/eclipse
#改成自己的Eclipse
圖標路徑
Icon=/usr/share/eclipse/icon.xpm
Terminal=false
StartupNotify=true
Type=Application
#類別:應用程序;編程;IDE;Java
Categories=Application;Development;IDE;Java
10. 操作系統哪個模塊是必不可少的
保護模式
(Protected Mode,或有時簡寫為 pmode) 是一種 80286 系列和之後的 x86 兼容 CPU 操作模式。保護模式有一些新的特色,設計用來增強 多工 和系統穩定度,像是 內存保護,分頁 系統,以及硬體支援的 虛擬內存。大部分的現今 x86 操作系統 都在保護模式下運行,包含 Linux、FreeBSD、以及 微軟 Windows 2.0 和之後版本。
另外一種 286 和其之後 CPU 的操作模式是 真實模式,一種向前兼容且關閉這些特色的模式。設計用來讓新的晶元可以執行舊的軟體。依照設計的規格,所有的 x86 CPU 都是在真實模式下開機來確保傳統操作系統的向前兼容性。在任何保護模式的特色可用前,他們必須要由某些程序手動地切換到保護模式。在現今的電腦,這種切換通常是由 操作系統 在開機時候必須完成的第一件工作的一個。它也可能當 CPU 在保護模式下運行時,使用 虛擬86模式 來執行設計給真實模式的程序碼。
盡管用軟體的方式也有某些可能在真實模式的系統下使用多工,但保護模式下內存保護的特色,可以避免有問題的程序破壞其他工作或是 操作系統 核心所擁有的內存。保護模式也有中斷正在執行程序的硬體支援,可以把 execution content 交給其他工作,得以實現 先佔式多工。
大部分可以使用保護模式的 CPU 也擁有 32 位元暫存器 的特色 (例如 80386 系列和其後任何的晶元),導入了融合保護模式而成為 32 位元處理的概念。80286 晶元雖有支援保護模式,但是仍然只有 16 位元暫存器。Windows 2.0 和之後版本中的保護模式增強稱為 "386 增強模式",是因為他們除了保護模式外,還需要 32 位元的暫存器,並且無法在 286 上面執行 (即使 286 支援保護模式)。
即使在 32 位元晶元上已經打開了保護模式,但是 1 MB 以上的內存並無法存取,是由於一種仿照 IBM XT 系統設計特性的 memory wrap-around(內存連續) 的因素。這種限制可以由打開 A20 line 來迴避。
在保護模式下,前面 32 個中斷都是保留給 CPU 例外處理用。舉個例子,中斷 0D (十進制 13) 是 一般保護模式錯物 和 中斷 00 是 除以零。
在8086/8088時代,處理器只存在一種操作模式(Operation Mode),當時由於不存在其它操作模式,因此這種模式也沒有被命名。自從80286到80386開始,處理器增加了另外兩種操作模式——保護模式PM (Protected Mode)和系統管理模式SMM(System Management Mode),因此,8086/8088的模式被命名為實地址模式RM(Real-address Mode)。
PM是處理器的native模式,在這種模式下,處理器支持所有的指令和所有的體系結構特性,提供最高的性能和兼容性。對於所有的新型應用程序和操作系統來說,建議都使用這種模式。為了保證PM的兼容性,處理器允許在受保護的,多任務的環境下執行RM程序。這個特性被稱做虛擬8086模式(Virtual -8086 Mode),盡管它並不是一個真正的處理器模式。Virtual-8086模式實際上是一個PM的屬性,任何任務都可以使用它。
RM提供了Intel 8086處理器的編程環境,另外有一些擴展(比如切換到PM或SMM的能力)。當主機被Power-up或Reset後,處理器處於RM下。
SMM是一個對所有Intel處理器都統一的標准體系結構特性。出現於Intel386 SL晶元。這個模式為OS實現平台指定的功能(比如電源管理或系統安全)提供了一種透明的機制。當外部的SMM interrupt pin(SMI#)被激活或者從APIC(Advanced Programming Interrupt Controller)收到一個SMI,處理器將進入SMM。在SMM下,當保存當前正在運行程序的整個上下文(Context)時,處理器切換到一個分離的地址空間。然後SMM指定的代碼或許被透明的執行。當從SMM返回時,處理器將回到被系統管理中斷之前的狀態。
由於機器在Power-up或Reset之後,處理器處於RM狀態,而對於Intel 80386以及其後的晶元,只有使用PM才能發揮出最大的作用。所以我們就面臨著一個從RM切換到PM的問題。
本文不討論SMM,本節的重點集中於在Booting階段如何從RM切換到PM,這里不會過多的討論PM的細節,因為《Intel Architecture Software Developer』s Manual Volume 3: System Programming》中有非常詳盡和准確的介紹。
1. What is GDT
在Protected Mode下,一個重要的必不可少的數據結構就是GDT(Global Descriptor Table)。
為什麼要有GDT?我們首先考慮一下在Real Mode下的編程模型:
在Real Mode下,我們對一個內存地址的訪問是通過Segment:Offset的方式來進行的,其中Segment是一個段的Base Address,一個Segment的最大長度是64 KB,這是16-bit系統所能表示的最大長度。而Offset則是相對於此Segment Base Address的偏移量。Base Address Offset就是一個內存絕對地址。由此,我們可以看出,一個段具備兩個因素:Base Address和Limit(段的最大長度),而對一個內存地址的訪問,則是需要指出:使用哪個段?以及相對於這個段Base Address的Offset,這個Offset應該小於此段的Limit。當然對於16-bit系統,Limit不要指定,默認為最大長度64KB,而 16-bit的Offset也永遠不可能大於此Limit。我們在實際編程的時候,使用16-bit段寄存器CS(Code Segment),DS(Data Segment),SS(Stack Segment)來指定Segment,CPU將段積存器中的數值向左偏移4-bit,放到20-bit的地址線上就成為20-bit的Base Address。
到了Protected Mode,內存的管理模式分為兩種,段模式和頁模式,其中頁模式也是基於段模式的。也就是說,Protected Mode的內存管理模式事實上是:純段模式和段頁式。進一步說,段模式是必不可少的,而頁模式則是可選的——如果使用頁模式,則是段頁式;否則這是純段模式。
既然是這樣,我們就先不去考慮頁模式。對於段模式來講,訪問一個內存地址仍然使用Segment:Offset的方式,這是很自然的。由於 Protected Mode運行在32-bit系統上,那麼Segment的兩個因素:Base Address和Limit也都是32位的。IA-32允許將一個段的Base Address設為32-bit所能表示的任何值(Limit則可以被設為32-bit所能表示的,以2^12為倍數的任何指),而不象Real Mode下,一個段的Base Address只能是16的倍數(因為其低4-bit是通過左移運算得來的,只能為0,從而達到使用16-bit段寄存器表示20-bit Base Address的目的),而一個段的Limit只能為固定值64 KB。另外,Protected Mode,顧名思義,又為段模式提供了保護機制,也就說一個段的描述符需要規定對自身的訪問許可權(Access)。所以,在Protected Mode下,對一個段的描述則包括3方面因素:[Base Address, Limit, Access],它們加在一起被放在一個64-bit長的數據結構中,被稱為段描述符。這種情況下,如果我們直接通過一個64-bit段描述符來引用一個段的時候,就必須使用一個64-bit長的段積存器裝入這個段描述符。但Intel為了保持向後兼容,將段積存器仍然規定為16-bit(盡管每個段積存器事實上有一個64-bit長的不可見部分,但對於程序員來說,段積存器就是16-bit的),那麼很明顯,我們無法通過16-bit長度的段積存器來直接引用64-bit的段描述符。
怎麼辦?解決的方法就是把這些長度為64-bit的段描述符放入一個數組中,而將段寄存器中的值作為下標索引來間接引用(事實上,是將段寄存器中的高13 -bit的內容作為索引)。這個全局的數組就是GDT。事實上,在GDT中存放的不僅僅是段描述符,還有其它描述符,它們都是64-bit長,我們隨後再討論。
GDT可以被放在內存的任何位置,那麼當程序員通過段寄存器來引用一個段描述符時,CPU必須知道GDT的入口,也就是基地址放在哪裡,所以Intel的設計者門提供了一個寄存器GDTR用來存放GDT的入口地址,程序員將GDT設定在內存中某個位置之後,可以通過LGDT指令將GDT的入口地址裝入此積存器,從此以後,CPU就根據此積存器中的內容作為GDT的入口來訪問GDT了。
GDT是Protected Mode所必須的數據結構,也是唯一的——不應該,也不可能有多個。另外,正象它的名字(Global Descriptor Table)所揭示的,它是全局可見的,對任何一個任務而言都是這樣。
除了GDT之外,IA-32還允許程序員構建與GDT類似的數據結構,它們被稱作LDT(Local Descriptor Table),但與GDT不同的是,LDT在系統中可以存在多個,並且從LDT的名字可以得知,LDT不是全局可見的,它們只對引用它們的任務可見,每個任務最多可以擁有一個LDT。另外,每一個LDT自身作為一個段存在,它們的段描述符被放在GDT中。
IA-32為LDT的入口地址也提供了一個寄存器LDTR,因為在任何時刻只能有一個任務在運行,所以LDT寄存器全局也只需要有一個。如果一個任務擁有自身的LDT,那麼當它需要引用自身的LDT時,它需要通過LLDT將其LDT的段描述符裝入此寄存器。LLDT指令與LGDT指令不同的時,LGDT指令的操作數是一個32-bit的內存地址,這個內存地址處存放的是一個32-bit GDT的入口地址,以及16-bit的GDT Limit。而LLDT指令的操作數是一個16-bit的選擇子,這個選擇子主要內容是:被裝入的LDT的段描述符在GDT中的索引值——這一點和剛才所討論的通過段積存器引用段的模式是一樣的。
LDT只是一個可選的數據結構,你完全可以不用它。使用它或許可以帶來一些方便性,但同時也帶來復雜性,如果你想讓你的OS內核保持簡潔性,以及可移植性,則最好不要使用它。
引用GDT和LDT中的段描述符所描述的段,是通過一個16-bit的數據結構來實現的,這個數據結構叫做Segment Selector——段選擇子。它的高13位作為被引用的段描述符在GDT/LDT中的下標索引,bit 2用來指定被引用段描述符被放在GDT中還是到LDT中,bit 0和bit 1是RPL——請求特權等級,被用來做保護目的,我們這里不詳細討論它。
前面所討論的裝入段寄存器中作為GDT/LDT索引的就是Segment Selector,當需要引用一個內存地址時,使用的仍然是Segment:Offset模式,具體操作是:在相應的段寄存器裝入Segment Selector,按照這個Segment Selector可以到GDT或LDT中找到相應的Segment Descriptor,這個Segment Descriptor中記錄了此段的Base Address,然後加上Offset,就得到了最後的內存地址。如下圖所示:
2. Setup GDT
由上一節的討論得知,GDT是Protected Mode所必須的數據結構,那麼我們在進入Protected Mode之前,必須設定好GDT,並通過LGDT將其裝入相應的寄存器。
盡管GDT允許被放在內存的任何位置,但由於GDT中的元素——描述符——都是64-bit長,也就是說都是8個位元組,所以為了讓CPU對GDT的訪問速度達到最快,我們應該將GDT的入口地址放在以8個位元組對齊,也就是說是8的倍數的地址位置。
GDT中第一個描述符必須是一個空描述符,也就是它的內容應該全部為0。如果引用這個描述符進行內存訪問,則是產生General Protection異常。
如果一個OS不使用虛擬內存,段模式會是一個不錯的選擇。但現代OS沒有不使用虛擬內存的,而實現虛擬內存的比較方便和有效的內存管理方式是頁式管理。但是在IA-32上如果我們想使用頁式管理,我們只能使用段頁式——沒有方法可以完全禁止段模式。但我們可以盡力讓段的效果降低的最小。
IA-32提供了一種被稱作「Basic Flat Model」的分段模式可以達到這種效果。這種模式要求在GDT中至少要定義兩個段描述符,一個用來引用Data Segment,另一個用來引用Code Segment。這2個Segment都包含整個線性空間,即Segment Limit = 4 GB,即使實際的物理內存遠沒有那麼多,但這個空間定義是為了將來由頁式管理來實現虛擬內存。
在這里,我們只是處於Booting階段,所以我們只需要初步設置一下GDT,等真正進入Protected Mode,啟動了OS Kernel之後,具體OS打算如何設置GDT,使用何種內存管理模式,由Kernel自身來設置,Booting只需要給Kernel的數據段和代碼段設置全部線性空間就可以了。
段描述符的格式如下圖所示:
具體到代碼段和數據段,它們的格式如下圖所示:
下面就是在Booting階段為進入Protected Mode而設置的臨時的gdt。這里定義了3個段描述符:第一個是系統規定的空描述符,第2個是引用4 GB線性空間的代碼段,第3個是引用4 GB線性空間的數據段。這是"Basic Flat Model"所要求的最下GDT設置,但就booting階段,只是為了進入Protected Mode,並為內核提供一個連續的,最大的線性空間這個目的而言,已經足夠了。
# Descriptor tables
gdt:
.word 0, 0, 0, 0 # mmy
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9A00 # code read/exec
.word 0x00CF # granularity = 4096, 386
# ( 5th nibble of limit)
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# ( 5th nibble of limit)
3. Load GDT
設置好GDT之後,我們需要通過LGDT指令將設定的gdt的入口地址和gdt表的大小裝入GDTR寄存器。
GDTR寄存器包括兩部分:32-bit的線性基地址,以及16-bit的GDT大小(以位元組為單位)。需要注意的是,對於32-bit線性基地址,必須是32-bit絕對物理地址,而不是相對於某個段的偏移量。而我們在Booting階段,在進入Protected Mode之前,我們CS和DS設置很可能不是0,所以我們必須計算出gdt的絕對物理地址。
為了執行LGDT指令,你需要把這兩部分內容放在內存的某個位置,然後將這個位置的內存地址作為操作數傳遞給LGDT指令。然後LGDT指令會自動將保存在這個位置的這兩部分值裝入GDTR寄存器。
# 這是存放GDTR所需的兩部分內容的位置
gdt_48:
.word 0x8000 # gdt limit=2048,
# 256 GDT entries
.word 0, 0 # gdt base (filled in later)
# 下面這段代碼用來計算GDT的32-bit線性地址,並將其裝入GDTR寄存器。
xorl ᖌ ᖀ# Compute gdt_base
movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
shll , ա
addl $gdt, ա
movl ᖌ (gdt_48 2)
lgdt gdt_48 # load gdt with whatever is appropriate
4. Other Preparing Stuff
在進入Protected Mode之前,除了需要設置和裝入GDT之外,還需要做如下一些事情:
屏蔽所有可屏蔽中斷;
裝入IDTR;
所有協處理器被正確的Reset。
由於在Real Mode和Protected Mode下的中斷處理機制有一些不同,所以在進入Protected Mode之前,務必禁止所有可屏蔽中斷,這可以通過下面兩種方法之一:
使用CLI指令;
對8259A可編程中斷控制器編程以屏蔽所有中斷。
即使當我們進入Protected Mode之後,也不能馬上將中斷打開,這時因為我們必須在OS Kernel中對相關的Protected Mode中斷處理所需的數據結構正確的初始化之後,才能打開中斷,否則會產生處理器異常。
在Real Mode下,中斷處理使用IVT(Interrupt Vector Table),在Protected Mode下,中斷處理使用IDT(Interrupt Descriptor Table),所以,我們必須在進入Protected Mode之前設置IDTR。
IDTR的格式和GDTR相同,IDTR的裝入方式和GDTR也相同。由於IDT中相關的中斷處理程序需要讓OS Kernel來設定,所以在Booting階段,我們只需要將IDTR中IDT的基地址和Size都設為0就可以了,隨後,等進入Protected Mode之後,由OS Kernel來真正設置它。
關於中斷機制和中斷處理,請參考 Interrupt