Kernel —— Hacks


initrd

initrd 本質上就是ramdisk,用來存儲數據的。至於是什麼數據,就是硬盤上的整個文件系統的閹割版,簡而言之就是Busybox,王家衛的《一代宗師》給我的感覺,反胃!趙本山說一個門派,要有人做裏子,有人做面子。面子要光彩奪目,容不的不乾淨的東西。裏子就要去面子做下三爛的勾當。內核要自己純淨一些,不要雜七亂八的東西。initrd就是裏子,就要替內核着想。系統啓動時需要掛載文件系統,可是文件系統是在硬盤上的,需要驅動。所以initrd裏面就包含了kernel需要用到的驅動。等kernel用驅動掛載了文件系統,initrd就被卸磨殺驢了。

如何製作initrd, dd 、編譯並copy busybox,到dd出來的文件裏,這就ok了。


Bootstrap parameters

splash: 貌似是背景吧。

Ramdisk

What is a RAM disk? A RAM disk is a portion of RAM which is being used as if it were a disk drive. RAM disks have fixed sizes, and act like regular disk partitions. Access time is much faster for a RAM disk than for a real, physical disk. However, any data stored on a RAM disk is lost when the system is shut down or powered off. RAM disks can be a great place to store temporary data.

mkfs.ext4 /dev/ram0 & mount /dev/ram0 /mnt



Kbuild


initcall

#define pure_initcall(fn) __define_initcall("0",fn,0)
#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
核心思想就是把所有的init函數編譯相同的segment裏,內核啓動時do_one_initcall調用,從0開始執行。
特別說下pure表示不需要其他的依靠,可以直接執行。可是net_ns_init和net_dev_init反了吧。


Kernel logging

 /proc/sys/kernel/printk

dmesg


hlist

hlist_node的成員有一個hlist_node ** pprev,不是普通的一級指針。爲什麼這樣?原因還得從內存緊張說起,hlist_head,只有一個fist指針,爲了省內存。既然是循環鏈表那麼第一個hlist_node就得指向即頭,可類型是hlist_head,這樣hlist_node再用prev指向hlist_head就不和諧了,可是頭有一個hlist_node的指針,每個節點也有這個指針所以pprev指向next的地址。
另見這裏


Notifier chains
只是簡單的事件相應機制,核心還是callback函數沒有什麼新意。callback函數會被封裝到notifier_block當中。顯然我們會把由聯繫的notifier_block,放到一個鏈表。爲什麼放到一塊,效率!struct raw_notifier_head 就是這個集合的頭!notifier block分爲4類,atomic在中斷中,blocking進程上下文中,raw你自己看着用,sruc這種還不理解Sleepable Read-Copy Update mechanism 自己google吧。操作notifier_chain_register()用來註冊nb,notifier_chain_register一般由驅動調用,喚醒notifier block的callback function。當然內核也會調用。

Variable arguments

我又一次將問題複雜化了。

typedef char *va_list;

//向上 or 向下對齊大小
#define  _AUPBND                (sizeof (acpi_native_int) - 1)
#define  _ADNBND                (sizeof (acpi_native_int) - 1)

//對齊後的size
#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))

//va_arg, 很巧。先加上一個size,ap指向下一個參數,之後減去一個size,再取值,即ap舊的值。
#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)              (void) 0

//指向第二個參數,你還記得x86是如何傳參的嗎?先壓右面的參數。爲什麼不是左面?stack是從高向低生長的!

//也正因爲這樣的入棧方式,最後入棧的是參數列表上的第一個參數(下例的“1”)在stack的低地址處。通過這個地址找到全部參數,這就是Variable arguments的紅肚兜,其實沒什麼。

#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
For example:void arg_test(1, 2, 3, 4)

void arg_test(int i, ...)//從下面的調用可知 i == 1,  ... == 2 3  4

{va_list va; //臨時指針,起到迭代器的作用。

va_start(va, i); // va == &2, 

va_arg(va,int);//返回值 2,va ==&3

va_arg(va,int);//返回值 3, va== &4

va_end(va);

}


Terminal

http://www.linusakesson.net/programming/tty/

最開始,在股票市場,typewriter + wires + ticker tape priter。 很簡單的組合,目地就是爲了打印出股票價格。

後來,概念被拓展了涉及到網絡Teletype + telex(網絡) ,此時還是和計算機沒關係。

事情變味了,Terminal(VT-100)+ wires + computer(可多任務的大型機)

一發不可收拾,Keboard,VGA monitor + Terminal emulator(in computer)

linux console 和 gnome terminal 都是 terminal emulator,功能上是沒有區別的, 實現上console是由 kenrel 提供。 gnome-terminal是構築在 X上的。


tty

Virtual console: 

/dev/tty1 就是virtual console對應Ctrl + alt + F1, X出現後virtual console用的就少了。

/dev/tty0 從用戶角度看正在使用(foreground)的virtual console前使用的virtual console,tty0 只能指代virtual console,不能指代X下的pty。

/dev/tty  在進程的task_struct 會保存一個使用的終端,tty就關聯到進程裏的這個終端。從進程角度出發,和用戶正在使用那個foreground 終端無關,可以代表virutal console 和pty 等

區分tty 和tty 0

/dev/console  就是內核啓動命令的傳參那個,一般和tty0一樣,可能指定爲ttys0.




Carriage return

Typewriter’s carriage /r 13

Line feed /n 10

newline linux /n windows /r/n


init 

 指pid 1到桌面啓動過程。
SysVinit:最早的init,已被各種替代。
Upstart:origin form ubuntu
Upstart Intro, Cookbook and Best Practises
/etc/init: system job is where the upstart init configs live. While they are not scripts themselves, they essentially execute whatever is required to replace sysvinit scripts.
/etc/init.d is where all the traditional sysvinit scripts and the backward compatible scripts for upstart live. The backward compatible scripts basically run
service myservice start instead of doing anything themselves. Some just show a notice to use the "service" command.
reboot -> runlevel RUNLEVEL=6 PREVLEVEL=2 -> /etc/init/rc.conf -> /etc/init.d/rc with 6 -> /etc/rc6.d/*
init -> init.d -> rcN.d
rc.local
systemd:Fedora 15 and next RHEL 7 will used it
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章