歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> Linux基本概念

Linux基本概念

日期:2017/3/1 13:38:48   编辑:關於Linux

在學習Linux的過程中,總有一些基本的概念困擾著我,比如,什麼是內核?控制台,Shell程序和內核的關系是怎麼樣的?這次主要通過度娘和Google把這些不太清楚的概念歸納了一下,具體如下:

1 Linux 體系結構 (圖太大,按列分割成2塊了)

\

\

2 Linux內核

\

2.1內核基本功能

· 內存管理

\

· 進程管理

進程調度,IPC

進程4要素

程序 PCB 地址空間 系統堆棧空間

PCB:進程創建時內核為其分配的一個核心數據結構,進程自身不能直接存取。

系統堆棧空間:進程運行在核心態時使用的堆棧,和PCB連在一起,共8KB,其中PCB約占1000字節,系統堆棧空間約占7200字節。

2.2 內核中linux進程個數有最大值限制(4092)。但2.4以後,系統中的進程個數受限於系統的物理內存數,即限定所有進程的PCB及系統堆棧(8K)占用的空間≤1/2的物理內存總和。例64M內存:進程數≤64M/2/8K=4K

· 硬件管理

設備驅動程序, ttyS (字符設備),sda (塊設備),網絡

· 文件系統管理

虛擬文件系統

2.2 啟動流程

1) 從BIOS到KERNEL

MBR->KERNEL->KERNEL自解壓->內核初始化->內核啟動(start_kernel函數,在linux內核源代碼樹的/usr/src/linux/init/main.c中)

2) 內核啟動:創建1#進程並執行,由它創建若干內核線程(kernelthread),然後裝入並執

行程序/sbin/init(變成一個用戶進程)。此後,init根據/etc/inittab配置文件來執行相應的腳本進行系統初始化,如設置鍵盤、字體,裝載模塊,設置網絡等

對於Redhat來說,執行的順序為:
/etc/rc.d/rc.sysinit # 由init執行的第一個腳本
/etc/rc.d/rc $RUNLEVEL # $RUNLEVEL為缺省的運行模式

/etc/rc.d/rc.local #運行模式2、3、5時會運行的腳本

/sbin/mingetty(或getty) # 等待用戶登錄

/etc/inittab中指定了系統的運行級別(RUNLEVEL),init根據運行級別啟動相關的服務(一些後台進程),實現不同的功能。

RUNLEVEL:0-6

0:halt, 1:單用戶,2:多用戶,3:多用戶並啟動NFS服務

4:保留,5:運行xdm(Xwindow)以圖形界面方式登錄

6:reboot

2.3 用戶登錄流程

\

2.4 Linux 內核空間和用戶空間

Linux簡化了分段機制,使得虛擬地址與線性地址總是一致,因此,Linux的虛擬地址空間也為0~4G。Linux內核將這4G字節的空間分為兩部分。將最高的1G字節(從虛擬地址0xC0000000到0xFFFFFFFF),供內核使用,稱為“內核空間”。而將較低的3G字節(從虛擬地址0x00000000到0xBFFFFFFF),供各個進程使用,稱為“用戶空間)。因為每個進程可以通過系統調用進入內核,因此,Linux內核由系統內的所有進程共享。於是,從具體進程的角度來看,每個進程可以擁有4G字節的虛擬空間。

Linux使用兩級保護機制:0級供內核使用,3級供用戶程序使用。從圖中可以看出(這裡無法表示圖),每個進程有各自的私有用戶空間(0~3G),這個空間對系統中的其他進程是不可見的。最高的1GB字節虛擬內核空間則為所有進程以及內核所共享。

內核空間中存放的是內核代碼和數據,而進程的用戶空間中存放的是用戶程序的代碼和數據。不管是內核空間還是用戶空間,它們都處於虛擬空間中。 雖然內核空間占據了每個虛擬空間中的最高1GB字節,但映射到物理內存卻總是從最低地址(0x00000000)開始。對內核空間來說,其地址映射是很簡單的線性映射,0xC0000000就是物理地址與線性地址之間的位移量,在Linux代碼中就叫做PAGE_OFFSET。

內核空間可以訪問所有的CPU指令和所有的內存空間、I/O空間。

用戶空間只能訪問有限的資源,若需要特殊權限,可以通過系統調用獲取相應的資源。

用戶空間允許頁面中斷,而內核空間則不允許。

內核空間和用戶空間是針對線性地址空間的。

所有內核進(線)程共用一個地址空間,而用戶進程都有各自的地址空間。

用戶空間和內核空間之間的數據移動:

access_ok

檢查用戶空間內存指針的有效性

get_user

從用戶空間獲取一個簡單變量

put_user

輸入一個簡單變量到用戶空間

clear_user

清除用戶空間中的一個塊,或者將其歸零。

copy_to_user

將一個數據塊從內核復制到用戶空間

copy_from_user

將一個數據塊從用戶空間復制到內核

strnlen_user

獲取內存空間中字符串緩沖區的大小

strncpy_from_user

從用戶空間復制一個字符串到內核

\

2.5 Linux內核態和用戶態

當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0級)內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。當進程在執行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象征性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。這與處於內核態的進程的狀態有些類似。

2.6 Linux內核線程,輕量級進程,用戶線程

內核線程

內核線程就是內核的分身,一個分身可以處理一件特定事情。這在處理異步事件如異步IO時特別有用。內核線程的使用是廉價的,唯一使用的資源就是內核棧和上下文切換時保存寄存器的空間。支持多線程的內核叫做多線程內核(Multi-Threadskernel )。

內核經常需要在後台執行一些操作。這種任務可以通過內核線程(kernel thread)完成。內核線程和普通的進程間的區別在於內核線程沒有獨立的地址空間,(實際它的mm指針被設置為NULL)內核線程只在內核空間運行,從來不切換到用戶空間去。內核進程和普通進程一樣,可以被調度,也可以被搶占內核線程也只能由其他內核線程創建。在現有內核線程中創建一個新的內核線程的方法如下:

Int kernel_thread(int(*fn)(void *),void *arg, unsigned long flags)

新的任務也是通過向普通的clone()系統調用傳遞特定的flags參數而創建的。在上面的函數返回時,返回一個指向子線程task_struct的指針。子線程開始運行fn指向的函數,arg是運行時需要用到的參數。一般情況下,內核線程會將它在創建時得到的函數永遠執行下去(除非系統重啟)。改函數通常由一個循環構成,在需要的時候,這個內核線程就會被喚醒和執行嗎,完成了當前任務,它會自行休眠。

從內核的角度來說,它並沒有線程這個概念。Linux把所有線程都當做進程來實現。內核並沒有准備特別的調度算法或者定義特別的數據結構來表示線程。相反,線程僅僅被視為一個與其他進程共享某些資源的進程。每個線程都擁有唯一屬於自己的task_struct,所以在內核中,它看起來就像是一個普通的進程(只是該進程和其他一些進程共享某些資源,如地址空間。

當Linux操作系統啟動以後,尤其是X window也啟動以後,可以用”ps -ef”命令查看系統中的進程,這時會發現很多以”d”結尾的進程名,確切說名稱顯示裡面加 "[]"的,這些進程就是內核線程。系統的啟動是從硬件->內核->用戶態進程的,pid的分配是一個往前的循環的過程,所以隨系統啟動的內核線程的pid往往很小。

PID TTY STAT TIMECOMMAND

2 1? S 0:01 init [3]

2 3? SN 0:00 [ksoftirqd/0]

2 5? SN 0:00 [ksoftirqd/1]

2 6? S< 0:00 [events/0]

2 7? S< 0:00 [events/1]

2 8? S< 0:00 [khelper]

2 9? S< 0:00 [kblockd/0]

2 10? S< 0:00 [kblockd/1]

2 11? S 0:00 [khubd]

2 35? S 0:42 [pdflush]

2 36? S 0:02 [pdflush]

2 38? S< 0:00 [aio/0]

2 39? S< 0:00 [aio/1]

2 37? S 0:19 [kswapd0]

2 112? S 0:00 [kseriod]

2 177? S 0:00 [scsi_eh_0]

2 178? S 0:00 [ahc_dv_0]

2 188? S 0:00 [scsi_eh_1]

2 189? S 0:00 [ahc_dv_1]

2 196? S 2:31 [kjournald]

2 1277? S 0:00 [kjournald]

2 1745? Ss 0:02 syslogd -m 0

2 1749? Ss 0:00 klogd -x

2 1958? Ss 0:13 /usr/sbin/sshd

2 2060? Ss 0:00 crond

2 2135tty2 Ss+ 0:00 /sbin/mingetty tty2

2 2136tty3 Ss+ 0:00 /sbin/mingetty tty3

2 2137tty4 Ss+ 0:00 /sbin/mingetty tty4

2 2138tty5 Ss+ 0:00 /sbin/mingetty tty5

2 2139tty6 Ss+ 0:00 /sbin/mingetty tty6

2 23564? S 0:00 bash

2 25605? Ss 0:00 sshd: peter [priv]

2 25607? S 0:00 sshd: peter@pts/2

輕量級進程(LWP)

輕量級線程(LWP)是一種由內核支持的用戶線程。它是基於內核線程的高級抽象,因此只有先支持內核線程,才能有LWP。每一個進程有一個或多個LWPs,每個LWP由一個內核線程支持。這種模型實際上就是恐龍書上所提到的一對一線程模型。在這種實現的操作系統中,LWP就是用戶線程。

由於每個LWP都與一個特定的內核線程關聯,因此每個LWP都是一個獨立的線程調度單元。即使有一個LWP在系統調用中阻塞,也不會影響整個進程的執行。

輕量級進程具有局限性。首先,大多數LWP的操作,如建立、析構以及同步,都需要進行系統調用。系統調用的代價相對較高:需要在usermode和kernel mode中切換。其次,每個LWP都需要有一個內核線程支持,因此LWP要消耗內核資源(內核線程的棧空間)。因此一個系統不能支持大量的LWP。

\

用戶線程

用戶線程指的是完全建立在用戶空間的線程庫,用戶線程的建立,同步,銷毀,調度完全在用戶空間完成,不需要內核的幫助。因此這種線程的操作是極其快速的且低消耗的。

上圖是最初的一個用戶線程模型,從中可以看出,進程中包含線程,用戶線程在用戶空間中實現,內核並沒有直接對用戶線程進程調度,內核的調度對象和傳統進程一樣,還是進程本身,內核並不知道用戶線程的存在。用戶線程之間的調度由在用戶空間實現的線程庫實現。

這種模型對應著恐龍書中提到的多對一線程模型,其缺點是一個用戶線程如果阻塞在系統調用中,則整個進程都將會阻塞。

\

加強版的用戶線程——用戶線程+LWP

\

3 GNU實用程序

3.1核心實用程序

GNU coreutils

3.2 Shell工作原理

Shell的基本功能是解釋並執行用戶打入的各種命令,實現用戶與Linux核心的接口。系統初啟後,核心為每個終端用戶建立一個進程去執行Shell解釋程序。它的執行過程基本上按如下步驟:

(1)讀取用戶由鍵盤輸入的命令行。

(2)分析命令,以命令名作為文件名,並將其它參數改造為系統調用execve( )內部處理所要求的形式。

(3)終端進程調用fork( )建立一個子進程。

(4)終端進程本身用系統調用wait4( )來等待子進程完成(如果是後台命令,則不等待)。當子進程運行時調用execve(),子進程根據文件名(即命令名)到目錄中查找有關文件(這是命令解釋程序構成的文件),將它調入內存,執行這個程序(解釋這條命令)。

(5)如果命令末尾有&號(後台命令符號),則終端進程不用系統調用wait4( )等待,立即發提示符,讓用戶輸入下一個命令,轉⑴。如果命令末尾沒有&號,則終端進程要一直等待,當子進程(即運行命令的進程)完成處理後終止,向父進程(終端進程)報告,此時終端進程醒來,在做必要的判別等工作後,終端進程發提示符,讓用戶輸入新的命令,重復上述處理過程。

4 終端,控制台

最初的計算機由於價格昂貴,因此,一台計算機一般是由多個人同時使用的。在這種情況下一台計算機需要連接上許多套鍵盤和顯示器來供多個人使用。在以前專門有這種可以連上一台電腦的設備,只有顯示器和鍵盤,還有簡單的處理電路,本身不具有處理計算機信息的能力,他是負責連接到一台正常的計算 機上(通常是通過串口),然後登陸計算機,並對該計算機進行操作。當然,那時候的計算機操作系統都是多任務多用戶的操作系統。這樣一台只有顯示器和鍵盤能夠通過串口連接到計算機 的設備就叫做終端。

而控制台又是什麼回事呢?在計算機裡,把那套直接連接在電腦上的鍵盤和顯示器就叫做控制台。請注意它和終端的區別,終端是通過串口連接上的,不是計算機本身就有的設備,而控制台是計算機本身就有的設備,一個計算機只有一個控制台。計算機啟動的時候,所有的信息都會顯示到控制台上,而不會顯示到終端上。也就是說,控制台是計算機的基本設備,而終端是附加設備。當然,由於控制台也有終端一樣的功能,控制台有時候也被模糊的統稱為終端。 計算機操作系統中,與終端不相關的信息,比如內核消息,後台服務消息,都可以顯示到控制台上,但不會顯示到終端上。

現在由於計算機硬件越來越便宜,通常都是一個人獨占一台計算機超做,不再連接以前那種真正意義上的“終端設備了”,因此,終端和控制台的概念也慢慢演化了。終端和控制台由硬件的概念,演化成了軟件的概念。現在說的終端,比如linux中的虛擬終端,都是軟件的概念,他用計算機的軟件來模擬以前硬件的方式。比如在linux中,你用 alt+f1 ~ f6 可以切換六個虛擬終端,就好比是以前多人公用的計算機中的六個終端設備,這就是為什麼這個叫“虛擬終端”的原因。當然,現在的linux也可以通過串口線,連接一個真正的終端。

簡單的說,能直接顯示系統消息的那個終端稱為控制台,其他的則稱為終端。

參考:

【Linux命令行和shell腳本編程寶典】

【Linux內核結構和進程管理.ppt】(找不到作者是誰,應該是浙大的一位老師)

http://blog.csdn.net/zhangskd/article/details/6956638

http://www.ibm.com/developerworks/cn/linux/l-kernel-memory-access/

http://blog.csdn.net/ylyuanlu/article/details/9115073

http://blog.csdn.net/sailor_8318/article/details/2613107

http://blog.csdn.net/yeyuangen/article/details/6858062

http://blog.csdn.net/caomiao2006/article/details/8791775

Copyright © Linux教程網 All Rights Reserved