linux學習總結

來源:互聯網
上載者:User

標籤:

                                                                               Linux學習總結

                                  

     結束了一學期的linux學習後我收穫非常的豐富,在這次學習中,我們嘗試了一種全新的學習方式,linux翻轉課堂,每周都上到mooc網站上跟著老師講解的視頻學習並進行實驗,一點一點的慢慢對linux這個作業系統有了瞭解,同時也掌握了一些基本的命令。每一個單元的內容我都有了自己的理解與收穫。在Linux核心這幾周的學習中,我受益匪淺,瞭解到了很多之前不曾瞭解的知識。

關於電腦是如何工作的:

電腦系統由硬體系統和軟體系統兩大部分組成。馮·諾依曼(John von Neumann)奠定了現代電腦的基本結構,這一結構又稱馮·諾依曼結構,其特點是:

1)使用單一的處理組件來完成計算、儲存以及通訊的工作。

2)儲存單元是定長的線性組織。

3)儲存空間的單元是直接定址的。

4)使用低級機器語言,指令通過作業碼來完成簡單的操作。

5)對計算進行集中的順序控制。

6)電腦硬體系統由運算器、儲存空間、控制器、輸入裝置、輸出裝置五大組件組成並規定了它們的準系統。

7)採用二進位形式表示資料和指令。

   我認為電腦在運行時,先從記憶體中取出第一條指令,然後按照指令的要求按,從儲存空間中取出資料進行指定的運算和邏輯操作等加工,然後再按地址把結果送到記憶體中去。接下來,再取出第二條指令,在控制器指揮下完成規定操作,就相當於C語言當中的for迴圈,依此進行下去。直至遇到停止指令。

關於作業系統是如何工作的:

  當一個進程在執行一個程式的時候,進來一個中斷,CPU首先將當前EIP,ESP壓入核心 棧,然後把ESP指向核心棧,EIP指向中斷處理的入口,其中最關鍵的就是TSS,因為TSS中儲存了使用者態下各個寄存器的資訊,所以將使用者態下的EIP 和ESP入棧,就相當於對進程之前的一個狀態進行儲存,以便於從中斷返回後繼續執行之前任務,然後kernel調用SAVE_ALL來將其他寄存器資訊保 存在棧中,接著根據CS EIP指向的中斷程式,對中斷進行處理。當執行完一個中斷後,會通過schedule進行調度,其中最重要的要數switch to,其會調用 switch to函數來進行調度。當中斷執行完後,若要返回到使用者態,就需要回到最初中斷開始的地方繼續執行先前任務,這就需要 restore all將之前儲存在核心棧中的值出棧,然後通過iret恢複其計算機的狀態,這樣我們就又回到了使用者態,繼續執行之前因中斷而暫停任務。

  我認為作業系統工作的核心是進程,而許多作業系統都有自己的核心進程,進程是程式的動態執行。系統最重要的操作就是完成核心進程,而其他的程式都是其核心進程的衍生物,其可以控制繁衍的處理序的進程啟動及切換甚至可以終止進程,當核心系統結束,將影響整個作業系統的運行。

關於Linux系統的啟動過程

首先找到main.c中start kernel,不管分析核心的哪一個部分都要調用start kernel.

Trap init中arch/x86,設定了很多中斷,而系統調用也是一種中斷。Init process是Linux系統中的一號進程,當系統中沒有進程需要執行的時候就會調度到idle進程,start kernel從核心一開始啟動就會一直存在,這便是0號進程,隨後0號進程建立了1號進程即init,於是系統便啟動起來了。這是核心的啟動過程。init_task是進程0使用的進程描述符,也是Linux系統中第一個進程描述符,該進程的描述符在arch/powerpc/kernel/init_task.c中定義,程式碼片段如下:struct  task_struct  init_task = INIT_TASK(init_task);init_task描述符使用宏INIT_TASK對init_task的進程描述符進行初始化,宏INIT_TASK在include/linux/init_task.h檔案中,init_task是Linux核心中的第一個線程,它貫穿於整個Linux系統的初始化過程中,該進程也是Linux系統中唯一一個沒有用kernel_thread() 函數建立的進程,在init_task進程執行後期,它會調用kernel_thread()函數建立第一個核心進程kernel_init,同時init_task進程繼續對Linux系統初始化。在完成初始化後,init_task會退化為cpu_idle進程,當Core 0的就緒隊列中沒有其它進程時,該進程將會獲得CPU運行。新建立的1號進程kernel_init將會逐個啟動次CPU,並最終建立使用者進程。

關於系統調用的方法:

 使用者程式------>C庫(即API):INT 0x80 ----->system_call------->系統調用服務常式-------->核心程式

 先說明一下,我們常說的使用者API其實就是系統提供的C庫。

 系統調用是通過非強制中斷指令 INT 0x80 實現的,而這條INT 0x80指令就被封裝在C庫的函數中。

(非強制中斷和我們常說的硬中斷不同之處在於,非強制中斷是由指令觸發的,而不是由硬體外設引起的。)

INT 0x80 這條指令的執行會讓系統跳轉到一個預設的核心空間地址,它指向系統調用處理常式,即system_call函數。

(注意:!!!系統調用處理常式system_call 並不是系統調用服務常式,系統調用服務常式是對一個具體的系統調用的核心實現函數,而系統調用處理常式是在執行系統調用服務常式之前的一個引導過程,是針對INT 0x80這條指令,面向所有的系統調用的。簡單來講,執行任何系統調用,都是先通過調用C庫中的函數,這個函數裡面就會有非強制中斷 INT 0x80 語句,然後轉到執行系統調用處理常式 system_call ,

system_call 再根據具體的系統調用號轉到執行具體的系統調用服務常式。)

system_call函數通過系統調用號尋找系統調用表sys_call_table!非強制中斷指令INT 0x80執行時,系統調用號會被放入 eax 寄存器中,system_call函數可以讀取eax寄存器擷取,然後將其乘以4,產生位移地址,然後以sys_call_table為基址,基址加上位移地址,就可以得到具體的系統調用服務常式的地址了!

然後就到了系統調用服務常式了。需要說明的是,系統調用服務常式只會從堆棧裡擷取參數,所以在system_call執行前,會先將參數存放在寄存器中,system_call執行時會首先將這些寄存器壓入堆棧。system_call退出後,使用者可以從寄存器中獲得(被修改過的)參數。

  另外:系統調用通過非強制中斷INT 0x80陷入核心,跳轉到系統調用處理常式system_call函數,然後執行相應的服務常式。但是由於是代表使用者進程,所以這個執行過程並不屬於中斷上下文,而是進程上下文。因此,系統調用執行過程中,可以訪問使用者進程的許多資訊,可以被其他進程搶佔,可以休眠。

  當系統調用完成後,把控制權交回到發起調用的使用者進程前,核心會有一次調度。如果發現有優先順序更高的進程或當前進程的時間片用完,那麼會選擇優先順序更高的進程或重新選擇進程執行。

關於system-call中斷處理過程:

 系統調用是通過非強制中斷指令 INT 0x80 實現的,而這條INT 0x80指令就被封裝在C庫的函數中。INT 0x80 這條指令的執行會讓系統跳轉到一個預設的核心空間地址,它指向系統調用處理常式,即system_call函數。系統調用處理常式system_call 並不是系統調用服務常式,系統調用服務常式是對一個具體的系統調用的核心實現函數,而系統調用處理常式是在執行系統調用服務常式之前的一個引導過程,是針對INT 0x80這條指令,面向所有的系統調用的。簡單來講,執行任何系統調用,都是先通過調用C庫中的函數,這個函數裡面就會有非強制中斷 INT 0x80 語句,然後轉到執行系統調用處理常式 system_call ,system_call 再根據具體的系統調用號轉到執行具體的系統調用服務常式。

  system_call函數通過系統調用號尋找系統調用表sys_call_table!非強制中斷指令INT 0x80執行時,系統調用號會被放入 eax 寄存器中,system_call函數可以讀取eax寄存器擷取,然後將其乘以4,產生位移地址,然後以sys_call_table為基址,基址加上位移地址,就可以得到具體的系統調用服務常式的地址了!

  然後就到了系統調用服務常式了。需要說明的是,系統調用服務常式只會堆棧裡擷取參數,所以在system_call執行前,會先將參數存放在寄存器中,system_call執行時會首先將這些寄存器壓入堆棧。system_call退出後,使用者可以從寄存器中獲得(被修改過的)參數。

  另外:系統調用通過非強制中斷INT 0x80陷入核心,跳轉到系統調用處理常式system_call函數,然後執行相應的服務常式。但是由於是代表使用者進程,所以這個執行過程並不屬於中斷上下文,而是進程上下文。因此,系統調用執行過程中,可以訪問使用者進程的許多資訊,可以被其他進程搶佔,可以休眠。

  當系統調用完成後,把控制權交回到發起調用的使用者進程前,核心會有一次調度。如果發現有優先順序更高的進程或當前進程的時間片用完,那麼會選擇優先順序更高的進程或重新選擇進程執行

關於Linux核心建立一個新進程的過程

    在Linux中建立一個新進程的唯一方法是使用fork函數,fork()執行一次但有兩個傳回值。

在父進程中,傳回值是子進程的進程號;在子進程中,傳回值為0。因此可通過傳回值來判斷當前進程是父進程還是子進程。

    在fork的最後是將任務設定成了就緒狀態,由於fork()是一個系統調用,在系統調用部分system_call.s,可以看到在系統函數返回後,會調用調度函數schedule(),在schedule()中,就會檢測到新進程的就緒狀態,並用switch_to()切換到新進程進行執行。

    使用fork函數得到的子進程是父進程的一個複製品,它從父進程處複製了整個進程的地址空間,包括進程上下文,進程堆棧,記憶體資訊,開啟的檔案描述符,訊號控制設定,進程優先順序,進程組號,當前工作目錄,根目錄,資源限制,控制終端等。而子進程所專屬的只是它的進程號,資源使用和計時器等。可以看出,使用fork函數的代價是很大的,它複製了父進程中的程式碼片段,資料區段和堆棧段裡的大部分內容,使得fork函數的執行速度並不快。由 fork() 系統調用建立的新進程被稱為子進程。該函數被調用一次,但返回兩次。如果 fork()進程調用成功,兩次返回的區別是子進程的傳回值是0,而父進程的傳回值則是新子進程的進程號

關於Linux如何裝載和啟動一個可執行程式

  在linux首先建立父進程,然後通過調用fork()系統調用建立一個新的進程,然後新的進程調用execve()系統調用執行指定的ELF檔案。主進程繼續返回等待新進程執行結束,然後重新等待使用者輸入命令。execve()系統調用被定義在unistd.h,它的原型如下:

  int execve(const char *filenarne, char *const argv[], char *const envp[]);

  它的三個參數分別是被執行的程式檔案名稱、執行參數和環境變最。Glibc對execvp()系統調用進行了封裝,提供了execl(), execlp(), execle(), execv()和execvp()等5個不同形式的exec系列API,它們只是在調用的參數形式上有所區別,但最終都會調用到execve()這個系統中。

  調用execve()系統調用之後,再調用核心的入口sys_execve()。 sys_execve()進行一些參數的檢查複製之後,調用do_execve()。因為可執行檔不止ELF一種,還有java程式和以“#!”開始的指令碼程式等,所以do_execve()會首先檢查被執行檔案,讀取前128個位元組,特別是開頭4個位元組的魔數,用以判斷可執行檔的格式。如果是解釋型語言的指令碼,前兩個位元組“#!"就構成了魔數,系統一旦判斷到這兩個位元組,就對後面的字串進行解析,以確定程式解譯器的路徑。環境下,可執行檔是以ELF格式存在的,檔案頭部標明了檔案在載入到記憶體中需要的相關資訊,隨後的部分是以段的形式存在的代碼和資料,段的劃分主要依據載入到記憶體中的讀寫屬性。系統調用execve負責可執行檔的調度工作,先進行相關參數的傳遞和調用前環境的處理,然後載入可執行檔的資訊,尋找相應的可執行檔解析模組,對於ELF格式的可執行檔,按照格式要求載入到記憶體中相應的地址空間,如果是靜態連結的就將檔案頭部標明的入口地址作為開始;如果是依賴動態連結程式庫的可執行檔則需要將動態連結器ld的入口地址作為開始。execve是一個特殊的系統調用,在子進程總fork返回到一個特定的點,當前程式執行到execve時陷入到核心態,當execve返回時返回的是一個新的可執行程式的執行起點,shell環境執行execve,當系統調用陷入核心中時,調用evecve,do execve,根據可執行檔載入頭部,在鏈表當中尋找能夠解析的核心模組

     我覺得在學習linux的過程中,明白了一個道理,那就是linux的使用者權限很大,做任何事情都很自由,所以你必須知道自己做的每一步在幹什麼,因為駭客會利用linux的漏洞來擷取資訊。比如緩衝區溢位就這個實驗,緩衝區溢位是指當電腦向緩衝區內填充資料位元數時超過了緩衝區本身的容量溢出的資料覆蓋在合法資料上,理想的情況是程式檢查資料長度並不允許輸入超過緩衝區長度的字元,但是絕大多數程式都會假設資料長度總是與所分配的儲存空間想匹配,這就為緩衝區溢位埋下隱患。作業系統所使用的緩衝區 又被稱為"堆棧".,在各個操作進程之間,指令會被臨時儲存在"堆棧"當中,"堆棧"也會出現緩衝區溢位 。緩衝區溢位通過往程式的緩衝區寫超出其長度的內容,造成緩衝區的溢出,從而破壞程式的堆棧,使程式轉而執行其它指令,以達到攻擊的目的。緩衝區溢位是指程式試圖向緩衝區寫入超出預分配固定長度資料的情況。這一漏洞可以被惡意使用者利用來改變程式的流量控制,甚至執行代碼的任意片段。這一漏洞的出現是由於資料緩衝器和返回地址的暫時關閉,溢出會引起返回地址被重寫。

     Linux這個作業系統是一個非常聰明的系統,但同時它又存在很多系統漏洞,比如Set-UID ,它是一個重要的安全機制。當一個Set-UID程式啟動並執行時候,它被假設為具有擁有者的許可權,任何人運行這個程式時都會獲得程式擁有者的許可權,同時就給駭客們創造了入侵盜取資訊的條件。這就需要我們在以後的學習當中不斷學習不斷突破,而我對於linux的瞭解遠遠不足,對細節方面瞭解還不夠透徹,希望在以後的學習生活中,對linux核心有更深入的瞭解,同時要多涉獵資訊安全的相關知識,感覺只有學習了資訊安全,才能升入的把握程式內在的各種機制。從攻擊的角度能更加細緻的看待編程。因為只有懂得了程式正常工作的邏輯,才能從供給的角度對其進行破壞。因此更多的夯實基礎,才是真正掌握資訊安全的正確途徑。不可能一簇而就,沒有好的基礎就能學習好資訊安全的知識。總之這學期的linux核心這門課程的學習給了我全新的體驗與收穫,感謝老師!

linux學習總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.