วิธี จำกัด ทรัพยากรทั้งหมด (หน่วยความจำ) ของกระบวนการและลูก ๆ ของกระบวนการ


16

มีคำถามและคำตอบมากมายเกี่ยวกับการ จำกัด ทรัพยากรของกระบวนการเดียวเช่น RLIMIT_AS สามารถใช้เพื่อ จำกัด หน่วยความจำสูงสุดที่จัดสรรโดยกระบวนการที่สามารถมองเห็นเป็น VIRT topได้ เพิ่มเติมเกี่ยวกับหัวข้อเช่นที่นี่มีวิธี จำกัด ปริมาณหน่วยความจำที่กระบวนการเฉพาะสามารถใช้ใน Unix ได้หรือไม่?

setrlimit(2) เอกสารกล่าวว่า:

กระบวนการลูกที่สร้างผ่าน fork (2) สืบทอดข้อ จำกัด ทรัพยากรของผู้ปกครอง ข้อ จำกัด ทรัพยากรจะถูกเก็บรักษาไว้ใน execve (2)

ควรเข้าใจด้วยวิธีต่อไปนี้:

หากกระบวนการมี RLIMIT_AS เช่น 2GB จะไม่สามารถจัดสรรหน่วยความจำได้มากกว่า 2GB เมื่อวางไข่เด็กขีด จำกัด พื้นที่แอดเดรสของ 2GB จะถูกส่งผ่านไปยังเด็ก แต่การนับเริ่มต้นที่ 0 กระบวนการทั้งสองเข้าด้วยกันสามารถใช้หน่วยความจำได้สูงสุด 4GB

แต่อะไรจะเป็นวิธีที่มีประโยชน์ในการ จำกัด ผลรวมของหน่วยความจำที่จัดสรรโดยแผนผังกระบวนการทั้งหมด?


เกี่ยวข้องแล้ว: unix.stackexchange.com/questions/1424/…
slm

7
ฉันใช้เวลาดูที่cgroups
slm

@slm ขอบคุณ! ฟังดูเหมือน cgroups เป็นสิ่งที่ควรลอง วิธีแก้ปัญหาเดียวที่ทำงานได้ในตอนนี้ (นอกเหนือจากวิธีการรวมหน่วยความจำที่น่าเกลียดโดยใช้ PS และฆ่ากระบวนการหลักหากเกินขีด จำกัด ) ที่อาจใช้งานได้คือการใช้คอนเทนเนอร์ (lxc หรือไลค์)
jpe

ใช่ - เครื่องมือที่ฉันรู้ว่าไม่ได้ทำกลุ่มเพียงแค่กระบวนการเดียว แต่กำหนดว่ากลุ่ม cg ทำงานกับเทคโนโลยี VM เช่น LXC และ Docker ได้อย่างไรฉันคาดหวังให้ทำสิ่งที่คุณต้องการ
slm

1
ถ้าเป็น Linux ให้วาง PID หลักไว้ในเนมสเปซของตนเองและควบคุมมันและลูก ๆ ของมันด้วยวิธีนั้น นี่คือคำตอบเบื้องต้นสำหรับแนวคิดดังกล่าว: unix.stackexchange.com/a/124194/52934
mikeserv

คำตอบ:


8

ฉันไม่แน่ใจว่าสิ่งนี้ตอบคำถามของคุณหรือไม่ แต่ฉันพบสคริปต์ Perlที่อ้างว่าทำสิ่งที่คุณต้องการอย่างแท้จริง สคริปต์ใช้ระบบของตนเองในการบังคับใช้ข้อ จำกัด โดยการปลุกและตรวจสอบการใช้ทรัพยากรของกระบวนการและลูก ๆ ดูเหมือนว่าจะได้รับการบันทึกและอธิบายอย่างดีและได้รับการอัปเดตเมื่อเร็ว ๆ นี้

ในฐานะที่เป็น slm กล่าวในความคิดเห็นของเขากลุ่ม cg ยังสามารถใช้สำหรับการนี้ คุณอาจจะต้องติดตั้งระบบสาธารณูปโภคสำหรับการจัดการ cgroups libcgroupsสมมติว่าคุณอยู่ในลินุกซ์คุณควรมองหา

sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:myGroup

ตรวจสอบให้แน่ใจว่า$USERเป็นผู้ใช้ของคุณ

/sys/fs/cgroup/memory/myGroupผู้ใช้ของคุณแล้วควรมีการเข้าถึงการตั้งค่าหน่วยความจำใน cgroup

จากนั้นคุณสามารถกำหนดขีด จำกัด เป็น 500 MB โดยทำสิ่งนี้:

echo 500000000 > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes

ตอนนี้ให้เรียกใช้เป็นกลุ่ม:

cgexec -g memory:myGroup vim

กระบวนการ vim และลูก ๆ ทั้งหมดของมันควรถูก จำกัด ให้ใช้ RAM 500 MB อย่างไรก็ตามฉันคิดว่าข้อ จำกัด นี้ใช้ได้กับ RAM เท่านั้นไม่ใช่การสลับ เมื่อกระบวนการถึงขีด จำกัด พวกเขาจะเริ่มแลกเปลี่ยน ฉันไม่แน่ใจว่าคุณจะได้รับสิ่งนี้หรือไม่ฉันไม่สามารถหาวิธี จำกัด การใช้ swap ได้โดยใช้กลุ่ม cg


วิธีแก้ปัญหาที่เสนอนั้นทำให้สามารถ จำกัด ขนาดชุดถิ่นที่อยู่ของแผนผังกระบวนการ พฤติกรรมดูเหมือนจะแตกต่างจาก RLIMIT_AS: มันเป็นไปได้ที่ malloc หน่วยความจำมากกว่าที่เป็นขีด จำกัด แต่ดูเหมือนว่าจะไม่สามารถใช้งานได้มากขึ้น
jpe

ตามค่าเริ่มต้นขีด จำกัด หน่วยความจำ cgroup จะใช้กับ (โดยประมาณ) การใช้ RAM จริงเท่านั้น มีตัวเลือกเคอร์เนล (CONFIG_MEMCG_SWAP) เพื่อเปิดใช้งานการแลกเปลี่ยนบัญชี ดูเอกสารเคอร์เนลเพื่อดูรายละเอียด
SørenLøvborg

1
ใน fedorasudo yum install libcgroup-tools
jozxyqk

2

ฉันสร้างสคริปต์ที่ทำสิ่งนี้โดยใช้ cgmanager ซึ่งใช้ใน Ubuntu ข้อดีอย่างหนึ่งคือไม่ต้องใช้การเข้าถึงรูท โปรดทราบว่าการจัดการ cgroup เป็นบิต distro เฉพาะดังนั้นฉันไม่ทราบว่านี้ทำงานบน distros ที่ใช้การจัดการ cgroup systemd

#!/bin/sh

set -eu

if [ "$#" -lt 2 ]
then
    echo Usage: `basename $0` "<limit> <command>..."
    exit 1
fi

limit="$1"
shift
cgname="limitmem_$$"
echo "limiting memory to $limit (cgroup $cgname) for command $@"

cgm create memory "$cgname" >/dev/null
cgm setvalue memory "$cgname" memory.limit_in_bytes "$limit" >/dev/null
# try also limiting swap usage, but this fails if the system has no swap
cgm setvalue memory "$cgname" memsw.limit_in_bytes "$limit" >/dev/null 2>&1 || true

# spawn subshell to run in the cgroup
set +e
(
set -e
cgm movepid memory "$cgname" `sh -c 'echo $PPID'` > /dev/null
exec "$@"
)
# grab exit code
exitcode=`echo $?`

set -e

echo -n "peak memory used: "
cgm getvalue memory "$cgname" memory.max_usage_in_bytes | tail -1 | cut -f2 -d\"

cgm remove memory "$cgname" >/dev/null
exit $exitcode

การใช้งาน: บันทึกlimitmemในเส้นทางของคุณและทำให้มันปฏิบัติการได้ limitmem 1G command...จากนั้นเรียกเช่น ข้อ จำกัด นี้หน่วยความจำที่ใช้งานจริง หากถึงตัวฆาตกร OOM จะฆ่ากระบวนการหรือหนึ่งในลูกของมัน แต่ไม่ใช่สิ่งสุ่มที่ไม่มีส่วนเกี่ยวข้องกับคำสั่งนี้


ขอบคุณสำหรับcgmคำแนะนำสั้น ๆมันมีประโยชน์
Vitaly Isaev

1

/unix//a/536046/4319 :

ในดิสทริบิวเตอร์ที่ยึดตาม systemd ใด ๆ คุณยังสามารถใช้กลุ่ม cg โดยอ้อมผ่าน systemd-run เช่นสำหรับกรณีของคุณ จำกัดpdftoppmRAM 500M ให้ใช้:

systemd-run --scope -p MemoryLimit=500M pdftoppm

...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.