รับล็อกการอ่าน / เขียนแบบเอกสิทธิ์เฉพาะบุคคลในไฟล์สำหรับการปรับปรุงอะตอม


10

ฉันต้องการมีไฟล์ที่ใช้เป็นตัวนับ ผู้ใช้ A จะเขียนและเพิ่มจำนวนนี้ในขณะที่ผู้ใช้ B ขอให้อ่านไฟล์ เป็นไปได้หรือไม่ที่ผู้ใช้ A สามารถล็อคไฟล์นี้เพื่อให้ไม่มีใครสามารถอ่านหรือเขียนไฟล์ได้จนกว่าการเขียนของผู้ใช้จะเสร็จสิ้น?

ฉันดูแล้วflockแต่ดูเหมือนจะไม่สามารถใช้งานได้ตามที่คาดหวัง

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

หากมีวิธีที่เหมาะสมกว่าในการรับไฟล์ที่เพิ่มขึ้นคล้ายกับอะตอมนี้ซึ่งจะเป็นการฟังที่ดีเช่นกัน!

เป้าหมายของฉันคือ:

LOCK counter.txt; write to counter.txt;

ในขณะที่ในเวลาเดียวกัน

Read counter.txt; realize it's locked so wait until that lock is finished.

1
"ดูเหมือนจะไม่สามารถทำงานได้ตามที่ฉันคาดหวัง" อะไรโดยเฉพาะที่หมายความว่า?
John1024

ฉันแน่ใจว่าฉันใช้มันไม่ถูกต้อง แต่ในขณะที่ใช้รหัสด้านบนฉันสามารถใช้เชลล์สองตัวและให้ทั้งคู่แก้ไขไฟล์ตัวนับในขณะที่ฉันคิดว่ามีคนล็อกอยู่ ดังนั้นถ้าฉันเรียกใช้บรรทัดนั้นสองครั้งบนเปลือกหอยสองอันแยกกัน (แต่ละอันมีหมายเลขของตัวเองเพื่อสะท้อน) ฉันยังคงเห็นหมายเลขที่สองถูกเขียนอยู่
d -_- b

1
เมื่อตัวแรกเสร็จสิ้นและปลดล็อคตัวที่สองจะทำงาน นั่นเป็นวิธีที่ควรใช้หรือไม่ (ในรหัสข้างต้น&& sleep 5จะถูกดำเนินการหลังจากที่ฝูงปลดล็อก)
John1024

อืมข้ากำลังขัดจังหวะ ... ดังนั้นในกรณีนี้มันจะเร็วเกินไปที่ดวงตาของข้าจะจับ ที่ดี! ความท้าทายต่อไปของฉันคือวิธีการใส่คำสั่งหลายคำflockแต่ฉันจะใส่คำถามนั้นแยกต่างหาก ขอบคุณจอห์น!
d -_- b

3
@d -_- b ฉันรักชื่อผู้ใช้ของคุณ นั่นคือชื่อผู้ใช้ที่ฉลาดที่สุดที่ฉันเคยเห็น
Devyn Collier Johnson

คำตอบ:


10

การประมวลผลคำสั่งด้านล่างของ Bash อาจน่าแปลกใจ:

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

วิ่งครั้งแรกทุบตีflock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txtและหากเสร็จสิ้นการที่ประสบความสำเร็จ (ปล่อยล็อค) sleep 5แล้วมันจะทำงาน ดังนั้นล็อคไม่ได้ถูกเก็บไว้เป็นเวลา 5 วินาทีที่อาจคาดหวัง

นอกเหนือจาก&เมื่อเทียบกับ&&

หากมีสองคำสั่งAและBจากนั้น:

  1. A & Bเริ่มAในพื้นหลังแล้วเริ่มBโดยไม่ต้องรอAให้เสร็จ

  2. A && Bเริ่มต้นAรอให้มันเสร็จสมบูรณ์แล้วถ้ามันเสร็จสมบูรณ์เรียบร้อยแล้ว (ถึงแก่กรรมรหัส 0), Bเริ่มต้น หากAล้มเหลว (รหัสการออกที่ไม่ใช่ศูนย์) Bจะไม่มีการเรียกใช้ใด ๆ

โดยสรุป&และ&&เป็นโอเปอเรเตอร์รายการที่แตกต่างกันสองรายการ


3
มันจะแปลกใจเลยถ้าในA && B, AจะรอBจนจบ
Andras Gyomrey

1
ใน A&& B จะดำเนินการก่อน B จะถูกประหารชีวิตถ้า A ถูกดำเนินการและออกสำเร็จแล้ว ใช้; B เพื่อดำเนินการ B เสมอโดยไม่คำนึงถึงสถานะการดำเนินการของ A.
kapad

15

การล็อคไฟล์ไม่บังคับ1 - คุณไม่สามารถล็อคไฟล์เพื่อให้กระบวนการอื่นไม่สามารถเข้าถึงได้ การล็อคไฟล์หมายความว่าหากกระบวนการ (nother) ตรวจสอบเพื่อดูว่ามันถูกล็อคหรือไม่นั้นจะรู้ได้

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

หากไม่สามารถรับล็อคได้ทันทีฝูงรอจนกว่าล็อคจะพร้อมใช้งาน


1. ซึ่งทำให้ฟีเจอร์นี้ดูเหมือนจะไร้ประโยชน์ถ้าคุณใช้มันเพื่อความปลอดภัย แต่นั่นไม่ใช่จุดประสงค์ของการล็อคไฟล์ - มันคือการซิงโครไนซ์ซึ่งเป็นสิ่งที่คุณกำลังทำอยู่ ผู้ใช้ Leo ชี้ให้เห็นว่าอาจมีการนำมาตรฐานการล็อคไฟล์ที่ไม่ได้มาตรฐานไปใช้ในเคอร์เนล linux ( ดูการสนทนานี้ ) ขึ้นอยู่กับการเปรียบเทียบในอดีตจากระบบปฏิบัติการ * nix อื่น ๆ อย่างไรก็ตามนี่เป็นอินเตอร์เฟสระดับ C เท่านั้น


ขอบคุณ! สิ่งนี้ช่วยให้เข้าใจลักษณะ 'คำแนะนำ' และวิธีที่ฉันต้องใช้flockในแต่ละครั้ง มีประโยชน์มาก!
d -_- b

2

คุณสามารถใช้ "คำสั่ง sh -c ... " เพื่อเรียกใช้คำสั่งเชลล์ทั้งหมดรวมถึงการเปลี่ยนเส้นทางไฟล์โดยมีการล็อคไว้ นอกจากนี้เนื่องจากคุณใช้ไฟล์เป็นตัวนับคุณจำเป็นต้องล็อคการล็อคอย่างต่อเนื่องในขณะที่คุณอ่านและเขียนกลับ ดังนั้นคุณต้องการทำอะไรเช่นนี้เพื่อเพิ่มตัวนับและคืนค่าใหม่:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

การเปลี่ยนเครื่องหมายบวกเป็นเครื่องหมายลบควรทำให้ตัวนับลดลง:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

ฉันคาดหวังว่าคุณจะเริ่มต้นการนับก่อนที่การโต้แย้งจะเกิดขึ้นดังนั้นจึงไม่จำเป็นต้องกังวลเกี่ยวกับการล็อกก่อนหน้านี้:

echo 0 > /dev/shm/counter.txt

ฉันไม่คิดว่าคุณจะต้องปิดกั้นค่าตัวนับในขณะที่ความขัดแย้งอาจเกิดขึ้น แต่ถ้าคุณเคยทำคุณควรทำเช่นนั้น:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

ฉันคิดว่าคุณเข้าใจวิธีการอ่าน แต่ฉันรวมไว้เพื่อความสมบูรณ์:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt

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