1.進程直接使用物理內存的壞處:第1、地址空間不隔離,1個進程可能改寫另外一個進程的數據,從而致使系統崩潰。第2、內存使用效力低,頻繁的數據換入換出,效力低。第3、程序運行地址不穩定,每次重新裝載的空閑區域位置不肯定。
2.虛擬地址和物理地址是為了隔離進程。
3.分段使用1段虛擬空間和物理空間的映照解決了地址空間隔離和程序運行地址穩定的問題。但是內存使用效力由于內存不足時換入換出到磁盤的還是全部程序,因此會有大量的磁盤訪問操作,粒度比較大。程序在運行時候,常常只會訪問部份數據,大部份數據是不會被頻繁的使用的,因此將粒度更小化,局部性原理得到利用,就有了分頁機制。
4.Linux中的缺頁異常機制,其實這本質上是1種動態分配內存的機制,然后每一個頁有自己的屬性,利用MMU來進行頁映照。
5.線程是輕量級的進程,1個標準的線程是由線程ID、當前指令指針PC、寄存器集合和堆棧組成,線程同享程序的內存空間,包括代碼段,數據段,堆等。
6.多線程的好處:多線程可以有效利用1個線程等待的時候去做其他的事情;長時任務,1個線程負責計算,1個線程負責交互;適應多核或多cpu計算機;同享數據效力高。
7.線程私有數據為局部變量、TLS局部存儲、函數參數,同享的為全局變量、堆數據、函數靜態變量、程序代碼和打開的文件。
8.線程的狀態有運行、就緒和等待。
9.頻繁計算的線程叫CPU密集型線程,頻繁等待的線程叫I/O密集型線程,后者相對來講更加受歡迎。
10.fork和execl,寫時復制機制,LDDR3講的很清楚。
11.i++這個指令轉化成匯編的時候不只是1條指令,因此有可能在履行到1半的時候被打斷,單指令操作叫做原子操作。
12.臨界區的作用范圍僅限于本進程,其他的進程沒法獲得該鎖。其余性質和互斥量基本相同。
13.1個函數可重入,表示這個函數沒有履行完成,由于外部因素或內部調用又1次進入函數履行,1個函數要被重入,有兩種情況:第1、多個線程同時履行這個函數。第2、函數本身(多是經過量層調用以后)調用本身。
14.可重入的特點。。。,保障并發安全。
15.volatile關鍵字可以制圖組織過度優化,這個在很多寄存器操作中用到過。
16.linux內核代碼中使用了眾多的if語句,這里得到解釋,原來是可以將lock的調用開消下降到最小,具體為何,后期琢磨。
17.barrier指令是用于禁止cpu將該指令之前的指令交換到以后,linux內核源碼中也見到過。
18.1對1的線程模型讓多線程程序在多處理器的系統上具有更好的表現,但是內核限制內核線程的數量,1對1線程會讓用戶的線程數量遭到限制,另外上下文切換開消較大,
19.多對1的線程模型可以具有無尚限的線程,上下文切換效力高,但是多處理器性能不會有明顯提升,并且當1個阻塞,其余的都會阻塞。
1.gcc是后臺程序的包裝,不同的語言調用不用的預編譯和編譯工具。
2.重新計算各個目標地址的進程叫做重定位。
3.符號被用來表示表示1段子程序(函數)或變量的起始地址。匯編語言中jmp等指令可以理解為符號?
4.預編譯、編譯、匯編和鏈接。
5.動態鏈接庫和靜態鏈接庫都依照可履行文件進行存儲。
6.程序源代碼編譯后的機器指令寄存在代碼段,.test或.code,全局變量、局部靜態變量寄存在.data段,未初始化的全局變量、局部靜態變量寄存在.bss段(預留),目標文件的開頭包括段屬性,文件內的偏移地址,還有每一個段的信息。
7.指令和數據分離的好處:第1、數據和指令的權限不同。第2、支持數據緩存和指令緩存。第3、節省內存。
8.readelf和obkdump工具的使用。
9.編譯器的優化屏蔽了1些細節,對了解系統工作機制和調試有1定的影響。
10..bss段寄存的是未初始化的全局變量和局部靜態變量,.data寄存了初始化的全局靜態變量和局部靜態變量。
11.有時希望函數中的局部變量的值在函數調用結束后不消失而保存原值,即其占用的存儲單元不釋放,在下1次該函數調用時,該變量保存上1次函數調用結束時的值。這時候就應當指定該局部變量為靜態局部變量(static local variable)。 把局部變量改變成靜態變量后是改變了它的存儲方式,即改變了它的生存期。把全局變量改變成靜態變量后是改變了它的作用域,限制了它的使用范圍。
12.馬屁股決定航天飛機的寬度的故事,遺留問題。
13.鏈接的進程實際上是對地址的援用,即對函數和變量地址的援用,所謂符號就是函數和變量的名稱,符號值就是他們的地址。可使用nm來查看符號。
14.ELF文件中的符號表是1個段,名稱為.symtab。
15.readelf –s xxxx.o查看符號在符號表中的狀態。
16.使用ld來鏈接的時候,會自動定義1些特殊符號,例如程序起始地址,代碼段結束地址,數據段結束地址等。
17.編譯后的符號前后加上_是為了解決符號名沖突的問題,后來使用“簽名機制”解決該問題。
18.extern “C”是表示編譯器依照C規則進行編譯。
19.強符號、弱符號,強援用和弱援用概念。
20.gcc –g添加調試信息。
21.鏈接器采取兩步鏈接方法,行將各個目標文件中相同的段進行合并,再鏈接成1個大的目標文件。第1步:空間與地址分配(虛擬地址,注意BSS段)。第2步:符號解析與重定位。重定位進程最重要!
22.ld a.o b.o –e main –o ab,-e指定程序的入口為main函數,ld默許的為_start。
23.符號解析的肯定是通過分配得各個段的起始虛擬地址加上偏移量來的,(操作系統中,偏移量的使用無處不在啊)
24.重定位表被用來保存與重定位相干的信息,.rel.text,也叫重定位段,鏈接器根據這個重定位符號。
25.符號的解析占據了鏈接進程的大部份。
26.undefined reference xxxx1般都是由于鏈接時候缺少了某個庫,或輸入目標文件路徑不正確或符號的聲明與定義不1致。
27.指令修正,絕對地址和相對地址,分別為S+A和S+A-P,絕對地址為該符號的實際地址,相對地址為與符號與被修正地址的地址差。
28.common塊機制處理弱符號解析的問題。
29.API是源碼級別的利用程序接口,例如POSIX。ABI是2進制文件層面的接口,規范更加嚴格。
30.靜態庫可以簡單地看作1組目標文件的集合。
動態鏈接
31.GCC手冊內嵌匯編知識
32.Ld連接器的語句分為連接語句和賦值語句。
33.BFD庫將編譯器和鏈接器與目標文件格式隔離開。
34.Runtimelib運行時動態庫。
35.程序的局部性原理,將運行的部份裝載。
36.覆蓋載入在初期內存不夠用的時候用的較多,現在已很少使用,但是在DSP中或許還有用武之地。關鍵詞:制止樹間調用和明確調用路勁。
37.為何叫映像文件,由于可履行文件在裝載的時候是被映照到虛擬地址空間的。
38.Linux缺頁異常機制。do_page_fault(),建立可履行文件頭文件和操作系統進程虛存之間的關系。當訪問該內存時候,發現為空,則產生缺頁異常。
39.對相同權限的段,把他們合并到1起當作1個段進行映照可以有效地減少系統內存的碎片。
40.從鏈接角度,依照section劃分,鏈接視角;從裝載角度,依照segment劃分,履行視角。
41.Linux裝載進程,./可履行文件以后,工作臺調用fork,然后fork調用execve,這時候候工作臺等待fork返回并接受用戶輸入的參數。:fork()->execve()->sys_execve()->do_execve()->search_binary_handler...。利用魔術肯定文件的格式和類型.
42.靜態鏈接的缺點:浪費內存和磁盤空間,由于每一個1個進程都有自己用到的庫的拷貝副本。第2是影響程序的跟新和發布,1個lib模塊的更新,全部程序都要更新發布。
43.動態鏈接的優勢:減少內存,減少物理頁的換入換出,增加CPU緩存的命中率,升級容易,下降耦合率,增加程序的可擴大性和兼容性。缺點在于需要完善的同享庫管理機制。linux下為.so,windows下為.dll
44.靜態庫為鏈接時重定位,動態庫為裝載時重定位。
45.地址無關代碼技術。。不怎樣看得懂。
46.如果1個lib.so中定義了1個全局變量a,進程A和進程B都使用了這個全局變量,1方的修改不會影響另外一方,由于他們有各自的數據段副本,是數據段副本。。。但是同1個進程的兩個線程,任何1邊的修改另外一個是會遭到影響的。
47.通過延遲綁定優化動態鏈接的速度。ELF通過PLT來實現,具體實現函數為_dl_runtime_reslove。
48.動態鏈接器其實也是1個同享庫,系統通過映照方式將其加載到進程的地址空間中,并將控制權交給他。動態鏈接庫進行1些列鏈接以后,將控制權交給可履行文件的入口地址。
49..interp段指定動態鏈接器的路徑。1般是1個軟鏈接。.dynamic段保存了動態鏈接器所需要的各種信息,比如哪些同享對象,動態鏈接符號表的位置,動態鏈接重定位表的位置,同享對象初始化代碼等。.symtab為靜態鏈接符號表,動態鏈接符號表為.dynsym,其中之保存于動態鏈接相干的符號。231頁
50.rel.dyn是動態庫對數據援用的修正(數據段),.rel.plt是對函數援用的修正(代碼段)。
51.elf.h包括了動態鏈接時候的輔助信息。
52.動態鏈接的步驟:啟動動態鏈接器本身,裝載所需要的同享對象,重定位和初始化。
53.動態鏈接器自舉后,首先找到自己的GOT段,第1個寄存的是.dynamic段,找到自己的重定位表和符號表等。
54.同享對象全局符號參與指的是在兩個模塊定義了同1個符號的時候,其中1個將另外1個覆蓋的現象,即他們之間存在優先級的順序。Linux的LD采取的是,如果行將加入的符號和已存在的符號同名的話,就疏忽行將加入的這個符號。
55.動態鏈接器本身是靜態鏈接的。也是PIC的(地址無關代碼)。
56.運行時加載,顯示模塊加載,linux驅動insmod和rmmod。
57.對動態庫的操作分為4個函數:打開(dlopen),查找符號(dlsym),毛病處理(dlerror),關閉動態庫(dlclose)
58.Libname.x.y.z.so,x主版本號,y次版本號,z發布版本號
59.SO-NAME機制,去掉次版本號和發布版本號,建立軟連接指向次版本號和發布版本號最新的庫。
60.程序的運行環境包括,內存、運行庫和系統調用。
61.棧1般分配在高地址內存區域,用來保存程序的上下文,它會向下生長。堆1般分配在低地址的內存區域,程序malloc和new出來的內存就在此分配,它是向上生長。
62.指針在初始化為NULL后,使用前1定要給他指向1個地址。棧上的指針也需要初始化好,不然隨機指針會出現毛病。
63.棧保存了:函數返回的地址和參數;臨時變量包括局部的非靜態的局部變量和編譯器生成的臨時變量;保存的上下文包括函數調用前后需要保存不變的寄存器。
64.Ebp寄存器成為幀指針,固定在函數活動的位置,調用函數的時候首先將參數壓入棧中,然后將下1條指令壓入棧中,跳轉到函數體履行。
65.函數的調用慣例:1.函數參數的傳遞方式溫柔序,例如從左到右還有益用寄存器傳遞參數提高性能。2.棧的保護方式,主要是彈出的時候由棧本身完成還是有函數體自己完成。3.名字修飾策略。默許的在C語言中使用的是_cdec1。(318頁)
31.eax用來傳遞函數的返回值。
32.堆空間由運行庫先向操作系統批發,再向各個程序零售,當零售光了的時候運行庫再向系統批發。運行庫有保護堆空間的算法。分別為mmap和brk。
33.在Linux2.6內核版本里,malloc可以分配的內存空間多達2.9G。
34.Malloc申請的內存,在進程結束以后就不存在了,由于進程結束以后,進程的資源包括內存,打開的文件,網絡接口等都會被操作系統回收。
35.堆的管理算法:簡單的方法有:空閑鏈表,位圖。針對固定分配大小的內存,可使用對象池。1般會采取多種方法的綜合。
36.Main函數之前會運行入口函數或叫入口點,操作系統在創建進程后,將系統的的控制權交給了程序的入口,入口函數都程序運行環境和運行庫進行初始化,包括堆、I/O、線程、全局變量等等。
37.入口函數初始化結束以后,調用Main函數,main函數履行結束返回到入口函數,然后回收資源,進行清算工作。
38.環境變量存儲的是1些系統的公然信心,例如路勁,版本等。
39._start傳給main的參數除argc和argv里面的參數意外,還包括init:main調用前的初始化工作;fini:main結束后的掃尾工作。Rtld_fini:和動態加載有關的掃尾工作。
40.其實main函數的退出也隱式的調用了exit函數,在exit后面還有個hlt是為了避免exit沒有調用,強迫的把進程給干掉。
41.程序的I/O包括文件、管道、信號、網絡、命令等。
42.I/O對文件的操作,初始化主要包括:建立打開文件表,如果能夠繼承自父進程,那末從父進程獲得繼承的句柄,初始化標準輸入輸出。
43.C語言的運行庫大致包括以下功能:1.啟動與退出。2.標準函數。3.I/O。4.堆的封裝和實現。5.語言實現。6.調試功能
C語言的標準庫由美國國家標準協會制定,最后1次擴充是1999年。。
66.(374)
67.線程私有數據包括:局部變量,函數的參數,線程局部存儲的數據。線程同享的數據包括:全局變量,堆上的數據,函數里面的靜態變量,程序代碼和打開的文件。
68.printf/fprintf在被多線程同享使用時,也會造成混亂。C庫當中1些函數做成可重入的。
69.可重入函數主要用于多任務環境中,1個可重入的函數簡單來講就是可以被中斷的函數,也就是說,可以在這個函數履行的任什么時候刻中斷它,轉入OS調度下去履行另外1段代碼,而返回控制時不會出現甚么毛病。
70.由于glibc在malloc和new中支持了多線程,所以在使用前后不用加鎖。但是1些例如memcopy,還是需要做保護。
71.緩沖機制的目的是為了不減少系統調用或讀盤的次數,減少切換開消,framebuffer,還有等等都是這樣。
72.linux下fread的實現:
73.linux下使用int 0x80來動身所有的系統調用。例如fork以后,會產生int 0x80的中斷,然后去查找中斷向量表,會發現是sys_call,這時候候fork的系統調用好會寄存在eax中,再去比對系統調用號的表,找到sys_fork,履行后返回到用戶態。
74.ESP是棧指針寄存器,指向系統棧最上面1個棧的棧頂。
75.EBP是基址指針寄存器,指向系統棧最上面1個棧的底部。
76.EAX1般用來保存函數的返回值,EB/C/DX等1般用來傳遞參數。