1. 程式人生 > >-bash: fork: Cannot allocate memory

-bash: fork: Cannot allocate memory

今天遇到伺服器無法SSH,VNC操作命令提示fork:cannot allocate memory

free檢視記憶體還有(注意,命令可能要多敲幾次才會出來)

 


檢視最大程序數 sysctl kernel.pid_max



 

ps -eLf | wc -l檢視程序數
 

確認是程序數滿了

修改最大程序數後系統恢復
echo 1000000 > /proc/sys/kernel/pid_max

永久生效
echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
sysctl -p

 

 

(二)

[

[email protected] ~]# java -version

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007ff55c5ea000, 4096, 0) failed; error='Cannot allocate memory' (errno=12)

#

# There is insufficient memory for the Java Runtime Environment to continue.

# Native memory allocation (mmap) failed to map 4096 bytes for committing reserved memory.

# An error report file with more information is saved as:

# /root/hs_err_pid5138.log

  

查找了一下相關文件,發現這個錯誤的含義其實就是像它自己說的,沒法分配記憶體了。

 

The problem is inherent with the way Java allocates memory when executing processes. When Java executes a process, it must fork() then exec(). Forking creates a child process by duplicating the current process. By duplicating the current process, the new child process will request approximately the same amount of memory as its parent process, essentially doubling the memory required. However, this does not mean all the memory allocated will be used, as exec() is immediately called to execute the different code within the child process, freeing up this memory. As an example, when Stash tries to locate git, the Stash JVM process must be forked, approximately doubling the memory required by Stash.

 

解決方案呢有兩個,第一個是用別的方法(例如 posix_spawn)替換掉 Java 的 fork/exec 方法從而申請到記憶體,第二個是開啟系統的 Over-commit,跳過系統的可用記憶體檢查直接分配。

 

第一個方法比較麻煩,需要使用一個 custom JNI binding 去更改 Java 底層呼叫,所以先不嘗試。

第二個方法比較簡單,但可能會導致依賴 C 語言 malloc() 的程式出錯。

 

總之先試試第二個吧,畢竟就是改下系統變數的事兒。

臨時更改: echo 1 > /proc/sys/vm/overcommit_memory

永久更改: 編輯 /etc/sysctl.conf,修改引數 vm.overcommit_memory = 1,重啟伺服器或者使用者重新登入

 

 

(三)swappiness設定

swappiness的值的大小對如何使用swap分割槽是有著很大的聯絡的。swappiness=0的時候表示最大限度使用實體記憶體,然後才是 swap空間,swappiness=100的時候表示積極的使用swap分割槽,並且把記憶體上的資料及時的搬運到swap空間裡面。linux的基本預設設定為60,具體如下:


一般預設值都是60   

[[email protected] ~]# cat /proc/sys/vm/swappiness
60

也就是說,你的記憶體在使用到100-60=40%的時候,就開始出現有交換分割槽的使用。大家知道,記憶體的速度會比磁碟快很多,這樣子會加大系統io,同時造的成大量頁的換進換出,嚴重影響系統的效能,所以我們在作業系統層面,要儘可能使用記憶體,對該引數進行調整。

 

臨時調整的方法如下,我們調成10:
[[email protected] ~]# sysctl vm.swappiness=10
vm.swappiness = 10
[[email protected] ~]# cat /proc/sys/vm/swappiness
10
這只是臨時調整的方法,重啟後會回到預設設定的

要想永久調整的話,需要將
需要在/etc/sysctl.conf修改,加上:
[[email protected] ~]# cat /etc/sysctl.conf

# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296
vm.swappiness=10


啟用設定

[[email protected] ~]# sysctl -p

 

在linux中,可以通過修改swappiness核心引數,降低系統對swap的使用,從而提高系統的效能。


遇到的問題是這樣的,新版本產品釋出後,每小時對記憶體的使用會有一個尖峰。雖然這個峰值還遠沒有到達伺服器的實體記憶體,但確發現記憶體使用達到峰值時系統開始使用swap。在swap的過程中系統性能會有所下降,表現為較大的服務延遲。對這種情況,可以通過調節swappiness核心引數降低系統對swap的使用,從而避免不必要的swap對效能造成的影響。


簡單地說這個引數定義了系統對swap的使用傾向,預設值為60,值越大表示越傾向於使用swap。可以設為0,這樣做並不會禁止對swap的使用,只是最大限度地降低了使用swap的可能性。


通過sysctl -q vm.swappiness可以檢視引數的當前設定。


修改引數的方法是修改/etc/sysctl.conf檔案,加入vm.swappiness=xxx,並重起系統。這個操作相當於是修改虛擬系統中的/proc/sys/vm/swappiness檔案,將值改為XXX數值。


如果不想重起,可以通過sysctl -p動態載入/etc/sysctl.conf檔案,但建議這樣做之前先清空swap。