linux用戶態
Ⅰ linux中的內核態和用戶態的區別,該如何解決
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0級)內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。當進程在執行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象徵性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。這與處於內核態的進程的狀態有些類似。
Ⅱ 為什麼 Linux 不將網路協議棧在用戶態實現
Linux其實有用戶態的協議棧.像Intel的dpdk和另外一個開源項目netmap,都可以把本來在內核態實現的協議棧,放到用戶態來實現.
不過他們的主要用途不是實現一個用戶態的協議棧,主要用來做包處理.
Ⅲ Linux內核態程序和用戶態程序的區別
操作系統的內核(kernel)的不同,體現在-可執行文件格式的不同(linux用的是標準的ELF格式,我不了解windows採用什麼格式)-
系統調用
(syscall)不同,
系統編程
介面不同,導致在兩個操作系統間的程序移植比較困難-靜態、
動態鏈接庫
機制、格式不同...
Ⅳ 在unix/linux系統中,什麼是用戶態,什麼是內核態
用戶態和內核態
內核棧:Linux中每個進程有兩個棧,分別用於用戶態和內核態的進程執行,其中的內核棧就是用於內核態的堆棧,它和進程的task_struct結構,更具體的是thread_info結構一起放在兩個連續的頁框大小的空間內。
現在我們從特權級的調度來理解用戶態和內核態就比較好理解了,當程序運行在3級特權級上時,就可以稱之為運行在用戶態,因為這是最低特權級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態;反之,當程序運行在0級特權級上時,就可以稱之為運行在內核態。
雖然用戶態下和內核態下工作的程序有很多差別,但最重要的差別就在於特權級的不同,即權力的不同。運行在用戶態的程序不能訪問操作系統內核數據結構合程序。 當我們在系統中執行一個程序時,大部分時間是運行在用戶態下的。在其需要操作系統幫助完成某些它沒有權力和能力完成的工作時就會切換到內核態。
Linux進程的4GB地址空間,3G-4G部分大家是共享的,是內核態的地址空間,這里存放在整個內核的代碼和所有的內核模塊,以及內核所維護的數據。用戶運行一個程序,該程序所創建的進程開始是運行在用戶態的,如果要執行文件操作,網路數據發送等操作,必須通過write,send等系統調用,這些系統調用會調用內核中的代碼來完成操作,這時,必須切換到Ring0,然後進入3GB-4GB中的內核地址空間去執行這些代碼完成操作,完成後,切換回Ring3,回到用戶態。這樣,用戶態的程序就不能隨意操作內核地址空間,具有一定的安全保護作用。
保護模式,通過內存頁表操作等機制,保證進程間的地址空間不會互相沖突,一個進程的操作不會修改另一個進程的地址空間中的數據。在內核態下,CPU可執行任何指令,在用戶態下CPU只能執行非特權指令。當CPU處於內核態,可以隨意進入用戶態;而當CPU處於用戶態,只能通過中斷的方式進入內核態。一般程序一開始都是運行於用戶態,當程序需要使用系統資源時,就必須通過調用軟中斷進入內核態.
Ⅳ linux內核態和用戶態的通信機制包括哪些
究竟什麼是用戶態,什麼是內核態,這兩個基本概念以前一直理解得不是很清楚,根本原因個人覺得是在於因為大部分時候我們在寫程序時關注的重點和著眼的角度放在了實現的功能和代碼的邏輯性上,先看一個例子:
1)例子
C代碼
1. void testfork(){
2. if(0 = = fork()){
3. printf(「create new process success!\n」);
4. }
5. printf(「testfork ok\n」);
6. }
這段代碼很簡單,從功能的角度來看,就是實際執行了一個fork(),生成一個新的進程,從邏輯的角度看,就是判斷了如果fork()返回的是則列印相關語句,然後函數最後再列印一句表示執行完整個testfork()函數。代碼的執行邏輯和功能上看就是如此簡單,一共四行代碼,從上到下一句一句執行而已,完全看不出來哪裡有體現出用戶態和進程態的概念。
如果說前面兩種是靜態觀察的角度看的話,我們還可以從動態的角度來看這段代碼,即它被轉換成CPU執行的指令後載入執行的過程,這時這段程序就是一個動態執行的指令序列。而究竟載入了哪些代碼,如何載入就是和操作系統密切相關了。
2)特權級
熟悉Unix/Linux系統的人都知道,fork的工作實際上是以系統調用的方式完成相應功能的,具體的工作是由sys_fork負責實施。其實無論是不是Unix或者Linux,對於任何操作系統來說,創建一個新的進程都是屬於核心功能,因為它要做很多底層細致地工作,消耗系統的物理資源,比如分配物理內存,從父進程拷貝相關信息,拷貝設置頁目錄頁表等等,這些顯然不能隨便讓哪個程序就能去做,於是就自然引出特權級別的概念,顯然,最關鍵性的權力必須由高特權級的程序來執行,這樣才可以做到集中管理,減少有限資源的訪問和使用沖突。
特權級顯然是非常有效的管理和控製程序執行的手段,因此在硬體上對特權級做了很多支持,就Intel x86架構的CPU來說一共有0~3四個特權級,0級最高,3級最低,硬體上在執行每條指令時都會對指令所具有的特權級做相應的檢查,相關的概念有 CPL、DPL和RPL,這里不再過多闡述。硬體已經提供了一套特權級使用的相關機制,軟體自然就是好好利用的問題,這屬於操作系統要做的事情,對於 Unix/Linux來說,只使用了0級特權級和3級特權級。也就是說在Unix/Linux系統中,一條工作在級特權級的指令具有了CPU能提供的最高權力,而一條工作在3級特權級的指令具有CPU提供的最低或者說最基本權力。
3)用戶態和內核態
現在我們從特權級的調度來理解用戶態和內核態就比較好理解了,當程序運行在3級特權級上時,就可以稱之為運行在用戶態,因為這是最低特權級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態;反之,當程序運行在級特權級上時,就可以稱之為運行在內核態。
雖然用戶態下和內核態下工作的程序有很多差別,但最重要的差別就在於特權級的不同,即權力的不同。運行在用戶態下的程序不能直接訪問操作系統內核數據結構和程序,比如上面例子中的testfork()就不能直接調用 sys_fork(),因為前者是工作在用戶態,屬於用戶態程序,而sys_fork()是工作在內核態,屬於內核態程序。
當我們在系統中執行一個程序時,大部分時間是運行在用戶態下的,在其需要操作系統幫助完成某些它沒有權力和能力完成的工作時就會切換到內核態,比如testfork()最初運行在用戶態進程下,當它調用fork()最終觸發 sys_fork()的執行時,就切換到了內核態。
2. 用戶態和內核態的轉換
1)用戶態切換到內核態的3種方式
a. 系統調用
這是用戶態進程主動要求切換到內核態的一種方式,用戶態進程通過系統調用申請使用操作系統提供的服務程序完成工作,比如前例中fork()實際上就是執行了一個創建新進程的系統調用。而系統調用的機制其核心還是使用了操作系統為用戶特別開放的一個中斷來實現,例如Linux的int 80h中斷。
b. 異常
當CPU在執行運行在用戶態下的程序時,發生了某些事先不可知的異常,這時會觸發由當前運行進程切換到處理此異常的內核相關程序中,也就轉到了內核態,比如缺頁異常。
c. 外圍設備的中斷
當外圍設備完成用戶請求的操作後,會向CPU發出相應的中斷信號,這時CPU會暫停執行下一條即將要執行的指令轉而去執行與中斷信號對應的處理程序,如果先前執行的指令是用戶態下的程序,那麼這個轉換的過程自然也就發生了由用戶態到內核態的切換。比如硬碟讀寫操作完成,系統會切換到硬碟讀寫的中斷處理程序中執行後續操作等。
這3種方式是系統在運行時由用戶態轉到內核態的最主要方式,其中系統調用可以認為是用戶進程主動發起的,異常和外圍設備中斷則是被動的。
2)具體的切換操作
從觸發方式上看,可以認為存在前述3種不同的類型,但是從最終實際完成由用戶態到內核態的切換操作上來說,涉及的關鍵步驟是完全一致的,沒有任何區別,都相當於執行了一個中斷響應的過程,因為系統調用實際上最終是中斷機制實現的,而異常和中斷的處理機制基本上也是一致的,關於它們的具體區別這里不再贅述。關於中斷處理機制的細節和步驟這里也不做過多分析,涉及到由用戶態切換到內核態的步驟主要包括:
[1] 從當前進程的描述符中提取其內核棧的ss0及esp0信息。
[2] 使用ss0和esp0指向的內核棧將當前進程的cs,eip,eflags,ss,esp信息保存起來,這個
過程也完成了由用戶棧到內核棧的切換過程,同時保存了被暫停執行的程序的下一
條指令。
[3] 將先前由中斷向量檢索得到的中斷處理程序的cs,eip信息裝入相應的寄存器,開始
執行中斷處理程序,這時就轉到了內核態的程序執行了。
Ⅵ linux用戶態棧空間的大小有沒有限制
當然有限制,你可以使用命令 ulimit -s 查看大小。
因為物理空間存在著大小限制,因此棧空間肯定也是有大小限制的,不然程序還不崩了。
甚至,你可以測試一下,分配一個超大的棧空間(方法是,在函數中,定義一個超大空間的數組),然後看是否可以運行,當達到一個限制的時候,程序是無法正常運行的
Ⅶ 用戶態的linux用戶態
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0 級)內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。
當進程在執行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3 級)用戶代碼中運行。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象徵性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。這與處於內核態的進程的狀態有些類似。
簡言之:
1、用系統調用時進入核心態。Linux 對硬體的操作只能在核心態,這可以通過寫驅動程序來控制。在用戶態操作硬體會造成core mp。
2、要注意區分系統調用和一般的函數。系統調用由內核提供,如read()、write()、open()等。而一般的函數由軟體包中的函數庫提供,如sin()、cos()等。在語法上兩者沒有區別。
3、一般情況:系統調用運行在核心態,函數運行在用戶態。但也有一些函數在內部使用了系統調用(如fopen),這樣的函數在調用系統調用是進入核心態,其他時候運行在用戶態。 處理器總處於以下狀態中的一種:
1、內核態,運行於進程上下文,內核代表進程運行於內核空間;
2、內核態,運行於中斷上下文,內核代表硬體運行於內核空間;
3、用戶態,運行於用戶空間。
用戶空間的應用程序,通過系統調用,進入內核空間。這個時候用戶空間的進程要傳遞很多變數、參數的值給內核,內核態運行的時候也要保存用戶進程的一些寄存器值、變數等。所謂的「進程上下文」,可以看作是用戶進程傳遞給內核的這些參數以及內核要保存的那一整套的變數和寄存器值和當時的環境等。
硬體通過觸發信號,導致內核調用中斷處理程序,進入內核空間。這個過程中,硬體的一些變數和參數也要傳遞給內核,內核通過這些參數進行中斷處理。所謂的「中斷上下文」,其實也可以看作就是硬體傳遞過來的這些參數和內核需要保存的一些其他環境(主要是當前被打斷執行的進程環境)。
Ⅷ 請教linux下用戶態進程調度問題
在進行Linux系統操作的時候,有時候會遇到一次用戶態進程死循環,即系統反應遲鈍、進程掛死等問題,那麼遇到這些問題又該如何解決呢?下面小編就給大家介紹下一次用戶態進程死循環的問題該如何處理。
Linux下如何處理一次用戶態進程死循環問題
1、問題現象
業務進程(用戶態多線程程序)掛死,操作系統反應遲鈍,系統日誌沒有任何異常。從進程的內核態堆棧看,看似所有線程都卡在了內核態的如下堆棧流程中:
[root@vmc116 ~]# cat /proc/27007/task/11825/stack
[《ffffffff8100baf6》] retint_careful+0x14/0x32
[《ffffffffffffffff》] 0xffffffffffffffff
2、問題分析
1)內核堆棧分析
從內核堆棧看,所有進程都阻塞在 retint_careful上,這個是中斷返回過程中的流程,代碼(匯編)如下:
entry_64.S
代碼如下:
ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
/* Restore saved previous stack */
popq %rsi
CFI_DEF_CFA rsi,SS+8-RBP /* reg/off reset after def_cfa_expr */
leaq ARGOFFSET-RBP(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET
。。。
retint_careful:
CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
pushq_cfi %rdi
SCHEDULE_USER
popq_cfi %rdi
GET_THREAD_INFO(%rcx)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
jmp retint_check
這其實是用戶態進程在用戶態被中斷打斷後,從中斷返回的流程,結合retint_careful+0x14/0x32,進行反匯編,可以確認阻塞的點其實就在
SCHEDULE_USER
這其實就是調用schele()進行調度,也就是說當進程走到中斷返回的流程中時,發現需要調度(設置了TIF_NEED_RESCHED),於是在這里發生了調度。
有一個疑問:為什麼在堆棧中看不到schele()這一級的棧幀呢?
因為這里是匯編直接調用的,沒有進行相關棧幀壓棧和上下文保存操作。
2)進行狀態信息分析
從top命令結果看,相關線程實際一直處於R狀態,CPU幾乎完全耗盡,而且絕大部分都消耗在用戶態:
[root@vmc116 ~]# top
top - 09:42:23 up 16 days, 2:21, 23 users, load average: 84.08, 84.30, 83.62
Tasks: 1037 total, 85 running, 952 sleeping, 0 stopped, 0 zombie
Cpu(s): 97.6%us, 2.2%sy, 0.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32878852k total, 32315464k used, 563388k free, 374152k buffers
Swap: 35110904k total, 38644k used, 35072260k free, 28852536k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27074 root 20 0 5316m 163m 14m R 10.2 0.5 321:06.17 z_itask_templat
27084 root 20 0 5316m 163m 14m R 10.2 0.5 296:23.37 z_itask_templat
27085 root 20 0 5316m 163m 14m R 10.2 0.5 337:57.26 z_itask_templat
27095 root 20 0 5316m 163m 14m R 10.2 0.5 327:31.93 z_itask_templat
27102 root 20 0 5316m 163m 14m R 10.2 0.5 306:49.44 z_itask_templat
27113 root 20 0 5316m 163m 14m R 10.2 0.5 310:47.41 z_itask_templat
25730 root 20 0 5316m 163m 14m R 10.2 0.5 283:03.37 z_itask_templat
30069 root 20 0 5316m 163m 14m R 10.2 0.5 283:49.67 z_itask_templat
13938 root 20 0 5316m 163m 14m R 10.2 0.5 261:24.46 z_itask_templat
16326 root 20 0 5316m 163m 14m R 10.2 0.5 150:24.53 z_itask_templat
6795 root 20 0 5316m 163m 14m R 10.2 0.5 100:26.77 z_itask_templat
27063 root 20 0 5316m 163m 14m R 9.9 0.5 337:18.77 z_itask_templat
27065 root 20 0 5316m 163m 14m R 9.9 0.5 314:24.17 z_itask_templat
27068 root 20 0 5316m 163m 14m R 9.9 0.5 336:32.78 z_itask_templat
27069 root 20 0 5316m 163m 14m R 9.9 0.5 338:55.08 z_itask_templat
27072 root 20 0 5316m 163m 14m R 9.9 0.5 306:46.08 z_itask_templat
27075 root 20 0 5316m 163m 14m R 9.9 0.5 316:49.51 z_itask_templat
。。。
3)進程調度信息
從相關線程的調度信息看:
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15681811525768 129628804592612 3557465
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682016493013 129630684625241 3557509
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682843570331 129638127548315 3557686
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683323640217 129642447477861 3557793
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683698477621 129645817640726 3557875
發現相關線程的調度統計一直在增加,說明相關線程一直是在被調度運行的,結合其狀態也一直是R,推測很可能在用戶態發生了死循環(或者非睡眠死鎖)。
這里又有問題:為什麼從top看每個線程的CPU佔用率只有10%左右,而不是通常看到的死循環進程導致的100%的佔用率?
因為線程數很多,而且優先順序都一樣,根據CFS調度演算法,會平均分配時間片,不會讓其中一個線程獨佔CPU。結果為多個線程間輪流調度,消耗掉了所有的cpu。。
另一個問題:為什麼這種情況下,內核沒有檢測到softlockup?
因為業務進程的優先順序不高,不會影響watchdog內核線程(最高優先順序的實時線程)的調度,所以不會產生softlockup的情況。
再一個問題:為什麼每次查看線程堆棧時,總是阻塞在retint_careful,而不是其它地方?
因為這里(中斷返回的時候)正是調度的時機點,在其它時間點不能發生調度(不考慮其它情況~),而我們查看線程堆棧的行為,也必須依賴於進程調度,所以我們每次查看堆棧時,正是查看堆棧的進程(cat命令)得到調度的時候,這時正是中斷返回的時候,所以正好看到的阻塞點為retint_careful。
4)用戶態分析
從上面的分析看,推測應該是用戶態發生了死鎖。
用戶態確認方法:
部署debug信息,然後gdb attach相關進程,確認堆棧,並結合代碼邏輯分析。
最終確認該問題確為用戶態進程中產生了死循環。
Ⅸ linux用戶態的信號量可以跨用戶訪問嗎
可以的,system v信號量的訪問許可權規則和文件訪問許可權規則一模一樣,都遵循linux用戶組和用戶的許可權繼承規則。
事實上用戶態信號量的結構體裡面有個ipc對象結構成員,記錄了程序的所有者用戶id,所有者組id、創建者及其組id,以及訪問模式等等,和文件訪問控制差不多。
Ⅹ linux操作系統中內核態和用戶態的差別在哪兒
操作系統的內核(kernel)的不同,體現在-可執行文件格式的不同(linux用的是標準的ELF格式,我不了解windows採用什麼格式)-系統調用(syscall)不同,系統編程介面不同,導致在兩個操作系統間的程序移植比較困難-靜態、動態鏈接庫機制、格式不同-開發方式不同,linux內核是開放源碼的,而windows是封閉式開發。-等等等等