1. 程式人生 > 其它 >11-程序執行機制及狀態切換

11-程序執行機制及狀態切換

 

一. 程序使用記憶體問題 1 記憶體洩漏:Memory Leak 指程式中用malloc或new申請了一塊記憶體,但是沒有用free或delete將記憶體釋放,導致這塊記憶體一直處於佔用狀態 2 記憶體溢位:Memory Overflow 指程式申請了10M的空間,但是在這個空間寫入10M以上位元組的資料,就是溢位,類似紅杏出牆,nginx 申請root使用者記憶體rm -rf / 3 記憶體不足:OOM OOM 即 Out Of Memory,“記憶體用完了”,在情況在java程式中比較常見。系統會選一個程序將之殺死, 在日誌messages中看到類似下面的提示 X X 10:20:30 kernel: Out of memory: Kill process 9527 (java) score 88 or sacrifice child 當JVM因為沒有足夠的記憶體來為物件分配空間並且垃圾回收器也已經沒有空間可回收時,就會丟擲這個 error,因為這個問題已經嚴重到不足以被應用處理)。 原因: 給應用分配記憶體太少:比如虛擬機器本身可使用的記憶體(一般通過啟動時的VM引數指定)太少。 應用用的太多,並且用完沒釋放,浪費了。此時就會造成記憶體洩露或者記憶體溢位。 使用的解決辦法: 1,限制java程序的max heap,並且降低java程式的worker數量,從而降低記憶體使用 2,給系統增加swap空間
[root@centos7 ~]# cat  /proc/sys/vm/overcommit_memory
0
說明: Linux預設是允許memory overcommit的,只要你來申請記憶體我就給你,寄希望於程序實際上用不到那麼多記憶體,但萬一用到那麼多了呢?Linux設計了一個OOM killer機制挑選一個程序出來殺死,以騰出部分記憶體,如果還不夠就繼續。也可通過設定核心引數 vm.panic_on_oom 使得發生OOM時自動重啟系統。這都是有風險的機制,重啟有可能造成業務中斷,殺死程序也有可能導致業務中斷。所以Linux 2.6之後允許通過核心引數 vm.overcommit_memory 禁止memory overcommit。 vm.overcommit_memory 接受三種取值:
0
– Heuristic overcommit handling. 這是預設值,它允許overcommit,但過於明目張膽的overcommit會被拒絕,比如malloc一次性申請的記憶體大小就超過了系統總記憶體。Heuristic的意思是“試探式的”,核心利用某種演算法猜測你的記憶體申請是否合理,它認為不合理就會拒絕overcommit。 1 – Always overcommit. 允許overcommit,對記憶體申請來者不拒。核心執行無記憶體過量使用處理。使用這個設定會增大記憶體超載的可能性,但也可以增強大量使用記憶體任務的效能。 2 – Don’t overcommit. 禁止overcommit。 記憶體拒絕等於或者大於總可用 swap 大小以及overcommit_ratio 指定的物理 RAM 比例的記憶體請求。如果希望減小記憶體過度使用的風險,這個設定就是最好的。
設定核心引數(不推薦),不允許記憶體申請過量:
echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio
echo 2 > /proc/sys/vm/panic_on_oom

 vm.overcommit_memory = 1    redis,部署redis,申請記憶體來著不拒,增強大量使用記憶體任務的效能

 net.core.somaxconn = 16384   三次握手 server 端 ESTABLISHED狀態到 還沒被 accept() 系統呼叫取走 之間是 accept queue 佇列

 

程序狀態

 

 

程序的基本狀態 建立狀態:程序在建立時需要申請一個空白PCB(process control block程序控制塊),向其中填寫控制和管理程序的資訊,完成資源分配。如果建立工作無法完成,比如資源無法滿足,就無法被排程執行,把此時程序所處狀態。 就緒狀態:程序已準備好,已分配到所需資源,只要分配到CPU就能夠立即執行 執行狀態:程序處於就緒狀態被排程後,程序進入執行狀態 阻塞狀態:正在執行的程序由於某些事件(I/O請求,申請快取區失敗)而暫時無法執行,程序受到阻塞。在滿足請求時進入就緒狀態等待系統呼叫 終止狀態:程序結束,或出現錯誤,或被系統終止,進入終止狀態。無法再執行      VSZ: Virtual memory SiZe,虛擬記憶體集,線性記憶體 RSS: ReSident Size, 常駐記憶體集 STAT:程序狀態 R:running 執行態   在該狀態的程序才可能在CPU上執行。而同一時刻可能有多個程序處於可執行狀態    S: interruptable sleeping   睡眠態可中斷   處於這個狀態的程序因為等待某某事件的發生(比如等待socket連線、等待訊號量),而被掛起。這些程序的task_struct結構被放入對應事件的等待佇列中。當這些事件發生時(由外部中斷觸發、或由其他程序觸發),對應的等待佇列中的一個或多個程序將被喚醒,CPU就這麼一兩個,程序動輒幾十上百個,如果不是絕大多數程序都在睡眠,CPU又怎麼響應得過來 D: uninterruptable sleeping    睡眠態不可中斷   kill -9竟然殺不死,很少見這個狀態 T: stopped 停止態        暫停於記憶體,但不會被排程,除非手動啟動 Z: zombie         殭屍態,結束程序,父程序結束前,子程序不關閉,殺死父程序可以關閉僵死態的子程序
[root@centos7 ~]# ps aux|grep nginx
root       945  0.0  0.0  28224   672 ?        Ss   07:22   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx      947  0.0  0.7  55756 29176 ?        S    07:22   0:05 nginx: worker process
nginx      948  0.0  0.7  55756 29176 ?        S    07:22   0:05 nginx: worker process
[root@centos7 ~]# ps aux|grep nginx
root       945  0.0  0.0  28224   672 ?        Ss   07:22   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx      947  0.0  0.7  55756 29176 ?        R    07:22   0:05 nginx: worker process
nginx      948  0.0  0.7  55756 29176 ?        R    07:22   0:05 nginx: worker process
nginx      947  0.2  0.7  55756 29176 ?        R    07:22   0:33 nginx: worker process
nginx      948  0.2  0.7  55756 29176 ?        S    07:22   0:33 nginx: worker process

 構建殭屍態

kill -19 3799
root        3799  0.0  0.1   8440  5444 pts/1    Ts   00:19   0:00 -bash
kill tail程序 殭屍態 root@ubuntu2004:
~# ps aux |grep Z USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 8685 0.0 0.0 0 0 pts/1 Z+ 03:37 0:00 [tail] <defunct>

殭屍態程序怎麼處理?

kill -18 3799

kill 父程序救活父程序或重啟機器

 

孤兒程序

如果在子程序在退出前,父程序先退出,這時子程序將成為孤兒程序,因為它的父程序已經死了。孤兒程序會被PID=1的systemd程序收養,成為systemd的子程序. 注意,孤兒程序還會繼續執行,而不會隨父程序退出而終止,只不過其父程序發生了改變。
systemd(1)─sshd(930)───sshd(2892)─┬─bash(9128)───screen(9263)───screen(9264)───bash(9265)───ping(9273)

新爹

systemd(1)├─screen(9264)───bash(9265)───ping(9273)

 

#利用()實現當前shell的子程序,&實現後臺執行,子程序結束後  
(sleep 100 &)
root@ubuntu2004:~# pstree -p|grep sleep  #孤兒程序
           |-sleep(9465

 

root@ubuntu2004:~# (sleep 100 )&
[1] 9417
root@ubuntu2004:~# pstree -s `pidof sleep`   正常
systemd───sshd───sshd───bash───sleep