說明:在多核處理器下,會存在多個進程處於內核態的情況,在內核態下,進程是可以訪問所有的內核數據,因此需要對共享數據做保護,即互斥處理。
原子性:一個操作是不可中斷的,即使在多個線程一起執行的時候,一個操作一旦開始,就不會被其它線程所幹擾。
Linux的內核鎖主要是自旋鎖和信號量。
自旋鎖最多只能被一個可執行線程持有,如果一個執行線程試圖請求一個已被徵用(已經被持有)的自旋鎖,那麼這個線程就會一直進行慢循環——旋轉——等待鎖重新可用。要是鎖未被徵用,請求它的執行線程便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於一個的執行線程同時進入臨界區。
Linux中的信號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以獲得這個信號量。
信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的情況;只能在進程上下文中使用,因為中斷上下文中是不能被調度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
內核態:進程陷入內核代碼中執行,在內核態將會使用內核棧,每個進程都有自己的內核棧。
用戶態:進程在執行自身的應用代碼。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象徵性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。這與處於內核態的進程的狀態有些類似。
當用戶程序調用系統的API時,會產生中斷,進入內核態的API,處理完成後,用中斷再退出,返回用戶態的調用函數:
user api --> interrupt --> kernel api --> interrupt
雖然用戶態下和內核態下工作的程序有很多差別,但最重要的差別就在於特權級的不同,即權力的不同。
用戶態切到內核態的三種方式:
——>:系統調用:而系統調用的機制其核心還是使用了作業系統為用戶特別開放的一個中斷來實現。
——>:異常:當出現事先不可知的異常,會切到異常內核程序,比如缺頁異常。
——>:外圍設備的中斷:由用戶態切到內核態去執行中斷程序。
內核模式的代碼可以無限制地訪問所有處理器指令集以及全部內存和I/O空間。如果用戶模式的進程要享有此特權,它必須通過系統調用向設備驅動程序或其他內核模式的代碼發出請求。另外,用戶模式的代碼允許發生缺頁,而內核模式的代碼則不允許。
在linux內核環境下,申請大塊內存的成功率隨著系統運行時間的增加而減少,雖然可以通過vmalloc系列調用申請物理不連續但虛擬地址連續的內存,但畢竟其使用效率不高且在32位系統上vmalloc的內存地址空間有限。所以,一般的建議是在系統啟動階段申請大塊內存,但是其成功的概率也只是比較高而已,而不是100%。如果程序真的比較在意這個申請的成功與否,只能退用「啟動內存」(Boot Memory)
(1)管道(Pipe):管道可用於具有親緣關係進程間的通信,允許一個進程和另一個與它有共同祖先的進程之間進行通信。
(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關係進程間的通信。命名管道在文件系統中有對應的文件名。命名管道通過命令mkfifo或系統調用mkfifo來創建。
(3)信號(Signal):信號是比較複雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還可以發送信號給進程本身;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD為了實現可靠信號機制,又能夠統一對外接口,用sigaction函數重新實現了signal函數)。
(4)消息(Message)隊列:消息隊列是消息的連結表,包括Posix消息隊列system V消息隊列。有足夠權限的進程可以向隊列中添加消息,被賦予讀權限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩衝區大小受限等缺
(5)共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
(6)信號量(semaphore):主要作為進程間以及同一進程不同線程之間的同步手段。
(7)套接字(Socket):更為一般的進程間通信機制,可用於不同機器之間的進程間通信。起初是由Unix系統的BSD分支開發出來的,但現在一般可以移植到其它類Unix系統上:Linux和System V的變種都支持套接字。
在物理頁面管理上實現了基於區的夥伴系統(zone based buddy system)。對不同區的內存使用單獨的夥伴系統(buddy system)管理,而且獨立地監控空閒頁。相應接口alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。
kmalloc 和 kfree。
引申:
slab:linux下的內存分配機制,針對一些經常分配並釋放的對象,如進程描述符,對象大小一般比較小。
優點:
1、內核通常依賴於對小對象的分配,它們會在系統生命周期內進行無數次分配。
2、slab 緩存分配器通過對類似大小的對象進行緩存而提供這種功能,從而避免了常見的碎片問題。
3、slab 分配器還支持通用對象的初始化,從而避免了為同一目的而對一個對象重複進行初始化。
4、slab 分配器還可以支持硬體緩存對齊和著色,這允許不同緩存中的對象佔用相同的緩存行,從而提高緩存的利用率並獲得更好的性能。
夥伴系統:(buddy system)需要談一談linux的內存分配系統
linux內核採取了一種同時適用於32位和64位系統的內存分頁模型,對於32位系統,兩級頁表足夠用,而64位系統,需要四級頁表。分別為:
頁全局目錄:包含一些頁上級目錄地址
頁上級目錄:包含頁中間目錄地址
頁中間目錄:包含一些頁表地址
頁表: 指向頁框,linux中採用4kb大小的頁框作為標準的內存分配單元。
在實際應用中,經常需要分配一組連續的頁框,而頻繁地申請和釋放不同大小的連續頁框,必然導致在已分配頁框的內存塊中分散了許多小塊的空閒頁框。這樣,即使這些頁框是空閒的,其他需要分配連續頁框的應用也很難得到滿足。
為了避免出現這種情況,Linux內核中引入了夥伴系統算法(buddy system)。把所有的空閒頁框分組為11個塊鍊表,每個塊鍊表分別包含大小為1,2,4,8,16,32,64,128,256,512和1024個連續頁框的頁框塊。最大可以申請1024個連續頁框,對應4MB大小的連續內存。每個頁框塊的第一個頁框的物理地址是該塊大小的整數倍。
假設要申請一個256個頁框的塊,先從256個頁框的鍊表中查找空閒塊,如果沒有,就去512個頁框的鍊表中找,找到了則將頁框塊分為2個256個頁框的塊,一個分配給應用,另外一個移到256個頁框的鍊表中。如果512個頁框的鍊表中仍沒有空閒塊,繼續向1024個頁框的鍊表查找,如果仍然沒有,則返回錯誤。
頁框塊在釋放時,會主動將兩個連續的頁框塊合併為一個較大的頁框塊。
Linux將4G的地址劃分為用戶空間和內核空間兩部分。在Linux內核的低版本中(2.0.X),通常0-3G為用戶空間,3G-4G為內核空間。這個分界點是可以改動的。 正是這個分界點的存在,限制了Linux可用的最大內存為2G.而且要通過重編內核,調整這個分界點才能達到。實際上還可以有更好的方法來解決這個問題。由於內核空間與用戶空間互不重合,所以可以用段機制提供的保護功能來保護內核級代碼。2.2.X版的內核對此進行了改動。這樣內核空間擴張到了4G。從表面上看內核的基地址變為了0,但實際上,內核通常仍在虛址3G以上。 用戶空間在2.2.X中從直觀上變為0-4G,讓人迷惑,不是可以直接訪問內核了? 其實不然,通過使用頁機制提供的保護,阻止了用戶程序訪問內核空間。
原型為:void *vmalloc(unsigned long size)。size要分配內存的大小. 以字節為單位。在設備驅動程序或者內核模塊中動態開闢內存,不是用malloc,而是kmalloc ,vmalloc,或者用get_free_pages直接申請頁。釋放內存用的是kfree,vfree,或free_pages.
kmalloc函數返回的是虛擬地址(線性地址). kmalloc特殊之處在於它分配的內存是物理上連續的,這對於要進行DMA的設備十分重要. 而用vmalloc分配的內存只是線性地址連續,物理地址不一定連續,不能直接用於DMA。vmalloc函數的工作方式類似於kmalloc,只不過前者分配的內存虛擬地址是連續的,而物理地址則無需連續。它通過分配非連續的物理內存塊,再修改頁表,把內存映射到邏輯地址空間的連續區域中。通過vmalloc獲得的頁必須一個一個地進行映射,效率不高,因此,只在不得已(一般是為了獲得大塊內存)時使用。vmalloc函數返回一個指針,指向邏輯上連續的一塊內存區,其大小至少為size。在發生錯誤時,函數返回NULL。vmalloc可能睡眠,因此,不能從中斷上下文中進行調用,也不能從其它不允許阻塞的情況下調用。要釋放通過vmalloc所獲得的內存,應使用vfree函數。
Kmalloc 是連續的物理內存。
Vmalloc 是非連續的。
vmalloc是一頁一頁地去獲取內存,然後把獲取到的這些頁映射成連續的虛擬地址;
kmalloc是一次性獲取所需要的所有頁,並且不需要再做映射;
vmalloc 是否效率遠不如 kmalloc
0~0xBFFFFFFF
簡單的說就是:內存是分散成一些小塊的,malloc管理的內存是通過鍊表的方式把這些塊串在一起,以這些內存的起始地址排序組織的,相鄰的內存塊如果尾首地址連續,那就把它們合併為一塊,當你申請一定大小的內存時以first fit模式,在內存鏈中找第一個大於你需要大小的內存,返回內存指針以best fit模式,要遍歷整個內存鏈,找剛好最接近但大於所需要大小的內存當然這是出於對內存不浪費的考慮,效率是有損失.釋放的話相反,把內存放回內存管理鏈中,可能的話合併相鄰的內存碎片。避免內存過於零散Linux下malloc函數主要用來在用戶空間從heap申請內存,申請成功返回指向所分配內存的指針,申請失敗返回NULL。默認情況下,Linux內核使用「樂觀的」分配內存策略,首先粗略估計系統可使用的內存數,然後分配內存,但是在使用的時候才真正把這塊分配的內存給你。這樣一來,即使用malloc申請內存沒有返回NULL,你也不一定能完全使用這塊內存,特別是在一次或連續多次申請很多內存的時候。如果一直連續用malloc申請內存,而不真正使用,所申請的內存總數可以超過真正可以使用的內存數。但是當真正使用這塊內存,比如用memset或bzero函數一次性把所申請到的大塊內存「使用掉」,Linux系統就會Out Of Memory,這個時候OOM Killer就會kill掉用戶空間的其他進程來騰出更多可使用內存。OOM Killer根據OOM score來決定kill哪個進程,OOM score可以看/proc/<PID>/oom_score,score由badness函數計算得出,根據進程運行時間長短,進程優先級,進程所使用的內存數等等。可以通過/proc/<PID>/oom_adj來幹預計算socre,這個值的取值範圍是-17~15,如果是-17該進程就永遠不會被kill(這個可能也和內核版本有關,不見得所有內核版本都支持,得實際試試)。「默認情況」Linux是這種做的,「默認情況」是指/proc/sys/vm/overcommit_memory為0的時候。這個參數也可以調整,如果為1表示「來者不拒」,只要你malloc過來申請,我啥都不做,立馬給你分配內存,這樣的話性能就會有大幅度的提高;如果為2表示Linux會精確計算所有可使用的內存和所申請的內存,如果所申請的超過的可使用的內存數就返回NULL。可使用的內存值計算方法,虛擬內存(swap)+ /proc/sys/vm/overcommit_memory(百分比) × 物理內存。/proc/sys/vm/overcommit_memory默認值為50,計算起來就是50%的物理內存數。Linux自身內核會佔一部分內存,還有buffer/cache所佔用的內存,所以實際上能被malloc申請後使用的內存並非物理內存大小,demsg的輸出裡面包含了相關信息(如果看不到,可能是被別的信息衝掉了,重啟系統,在系統起來後馬上看):
Memory: 2071220k/2097152k available (2122k kernel code, 24584k reserved, 884k data, 228k init, 1179584k highmem)
虛擬地址模式
在ARM存儲系統中,使用內存管理單元(MMU)實現虛擬地址到實際物理地址的映射。利用MMU,可把SDRAM的地址完全映射到0x0起始的一片連續地址空間,而把原來佔據這片空間的FLASH或者ROM映射到其他不相衝突的存儲空間位置。例如,FLASH的地址從0x0000 0000~0x00ff ffff,而SDRAM的地址範圍是0x3000 0000~Ox3lff ffff,則可把SDRAM地址映射為0x0000 0000~Oxlfff ffff而FLASH的地址可以映射到Ox9000 0000~Ox90ff ffff(此處地址空間為空閒,未被佔用)。映射完成後,如果處理器發生異常,假設依然為IRQ中斷,PC指針指向Oxl8處的地址,而這個時候PC實際上是從位於物理地址的Ox3000 0018處讀取指令。通過MMU的映射,則可實現程序完全運行在SDRAM之中。在實際的應用中.可能會把兩片不連續的物理地址空間分配給SDRAM。而在作業系統中,習慣於把SDRAM的空間連續起來,方便內存管理,且應用程式申請大塊的內存時,作業系統內核也可方便地分配。通過MMU可實現不連續的物理地址空間映射為連續的虛擬地址空間。作業系統內核或者一些比較關鍵的代碼,一般是不希望被用戶應用程式訪問。通過MMU可以控制地址空間的訪問權限,從而保護這些代碼不被破壞。
MMU的實現過程,實際上就是一個查表映射的過程。建立頁表(translate table)是實現MMU功能不可缺少的一步。頁表是位於系統的內存中,頁表的每一項對應於一個虛擬地址到物理地址的映射。每一項的長度即是一個字的長度(在ARM中,一個字的長度被定義為4B)。頁表項除完成虛擬地址到物理地址的映射功能之外,還定義了訪問權限和緩衝特性等。
MMU的映射分為兩種,一級頁表的變換和二級頁表變換。兩者的不同之處就是實現的變換地址空間大小不同。一級頁表變換支持1 M大小的存儲空間的映射,而二級可以支持64 kB,4 kB和1 kB大小地址空間的映射
虛擬存儲空間到物理存儲空間的映射是以內存塊為單位進行的,虛擬存儲空間中的一塊連續存儲空間被映射成物理存儲空間中同樣大小的一塊連續存儲空間。每一個地址變換條目(頁表項)記錄了一個虛擬存儲空間的存儲塊的基地址與物理存儲空間相應的一個存儲塊的基地址的對應關係。根據存儲塊大小不同,可以有多種地址變換。
ARM處理器支持的存儲塊大小有以下幾種:
1)段(section):大小為1MB的存儲塊。
2)大頁(Large Page):大小為64KB的存儲塊。
3)小頁(Small Page):大小為4KB的存儲塊。
4)極小頁(Tiny Page):大小為1KB的存儲塊。
通過採用適當的訪問控制機制,還可以將大頁分成大小為16KB的子頁,也可將小頁分成大小為1KB的子頁,但極小頁不能再細分,只能以1KB大小的整頁為單位。
ARM處理器採用兩級頁表實現地址映射:
1)一級頁表中包含以段為單位的地址變換條目或者指向二級頁表的指針,一級頁表實現的地址映射力度較大。
2)二級頁表中包含以大頁、小頁和極小頁為單位的地址變換條目。
當以二級分頁管理某段存儲空間時,要同時設置一級頁表項和二級頁表項,一個一級頁表項對應一段(1section=1MB)虛擬存儲空間的映射關係,一個一級頁表項對應一張二級頁表,這張二級頁表中的所有頁表項合在一起對應了前面一級頁表項所對應的一段虛擬存儲空間的映射關係。ARM處理器的二級頁表分為粗粒度二級頁表和細粒度二級頁表,一張粗粒度二級頁表的最大容量為1KB,一張細粒度二級頁表的最大容量為4KB,不管是粗粒度還是細粒度頁表,每張頁表都對應一段(1M)虛擬存儲空間的映射關係。所以粗粒度二級頁表的頁表項(頁描述符)最小只能描述4KB大小(小頁)虛擬存儲空間的映射關係,如果再小就沒有足夠的頁表空間來存放一段虛擬存儲空間的全部頁表項(因為粗粒度二級頁表的最大容量為1KB),因為粗粒度二級頁表容量最大容量為1K,一個頁表項為4個字節,所以1K容量最多有1024/4=256個頁表項,所以最小只能描述1M/256=4K大小(小頁)虛擬空間的存儲映射關係,而細粒度二級頁表的頁描述符最小可以描述1KB大小(極小頁)的虛擬存儲空間的映射關係。
綜上所述,我們可以歸納出以下6種ARM處理器的地址變換方法:
1)分段地址變換,這種變換隻需要一級地址變換,而下面5種都需要兩級地址變換;
2)粗粒度大頁(64K)地址變換;
3)粗粒度小頁(4K)地址變換(Linux通常使用的地址變換方法);
4)細粒度大頁(64K)地址變換;
5)細粒度小頁(4K)地址變換;
6)細粒度極小頁(1K)地址變換。
在講解以上各種地址變換方法之前我們先介紹一下一級映射描述符和二級映射描述符的定義。
VFS
VFS超級塊:struct super_block
VFS的i節點:struct inode
i節點的操作函數:struct inode_operations
VFS的dentry結構:struct dentry
file_operations
file_operations結構體,用來存儲驅動內核模塊提供的對設備進行各種操作的函數的指針。
常用的操作包括:read、write、poll、ioctl、mmap、open、close、flush、llseek等方法。
file 每個打開的文件在內核空間都有一個對應的file結構
file結構體,打開的文件描述
通用的描述有,f_mode(讀寫屬性)、f_ops(當前文件位移)、f_rdev(設備)、f_flags(文件標誌)、f_count(打開文件的數目)、f_reada、f_inode(指向inode的結構指針)、file_operations
inode
inode 索引節點,和存儲有關。
inode內容:
除了文件名以外的所有文件信息,都存在inode之中。
* 文件的字節數
* 文件擁有者的User ID
* 文件的Group ID
* 文件的讀、寫、執行權限
* 文件的時間戳,共有三個:ctime指inode上一次變動的時間,mtime指文件內容上一次變動的時間,atime指文件上一次打開的時間。
* 連結數,即有多少文件名指向這個inode
* 文件數據block的位置
可以用stat命令,查看某個文件的inode信息:stat xxx.txt
struct file 結構體中包含有struct file_operations結構體,struct file_operations是struct file的一個域;我們在使用系統調用open()打開一個設備節點struct inode時,我們會得到一個文件struct file,同時返回一個文件描述符,該文件描述符是一個整數,我們稱之為句柄,通過訪問句柄我們能夠訪問設備文件struct file,描述符是一個有著特殊含義的整數,特定位都有一定的意義或屬性。
文件描述符就是句柄,是一個整數,通過句柄來訪問設備文件 file。文件file裡有相關的文件屬性,並且包含相關的文件操作。
普通文件 : 通常是流式文件
目錄文件 : 用於表示和管理系統中的全部文件
連接文件 : 用於不同目錄下文件的共享
設備文件 : 包括塊設備文件和字符設備文件,塊設備文件表示磁碟文件、光碟等,字符設備文件按照字符操作終端、鍵盤等設備。
管道(FIFO)文件 : 提供進程建通信的一種方式
套接字(socket) 文件: 該文件類型與網絡通信有關
fork();創建子進程,其實是複製了父進程,但是父進程的程序代碼和全局變量沒有被複製。
父進程調用fork會返回子進程的ID號,調用失敗返回-1,子進程調用返回0。
execve();子進程調用execve(),是為了運行另一個屬於自己的程序。
exit();進程調用exit()就會立即退出,系統的跟進程會接替被中止進程的地位。
wait();進程調用,阻塞自己,等到自己的某個子進程退出再繼續運行。
vfork();也是創建一個子進程,但它並不把父進程的映像全部複製到子進程中,而是只是用複製指針的方法使子進程與父進程的資源共享。它與父進程共享一個內存空間。
進程的切換與系統的一般執行過程 - 20135222 - 博客園
直接調用 延遲調用
切換用戶空間
切換內存堆棧
引申:
進程的調度時機:
中斷處理過程(包括時鐘中斷、I/O中斷、系統調用和異常)中,直接調用schedule(),或者返回用戶態時根據need_resched標記調用schedule();
內核線程可以直接調用schedule()進行進程切換,也可以在中斷處理過程中進行調度,也就是說內核線程作為一類的特殊的進程可以主動調度,也可以被動調度;
用戶態進程無法實現主動調度,僅能通過陷入內核態後的某個時機點進行調度,即在中斷處理過程中進行調度。
進程的切換:
——為了控制進程的執行,內核必須有能力掛起正在CPU上執行的進程,並恢復以前掛起的某個進程的執行,這叫做進程切換、任務切換、上下文切換;
——掛起正在CPU上執行的進程,與中斷時保存現場是不同的,中斷前後是在同一個進程上下文中,只是由用戶態轉向內核態執行;
——進程上下文包含了進程執行需要的所有信息
| 用戶地址空間:包括程序代碼,數據,用戶堆棧等
| 控制信息:進程描述符,內核堆棧等
| 硬體上下文(注意中斷也要保存硬體上下文只是保存的方法不同)
——schedule()函數選擇一個新的進程來運行,並調用context_switch進行上下文的切換,這個宏調用switch_to來進行關鍵上下文切換
| next = pick_next_task(rq, prev); //進程調度算法都封裝這個函數內部
| context_switch(rq, prev, next); //進程上下文切換
| switch_to利用了prev和next兩個參數:prev指向當前進程,next指向被調度的進程
動態優先級----完全公平調度器CFS
CFS 調度器 - uefi_artisan - CSDN博客
實時進程優於普通進程,每次進行進程調度時,會計算出每一個進程佔用處理器權利的權重參數weight,優先運行weight值大的進程。
進程控制塊 task_struct
淺析Linux下的task_struct結構體 - qq_29503203的博客 - CSDN博客
使用insmod 命令加載模塊,使用rmmod命令卸載模塊。
insmod xxx.ko —— rmmod xxx.ko —— lsmod
模塊運行在內核空間、應用程式運行在用戶空間
由內核實現
不能,模塊是內核函數,不能使用C庫函數
TLB(Translation Lookaside Buffer)傳輸後備緩衝器是一個內存管理單元用於改進虛擬地址到物理地址轉換速度的緩存。TLB是一個小的,虛擬尋址的緩存,其中每一行都保存著一個由單個PTE組成的塊。如果沒有TLB,則每次取數據都需要兩次訪問內存,即查頁表獲得物理地址和取數據。
字符設備 塊設備 網絡設備
file_operations
字符設備驅動的開始,我們必須了解的是三個很重要的數據結構,他們分別是file_operations、inode、file
模塊的註冊與註銷
設備的打開、關閉、讀、寫及其他操作函數
設備的終端服務程序
主設備號和從設備號
通常,為了使應用程式區分所控制設備的類型,內核使用主設備號。而存在多臺同類設備時,為了選擇其中的一種,設備驅動程序就使用此設備號。
SWI(軟中斷)
linux內核中設置了一組用於實現系統功能的子程序,稱為系統調用。系統調用和普通庫函數調用非常相似,只是系統調用由作業系統核心提供,運行於核心態,而普通的函數調用由函數庫或用戶自己提供,運行於用戶態。
用戶空間的程序無法直接執行內核代碼。它們不能直接調用內核空間中的函數,因為內核駐留在受保護的地址空間上。如果進程可以直接在內核的地址空間上讀寫的話,系統安全就會失去控制。所以,應用程式應該以某種方式通知系統,告訴內核自己需要執行一個系統調用,希望系統切換到內核態,這樣內核就可以代表應用程式來執行該系統調用了。
通知內核的機制是靠軟體中斷實現的。首先,用戶程序為系統調用設置參數。其中一個參數是系統調用編號。參數設置完成後,程序執行「系統調用」指令。x86系統上的軟中斷由int產生。這個指令會導致一個異常:產生一個事件,這個事件會致使處理器切換到內核態並跳轉到一個新的地址,並開始執行那裡的異常處理程序。此時的異常處理程序實際上就是系統調用處理程序。它與硬體體系結構緊密相關。
新地址的指令會保存程序的狀態,計算出應該調用哪個系統調用,調用內核中實現哪個系統調用的函數,恢復用戶程序狀態,然後將控制權返還給用戶程序。系統調用是設備驅動程序中定義的函數最終被調用的一種方式。
在Linux中,每個系統調用被賦予一個系統調用號。這樣,通過這個獨一無二的號就可以關聯繫統調用。當用戶空間的進程執行一個系統調用的時候,這個系統調用號就被用來指明到底是要執行哪個系統調用。進程不會提及系統調用的名稱。
軟中斷(softirq):Linux系統把中斷分為兩部分,前半部分是中斷立即執行的,後半部分可以在稍後的某個時候執行。由於後半部分的緊急程度不那麼「硬」,也由於後半部分的執行是由軟體來啟動的,所以後半部分的中斷機制也叫做「軟中斷」。
工作隊列:Linux總是在已經進入就緒狀態的進程中來選擇一個合適的進程來運行的。為了加快尋找速度,Linux就把所有已就緒的進程集中起來形成一個就緒進程隊列。這個隊列就叫工作隊列。
0人點讚
6. linux內核和驅動相關