1. 程式人生 > >Linux2.6 核心的 Initrd 機制解析

Linux2.6 核心的 Initrd 機制解析

initrd 的英文含義是 boot loader initialized RAM disk,就是由 boot loader 初始化的記憶體盤。在 linux核心啟動前, boot loader 會將儲存介質中的 initrd 檔案載入到記憶體,核心啟動時會在訪問真正的根檔案系統前先訪問該記憶體中的 initrd 檔案系統。在 boot loader 配置了 initrd 的情況下,核心啟動被分成了兩個階段,第一階段先執行 initrd 檔案系統中的"某個檔案",完成載入驅動模組等任務,第二階段才會執行真正的根檔案系統中的 /sbin/init 程序。這裡提到的"某個檔案",Linux2.6 核心會同以前版本核心的不同,所以這裡暫時使用了"某個檔案"這個稱呼,後面會詳細講到。第一階段啟動的目的是為第二階段的啟動掃清一切障愛,最主要的是載入根檔案系統儲存介質的驅動模組。我們知道根檔案系統可以儲存在包括IDE、SCSI、USB在內的多種介質上,如果將這些裝置的驅動都編譯進核心,可以想象核心會多麼龐大、臃腫。

Initrd 的用途主要有以下四種:

1. linux 發行版的必備部件

linux 發行版必須適應各種不同的硬體架構,將所有的驅動編譯進核心是不現實的,initrd 技術是解決該問題的關鍵技術。Linux 發行版在核心中只編譯了基本的硬體驅動,在安裝過程中通過檢測系統硬體,生成包含安裝系統硬體驅動的 initrd,無非是一種即可行又靈活的解決方案。

2. livecd 的必備部件

同 linux 發行版相比,livecd 可能會面對更加複雜的硬體環境,所以也必須使用 initrd。

3. 製作 Linux usb 啟動盤必須使用 initrd

usb 裝置是啟動比較慢的裝置,從驅動載入到裝置真正可用大概需要幾秒鐘時間。如果將 usb 驅動編譯進核心,核心通常不能成功訪問 usb 裝置中的檔案系統。因為在核心訪問 usb 裝置時, usb 裝置通常沒有初始化完畢。所以常規的做法是,在 initrd 中載入 usb 驅動,然後休眠幾秒中,等待 usb裝置初始化完畢後再掛載 usb 裝置中的檔案系統。

4. 在 linuxrc 指令碼中可以很方便地啟用個性化 bootsplash。





回頁首


為了使讀者清晰的瞭解Linux2.6核心initrd機制的變化,在重點介紹Linux2.6核心initrd之前,先對linux2.4核心的initrd進行一個簡單的介紹。Linux2.4核心的initrd的格式是檔案系統映象檔案,本文將其稱為image-initrd,以區別後面介紹的linux2.6核心的cpio格式的initrd。 linux2.4核心對initrd的處理流程如下:

1. boot loader把核心以及/dev/initrd的內容載入到記憶體,/dev/initrd是由boot loader初始化的裝置,儲存著initrd。

2. 在核心初始化過程中,核心把 /dev/initrd 裝置的內容解壓縮並拷貝到 /dev/ram0 裝置上。

3. 核心以可讀寫的方式把 /dev/ram0 裝置掛載為原始的根檔案系統。

4. 如果 /dev/ram0 被指定為真正的根檔案系統,那麼核心跳至最後一步正常啟動。

5. 執行 initrd 上的 /linuxrc 檔案,linuxrc 通常是一個指令碼檔案,負責載入核心訪問根檔案系統必須的驅動, 以及載入根檔案系統。

6. /linuxrc 執行完畢,真正的根檔案系統被掛載。

7. 如果真正的根檔案系統存在 /initrd 目錄,那麼 /dev/ram0 將從 / 移動到 /initrd。否則如果 /initrd 目錄不存在, /dev/ram0 將被解除安裝。

8. 在真正的根檔案系統上進行正常啟動過程 ,執行 /sbin/init。 linux2.4 核心的 initrd 的執行是作為核心啟動的一箇中間階段,也就是說 initrd 的 /linuxrc 執行以後,核心會繼續執行初始化程式碼,我們後面會看到這是 linux2.4 核心同 2.6 核心的 initrd 處理流程的一個顯著區別。





回頁首


linux2.6 核心支援兩種格式的 initrd,一種是前面第 3 部分介紹的 linux2.4 核心那種傳統格式的檔案系統映象-image-initrd,它的製作方法同 Linux2.4 核心的 initrd 一樣,其核心檔案就是 /linuxrc。另外一種格式的 initrd 是 cpio 格式的,這種格式的 initrd 從 linux2.5 起開始引入,使用 cpio 工具生成,其核心檔案不再是 /linuxrc,而是 /init,本文將這種 initrd 稱為 cpio-initrd。儘管 linux2.6 核心對 cpio-initrd和 image-initrd 這兩種格式的 initrd 均支援,但對其處理流程有著顯著的區別,下面分別介紹 linux2.6 核心對這兩種 initrd 的處理流程。

1. boot loader 把核心以及 initrd 檔案載入到記憶體的特定位置。

2. 核心判斷initrd的檔案格式,如果是cpio格式。

3. 將initrd的內容釋放到rootfs中。

4. 執行initrd中的/init檔案,執行到這一點,核心的工作全部結束,完全交給/init檔案處理。

1. boot loader把核心以及initrd檔案載入到記憶體的特定位置。

2. 核心判斷initrd的檔案格式,如果不是cpio格式,將其作為image-initrd處理。

3. 核心將initrd的內容儲存在rootfs下的/initrd.image檔案中。

4. 核心將/initrd.image的內容讀入/dev/ram0裝置中,也就是讀入了一個記憶體盤中。

5. 接著核心以可讀寫的方式把/dev/ram0裝置掛載為原始的根檔案系統。

6. .如果/dev/ram0被指定為真正的根檔案系統,那麼核心跳至最後一步正常啟動。

7. 執行initrd上的/linuxrc檔案,linuxrc通常是一個指令碼檔案,負責載入核心訪問根檔案系統必須的驅動, 以及載入根檔案系統。

8. /linuxrc執行完畢,常規根檔案系統被掛載

9. 如果常規根檔案系統存在/initrd目錄,那麼/dev/ram0將從/移動到/initrd。否則如果/initrd目錄不存在, /dev/ram0將被解除安裝。

10. 在常規根檔案系統上進行正常啟動過程 ,執行/sbin/init。

通過上面的流程介紹可知,Linux2.6核心對image-initrd的處理流程同linux2.4核心相比並沒有顯著的變化, cpio-initrd的處理流程相比於image-initrd的處理流程卻有很大的區別,流程非常簡單,在後面的原始碼分析中,讀者更能體會到處理的簡捷。

沒有找到正式的關於cpio-initrd同image-initrd對比的文獻,根據筆者的使用體驗以及核心程式碼的分析,總結出如下三方面的區別,這些區別也正是cpio-initrd的優勢所在:

cpio-initrd的製作非常簡單,通過兩個命令就可以完成整個製作過程



#假設當前目錄位於準備好的initrd檔案系統的根目錄下
bash# find . | cpio -c -o > ../initrd.img
bash# gzip ../initrd.img

而傳統initrd的製作過程比較繁瑣,需要如下六個步驟



#假設當前目錄位於準備好的initrd檔案系統的根目錄下
bash# dd if=/dev/zero of=../initrd.img bs=512k count=5
bash# mkfs.ext2 -F -m0 ../initrd.img
bash# mount -t ext2 -o loop ../initrd.img  /mnt
bash# cp -r  * /mnt
bash# umount /mnt
bash# gzip -9 ../initrd.img

本文不對上面命令的含義作細節的解釋,因為本文主要介紹的是linux核心對initrd的處理,對上面命令不理解的讀者可以參考相關文件。

通過上面initrd處理流程的介紹,cpio-initrd的處理流程顯得格外簡單,通過對比可知cpio-initrd的處理流程在如下兩個方面得到了簡化:

1. cpio-initrd並沒有使用額外的ramdisk,而是將其內容輸入到rootfs中,其實rootfs本身也是一個基於記憶體的檔案系統。這樣就省掉了ramdisk的掛載、解除安裝等步驟。

2. cpio-initrd啟動完/init程序,核心的任務就結束了,剩下的工作完全交給/init處理;而對於image-initrd,核心在執行完/linuxrc程序後,還要進行一些收尾工作,並且要負責執行真正的根檔案系統的/sbin/init。通過圖1可以更加清晰的看出處理流程的區別:



圖1核心對cpio-initrd和image-initrd處理流程示意圖
圖1核心對cpio-initrd和image-initrd處理流程示意圖

如圖1所示,cpio-initrd不再象image-initrd那樣作為linux核心啟動的一箇中間步驟,而是作為核心啟動的終點,核心將控制權交給cpio-initrd的/init檔案後,核心的任務就結束了,所以在/init檔案中,我們可以做更多的工作,而不比擔心同核心後續處理的銜接問題。當然目前linux發行版的cpio-initrd的/init檔案的內容還沒有本質的改變,但是相信initrd職責的增加一定是一個趨勢。





回頁首


上面簡要介紹了Linux2.4核心和2.6核心的initrd的處理流程,為了使讀者對於Linux2.6核心的initrd的處理有一個更加深入的認識,下面將對Linuxe2.6核心初始化部分同initrd密切相關的程式碼給予一個比較細緻的分析,為了講述方便,進一步明確幾個程式碼分析中使用的概念:

rootfs: 一個基於記憶體的檔案系統,是linux在初始化時載入的第一個檔案系統,關於它的進一步介紹可以參考文獻[4]。

initramfs: initramfs同本文的主題關係不是很大,但是程式碼中涉及到了initramfs,為了更好的理解程式碼,這裡對其進行簡單的介紹。Initramfs是在 kernel 2.5中引入的技術,實際上它的含義就是:在核心映象中附加一個cpio包,這個cpio包中包含了一個小型的檔案系統,當核心啟動時,核心將這個cpio包解開,並且將其中包含的檔案系統釋放到rootfs中,核心中的一部分初始化程式碼會放到這個檔案系統中,作為使用者層程序來執行。這樣帶來的明顯的好處是精簡了核心的初始化程式碼,而且使得核心的初始化過程更容易定製。Linux 2.6.12核心的 initramfs還沒有什麼實質性的東西,一個包含完整功能的initramfs的實現可能還需要一個緩慢的過程。對於initramfs的進一步瞭解可以參考文獻[1][2][3]。

cpio-initrd: 前面已經定義過,指linux2.6核心使用的cpio格式的initrd。

image-initrd: 前面已經定義過,專指傳統的檔案映象格式的initrd。

realfs: 使用者最終使用的真正的檔案系統。

核心的初始化程式碼位於 init/main.c 中的 static int init(void * unused)函式中。同initrd的處理相關部分函式呼叫層次如下圖,筆者按照這個層次對每一個函式都給予了比較詳細的分析,為了更好的說明,下面列出的程式碼中刪除了同本文主題不相關的部分:



圖2 initrd相關程式碼的呼叫層次關係圖
圖2 initrd相關程式碼的呼叫層次關係圖

init函式是核心所有初始化程式碼的入口,程式碼如下,其中只保留了同initrd相關部分的程式碼。



static int init(void * unused){
[1]	populate_rootfs();
	
[2]	if (sys_access((const char __user *) "/init", 0) == 0)
		execute_command = "/init";
	else
		prepare_namespace();

[3]	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		printk(KERN_WARNING "Warning: unable to open an initial console./n");

	(void) sys_dup(0);
	(void) sys_dup(0);

[4]	if (execute_command)
		run_init_process(execute_command);

	run_init_process("/sbin/init");
	run_init_process("/etc/init");
	run_init_process("/bin/init");
	run_init_process("/bin/sh");
	panic("No init found.  Try passing init= option to kernel.");
}

程式碼[1]:populate_rootfs函式負責載入initramfs和cpio-initrd,對於populate_rootfs函式的細節後面會講到。

程式碼[2]:如果rootfs的根目錄下中包含/init程序,則賦予execute_command,在init函式的末尾會被執行。否則執行prepare_namespace函式,initrd是在該函式中被載入的。

程式碼[3]:將控制檯設定為標準輸入,後續的兩個sys_dup(0),則複製標準輸入為標準輸出和標準錯誤輸出。

程式碼[4]:如果rootfs中存在init程序,就將後續的處理工作交給該init程序。其實這段程式碼的含義是如果載入了cpio-initrd則交給cpio-initrd中的/init處理,否則會執行realfs中的init。讀者可能會問:如果載入了cpio-initrd, 那麼realfs中的init程序不是沒有機會運行了嗎?確實,如果載入了cpio-initrd,那麼核心就不負責執行realfs的init程序了,而是將這個執行任務交給了cpio-initrd的init程序。解開fedora core4的initrd檔案,會發現根目錄的下的init檔案是一個指令碼,在該指令碼的最後一行有這樣一段程式碼:



………..
switchroot --movedev /sysroot

就是switchroot語句負責載入realfs,以及執行realfs的init程序。

對cpio-initrd的處理位於populate_rootfs函式中。



void __init populate_rootfs(void){
[1]  char *err = unpack_to_rootfs(__initramfs_start,
			 __initramfs_end - __initramfs_start, 0);
[2]	if (initrd_start) {
[3]		err = unpack_to_rootfs((char *)initrd_start,
			initrd_end - initrd_start, 1);
	
[4]		if (!err) {
			printk(" it is/n");
			unpack_to_rootfs((char *)initrd_start,
				initrd_end - initrd_start, 0);
			free_initrd_mem(initrd_start, initrd_end);
			return;
		}

[5]		fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 700);
		if (fd >= 0) {
			sys_write(fd, (char *)initrd_start,
					initrd_end - initrd_start);
			sys_close(fd);
			free_initrd_mem(initrd_start, initrd_end);
		}
}

程式碼[1]:載入initramfs, initramfs位於地址__initramfs_start處,是核心在編譯過程中生成的,initramfs的是作為核心的一部分而存在的,不是 boot loader載入的。前面提到了現在initramfs沒有任何實質內容。

程式碼[2]:判斷是否載入了initrd。無論哪種格式的initrd,都會被boot loader載入到地址initrd_start處。

程式碼[3]:判斷載入的是不是cpio-initrd。實際上 unpack_to_rootfs有兩個功能一個是釋放cpio包,另一個就是判斷是不是cpio包, 這是通過最後一個引數來區分的, 0:釋放 1:檢視。

程式碼[4]:如果是cpio-initrd則將其內容釋放出來到rootfs中。

程式碼[5]:如果不是cpio-initrd,則認為是一個image-initrd,將其內容儲存到/initrd.image中。在後面的image-initrd的處理程式碼中會讀取/initrd.image。

對image-initrd的處理在prepare_namespace函式裡,包含了對image-initrd進行處理的程式碼,相關程式碼如下:



void __init prepare_namespace(void){
[1]	if (initrd_load())
		goto out;

out:
		umount_devfs("/dev");
[2]		sys_mount(".", "/", NULL, MS_MOVE, NULL);
		sys_chroot(".");
		security_sb_post_mountroot();
		mount_devfs_fs ();
}

程式碼[1]:執行initrd_load函式,將initrd載入,如果載入成功的話initrd_load函式會將realfs的根設定為當前目錄。

程式碼[2]:將當前目錄即realfs的根mount為Linux VFS的根。initrd_load函式執行完後,將真正的檔案系統的根設定為當前目錄。

initrd_load函式負責載入image-initrd,程式碼如下:



int __init initrd_load(void)
{
[1]	if (mount_initrd) {
		create_dev("/dev/ram", Root_RAM0, NULL);
[2]		if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
			sys_unlink("/initrd.image");
			handle_initrd();
			return 1;
		}
	}
	sys_unlink("/initrd.image");
	return 0;
}

程式碼[1]:如果載入initrd則建立一個ram0裝置 /dev/ram。

程式碼[2]:/initrd.image檔案儲存的就是image-initrd,rd_load_image函式執行具體的載入操作,將image-nitrd的檔案內容釋放到ram0裡。判斷ROOT_DEV!=Root_RAM0的含義是,如果你在grub或者lilo裡配置了 root=/dev/ram0 ,則實際上真正的根裝置就是initrd了,所以就不把它作為initrd處理 ,而是作為realfs處理。

handle_initrd()函式負責對initrd進行具體的處理,程式碼如下:



	static void __init handle_initrd(void){
[1]	real_root_dev = new_encode_dev(ROOT_DEV);
[2]	create_dev("/dev/root.old", Root_RAM0, NULL);
	mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
[3]	sys_mkdir("/old", 0700);
	root_fd = sys_open("/", 0, 0);
	old_fd = sys_open("/old", 0, 0);

	/* move initrd over / and chdir/chroot in initrd root */
[4]	sys_chdir("/root");
	sys_mount(".", "/", NULL, MS_MOVE, NULL);
	sys_chroot(".");
	mount_devfs_fs ();

[5]	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
	if (pid > 0) {
		while (pid != sys_wait4(-1, &i, 0, NULL))
			yield();
	}

	/* move initrd to rootfs' /old */
	sys_fchdir(old_fd);
	sys_mount("/", ".", NULL, MS_MOVE, NULL);

	/* switch root and cwd back to / of rootfs */
[6]	sys_fchdir(root_fd);
	sys_chroot(".");
	sys_close(old_fd);
	sys_close(root_fd);
	umount_devfs("/old/dev");

[7]	if (new_decode_dev(real_root_dev) == Root_RAM0) {
		sys_chdir("/old");
		return;
	}

[8]	ROOT_DEV = new_decode_dev(real_root_dev);
	mount_root();

[9]	printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
	error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
	if (!error)
		printk("okay/n");
	else {
		int fd = sys_open("/dev/root.old", O_RDWR, 0);
		printk("failed/n");
		printk(KERN_NOTICE "Unmounting old root/n");
		sys_umount("/old", MNT_DETACH);
		printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
		if (fd < 0) {
			error = fd;
		} else {
			error = sys_ioctl(fd, BLKFLSBUF, 0);
			sys_close(fd);
		}
		printk(!error ? "okay/n" : "failed/n");
	}
	

handle_initrd函式的主要功能是執行initrd的linuxrc檔案,並且將realfs的根目錄設定為當前目錄。

程式碼[1]:real_root_dev,是一個全域性變數儲存的是realfs的裝置號。

程式碼[2]:呼叫mount_block_root函式將initrd檔案系統掛載到了VFS的/root下。

程式碼[3]:提取rootfs的根的檔案描述符並將其儲存到root_fd。它的作用就是為了在chroot到initrd的檔案系統,處理完initrd之後要,還能夠返回rootfs。返回的程式碼參考程式碼[7]。

程式碼[4]:chroot進入initrd的檔案系統。前面initrd已掛載到了rootfs的/root目錄。

程式碼[5]:執行initrd的linuxrc檔案,等待其結束。

程式碼[6]:initrd處理完之後,重新chroot進入rootfs。

程式碼[7]:如果real_root_dev在 linuxrc中重新設成Root_RAM0,則initrd就是最終的realfs了,改變當前目錄到initrd中,不作後續處理直接返回。

程式碼[8]:在linuxrc執行完後,realfs裝置已經確定,呼叫mount_root函式將realfs掛載到root_fs的 /root目錄下,並將當前目錄設定為/root。

程式碼[9]:後面的程式碼主要是做一些收尾的工作,將initrd的記憶體盤釋放。

到此程式碼分析完畢。





回頁首


6.結束語

通過本文前半部分對cpio-initrd和imag-initrd的闡述與對比以及後半部分的程式碼分析,我相信讀者對Linux 2.6核心的initrd技術有了一個較為全面的瞭解。在本文的最後,給出兩點最重要的結論:

1. 儘管Linux2.6既支援cpio-initrd,也支援image-initrd,但是cpio-initrd有著更大的優勢,在使用中我們應該優先考慮使用cpio格式的initrd。

2. cpio-initrd相對於image-initrd承擔了更多的初始化責任,這種變化也可以看作是核心程式碼的使用者層化的一種體現,我們在其它的諸如FUSE等專案中也看到了將核心功能擴充套件到使用者層實現的嘗試。精簡核心程式碼,將部分功能移植到使用者層必然是linux核心發展的一個趨勢。





回頁首


參考資料

從下面三篇文章中,可以獲得更多的關於initramfs的知識:

從下面這篇文章中讀者可以瞭解到關於linux VSF、rootfs的相關知識:

下面是一些initrd的參考資料:





回頁首






回頁首


關於作者

李大治,軟體工程師,目前從事Linux平臺下網路安全產品的開發工作,您可以通過[email protected]同他取得聯絡。

相關推薦

Linux2.6 核心Initrd 機制解析

initrd 的英文含義是 boot loader initialized RAM disk,就是由 boot loader 初始化的記憶體盤。在 linux核心啟動前, boot loader 會將儲存介質中的 initrd 檔案載入到記憶體,核心啟動時會在訪問真正的根檔

Linux2.6核心--中斷下半部實現方法 工作佇列

      工作佇列子系統是一個用於建立核心執行緒的介面,通過它建立的程序負責執行由核心其他部分排到佇列裡的任務。它建立的這些核心執行緒稱作工作者執行緒。工作佇列可以讓你的驅動程式建立一個專門的工作者執

Linux2.6核心(CentOS)中編譯核心模組的一個例子

使用的簡單測試記憶體原始檔hello.c: ------------------------------------------------------------------------- #include <linux/module.h>      /* Needed by all mod

Linux 2.6核心中新的鎖機制--RCU

一、 引言 眾所周知,為了保護共享資料,需要一些同步機制,如自旋鎖(spinlock),讀寫鎖(rwlock),它們使用起來非常簡單,而且是一種很有效的同步機制,在UNIX系統和Linux系統中得到了廣泛的使用。但是隨著計算機硬體的快速發展,獲得這種鎖的開銷相對於CPU

5.Linux核心設計與實現 P39---linux2.6 CFS排程演算法分析(轉)

1.概述      CFS(completely fair schedule)是最終被核心採納的排程器。它從RSDL/SD中吸取了完全公平的思想,不再跟蹤程序的睡眠時間,也不再企圖區分互動式程序。它將所有的程序都統一對待,這就是公平的含義。CFS的演算法和實現都相當簡單,眾多的測試表明其效能也非常優越。   

iscsitarget 在Linux2.6.32核心上編譯 若干編譯錯誤與解決方法(備忘)

#make make -C usr make[1]: Entering directory `/work/iscsitarget-0.4.16/usr' cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include 

Linux 核心網路協議棧 ----- Linux 核心路由機制(一) (2.6.25)

       核心的路由部分是是網路中重要部分,目前在Linux核心中預設的路由查詢演算法使用的是Hash查詢,所以你會看到很多的資料結構是XXX_hash什麼之類(例如fn_hash)。Linux核心從2.1開始就支援基於策略的路由,那麼什麼是基於策略的路由呢?我們一般

mini6410基於linux2.6.36核心通過NFS啟動根檔案系統總結(四製作根檔案系統及通過NFS掛載檔案系統)

本系列文章有本人yinjiabin製作,轉載請註明出處: http://blog.csdn.net/yinjiabin/article/details/7489563根檔案系統一般包括: 1)基本的檔案系統結構,包含一些必須的目錄,比如:/dev,/proc,/bin,/

PHP核心之旅-6.垃圾回收機制

回收PHP 核心之旅系列 一、引用計數 只有使用引用計數的變數才需要回收。引用計數就是用來標記變數的引用次數的。 當有新的變數zval指向value時,計數器加1,當變數zval銷燬時,計數器減一。當引用計數為0時,表示此value沒有被任何變數指向,可以對value進行釋放。 下面的例子說明引用

Dubbo原理和原始碼解析之“微核心+外掛”機制

private void loadFile(Map<String, Class<?>> extensionClasses, String dir) { //...... BufferedReader reader = new BufferedReader(new

inotify -- Linux 2.6 核心中的檔案系統變化通知機制

一、 引言 眾所周知,Linux 桌面系統與 MAC 或 Windows 相比有許多不如人意的地方,為了改善這種狀況,開源社群提出使用者態需要核心提供一些機制,以便使用者態能夠及時地得知核心或底層硬體裝置發生了什麼,從而能夠更好地管理裝置,給使用者提供更好的服務,如 hotplug、udev 和 ino

ETCD核心機制解析

ETCD整體機制 etcd 是一個分散式的、可靠的 key-value 儲存系統,它適用於儲存分散式系統中的關鍵資料。 etcd 叢集中多個節點之間通過Raft演算法完成分散式一致性協同,演算法會選舉出一個主節點作為 leader,由 leader 負責資料的同步與分發。當 leader 出現故障後系統會自動

Oracle SCN機制解析

丟失 self pen 必須 發出 span system 幫助 不同的 SCN(System Chang Number)作為oracle中的一個重要機制,在數據恢復、Data Guard、Streams復制、RAC節點間的同步等各個功能中起著重要作用。理解SCN的運作機制

筆記:XML-解析文檔-流機制解析器(SAX、StAX)

輸入 tex 字符數 表示 getname 重要 樹形 puts ron DOM 解析器完整的讀入XML文檔,然後將其轉換成一個樹型的數據結構,對於大多數應用,DOM 都運行很好,但是,如果文檔很大,並且處理算法又非常簡單,可以在運行時解析節點,而不必看到完整的樹形

Quartz定時任務調度機制解析(CronTirgger、SimpleTrigger )

sched 它的 main 目前 可選值 -- 實現接口 不能 三種 一、Quartz的介紹   Quartz 是 OpenSymphony 開源組織在任務調度領域的一個開源項目,完全基於 Java 實現。該項目於 2009 年被 Terracotta 收購,目前是 Te

vuex所有核心概念完整解析State Getters Mutations Actions

function 鉤子 action 元素事件 getter 參數 pst isp 文件中 vuex是解決vue組件和組件間相互通信而存在的,vuex理解起來稍微復雜,但一旦看懂則即為好用: 安裝: npm install --save vuex 引入 import

centos 6.8模板機制

centos第一章虛擬化NAT網絡設置使用DHCP自動獲取IP地址第二章創建虛擬機第三章安裝CentOS-6.8-x86_64-bin-DVD1操作系統第四章模板機優化開機後使用命令ifup eth0獲取到IP地址後。用SecureCRT連接。4.1SecureCRT設置4.2系統優化優化開機網卡啟動sed

3.6 C++繼承機制下的構造函數

需要 類的構造函數 color view ice 如果 itl 不難 tor 參考:http://www.weixueyuan.net/view/6363.html 總結:   在codingbook類中新增了一個language成員變量,為此必須重新設計新的構造函數。在本

3.1_SpringBoot內部處理機制解析

ext tom list process eba 版本 代碼 http eric 前言 目前基於SpringBoot進行Web應用開發已經成為一個趨勢,Spring官網內部的很多入門Demo都是基於SpringBoot的,因此掌握SpringBoot成為當下基於Java的W

JAVA動態代理機制解析

定義 book lang 並不是 stat 控制 () highlight 什麽 1. 概述  首先,我們來思考如下兩個問題:  什麽是代理模式?為什麽要使用代理模式?   簡單總結一下,所謂的代理模式就是在原有的服務上多加一個占位,通過這個占位去控制服務的訪問。通過代理模