เอาต์พุตของการเรียก fork()

ผลลัพธ์ของการเรียก fork() ต่อไปนี้จะเป็นอย่างไร

func(){
fork();
fork();
fork() && fork() || fork();
fork();
print("Saikacollection\n");
}

ใครสามารถช่วยฉันในการรับคำตอบสำหรับรหัสนี้รวมถึงคำอธิบายบางอย่างเนื่องจากฉันยังใหม่กับ OS ฉันพบคำถามหลายข้อเกี่ยวกับ fork() บน SO แต่คิดไม่ออกมากนัก


person Prashant Singh    schedule 14.10.2012    source แหล่งที่มา
comment
วันหนึ่ง ฉันจะสร้าง OS ที่ทำหน้าที่หยุดความวิกลจริต!! และจะตายเมื่อมีส้อม 4 อันเกิดขึ้นโดยไม่มีการประมวลผลอยู่ระหว่างนั้น   -  person cHao    schedule 14.10.2012
comment
ไม่ใช่ตัวอย่างเชิงปฏิบัติ เป็นเพียงคำถามสัมภาษณ์เพื่อตรวจสอบความเข้าใจ   -  person Prashant Singh    schedule 14.10.2012
comment
ผลลัพธ์คือกระบวนการจำนวนมาก   -  person nneonneo    schedule 14.10.2012
comment
@nneonneo คุณช่วยอธิบายอย่างละเอียดได้ไหม? มันจะเกิดขึ้นได้อย่างไร?   -  person Prashant Singh    schedule 14.10.2012
comment
@cHao: OS X ทำได้ค่อนข้างดีในเรื่องนี้ โดยทั่วไปแล้ว forkbombs จะพบกับทรัพยากรที่ไม่สามารถใช้งานได้ชั่วคราว   -  person nneonneo    schedule 14.10.2012
comment
@PrasantSingh: แต่ละ fork() เปลี่ยนหนึ่งกระบวนการเป็นสอง ทั้งสองจะ fork() อีกครั้ง และตอนนี้คุณมี 4 จากนั้นอีกครั้ง และคุณมี 8 ครึ่งหนึ่งของสิ่งเหล่านั้น (กระบวนการหลัก) จะแยก อีกครั้ง และตอนนี้คุณมี 12 เป็นต้น   -  person cHao    schedule 14.10.2012
comment
@ PrashantSingh: ฉันล้อเล่น ผลลัพธ์ก็คือมีการสร้างกระบวนการจำนวนมากพอสมควร ดังนั้นคุณอาจเห็น Saikacollection พิมพ์ออกมาหลายครั้ง ฉันไม่เห็นประเด็นในการพยายามนับจำนวนจริงๆ และมันเป็นคำถามสัมภาษณ์ที่แย่มาก   -  person nneonneo    schedule 14.10.2012
comment
@cHao ลองดูคำตอบที่ฉันได้รับในที่สุด   -  person Prashant Singh    schedule 03.11.2012
comment
@nneonneo ตรวจสอบคำตอบที่ฉันโพสต์   -  person Prashant Singh    schedule 03.11.2012
comment
บุกโจมตีส้อม! ไปที่ที่พักพิงระเบิด!   -  person Linuxios    schedule 03.11.2012


คำตอบ (3)


Saikacollection จะถูกพิมพ์ 40 ครั้งเป็นเอาต์พุตไปยังโค้ด อธิบายได้ดังนี้:-

เพื่อให้เข้าใจถึงผลลัพธ์ เราจำเป็นต้องรู้สิ่งต่อไปนี้:-

  • เมื่อดำเนินการโทร fork() ได้สำเร็จ ลูกใหม่จะถูกสร้างขึ้น กระบวนการสร้างลูกเรียกว่า parent process.
  • การเรียก Fork() ส่งคืน pid (ตัวระบุกระบวนการ) ของลูกไปยังพาเรนต์
  • Fork() ส่งคืน 0 ไปยังกระบวนการลูก

ป้อนคำอธิบายรูปภาพที่นี่

พิจารณาภาพที่แสดง:-

แบบแผน : ผู้ปกครองทั้งหมด (ผู้โทร) ของกระบวนการจะถูกเขียนไปที่ left และทำเครื่องหมายด้วย star

fork()
  • ในตอนแรก เรามีเพียง 1 กระบวนการ ดังนั้นการเรียก fork() จะสร้างรายการย่อยขึ้นมา เมื่อพิจารณารากของต้นไม้เป็นระดับ 1 เราจะเห็นได้ในระดับ 2 เรามีสองกระบวนการ parent(left) และ child(right)

    fork()

  • fork() จะสร้าง 4 กระบวนการดังกล่าวอีกครั้ง โดยมีเครื่องหมาย 1, 2, 3, 4 เนื่องจากทั้งสี่กระบวนการจะต้องผ่านโครงสร้างโค้ดที่คล้ายกันเพิ่มเติม เราจึงสามารถพูดได้ว่าจำนวนกระบวนการทั้งหมดจะเป็น 4 คูณด้วยกระบวนการเดียวที่สร้าง

    fork()&&fork()||fork()

  • การทำความเข้าใจข้อความนี้เกี่ยวข้องกับการตระหนักว่าใน C, && operator has more precedence than ||

  • นอกจากนี้ ถ้า first จากสองตัวถูกดำเนินการที่เชื่อมด้วย && ไปเป็น wrong เราก็ don't check the second ในทำนองเดียวกัน ถ้า first ของสองตัวถูกดำเนินการของ || คือ true, we don't check the second ถูกดำเนินการ
  • พิจารณาว่าการเรียก fork() ที่โหนด 1 (ทำเครื่องหมาย) มีการสร้างกระบวนการสองกระบวนการ ในขณะที่ผู้ปกครองได้รับจำนวนบวก (pid) เมื่อส่งคืน ลูกจะได้รับ 0 ดังนั้นผู้ปกครองจึงดำเนินการตัวดำเนินการที่สอง ในขณะที่ลูกกระโดดไปที่ fork() หลังจาก || ตามที่ระบุไว้ในรูป
  • การดำเนินการของ &&fork() สำหรับพาเรนต์ที่ระดับที่ 4 จะส่งกลับ pid สำหรับหนึ่งกระบวนการ ซึ่งจะยุติลง ในขณะที่รายการย่อยของขั้นตอนนั้นได้รับ 0 ดังนั้นจึงไปที่การดำเนินการของ ||fork()
  • การเรียก ||fork() สุดท้ายสำหรับลูกระดับ 5 ทำให้เกิดกระบวนการเพิ่มเติมตามมา
  • ในตอนท้ายของขั้นตอน เรามี 5 ใบไม้ (กระบวนการ) ตามที่ทำเครื่องหมายไว้ด้วยการขีดเส้นใต้ในรูป
  • หากเราทำแบบเดียวกันกับทั้งสามโหนด เราอาจมี 5*4 = 20 กระบวนการ

    fork()

  • Final fork() เพียง doubles จำนวนกระบวนการที่มีอยู่ในขั้นตอนนั้น

  • ดังนั้น จำนวนกระบวนการทั้งหมด = 2*20 = 40
person Prashant Singh    schedule 03.11.2012

Saikacollection พิมพ์ขึ้นบรรทัดใหม่ 32 ครั้งทุกครั้ง

person Sahil Sharma    schedule 15.10.2012
comment
สมมติว่าระบบปฏิบัติการซิงโครไนซ์การเข้าถึง stdout ระหว่างกระบวนการ ถ้าไม่เช่นนั้น คุณก็อาจจะจบลงด้วย SSSSSSSSSSaaaaSaaaaaiSaaaaiiSSS... - person cHao; 15.10.2012
comment
คุณช่วยอธิบายมันหน่อยได้ไหม? - person Prashant Singh; 22.10.2012
comment
@ user1747039 ไม่ควรเป็น 40 แทนที่จะเป็น 32 ฉันคิดว่าคุณทำผิดที่ไหนสักแห่ง - person Prashant Singh; 02.11.2012

หากคุณต้องการให้กระบวนการใหม่มีความเป็นอิสระมากขึ้น คุณอาจลองดู exec-* family of funcitons (POSIX) เพื่อให้คุณสามารถแยก จากนั้นจึงแทนที่กระบวนการแยกทันที (คุณสามารถทำได้ เนื่องจากกระบวนการที่แยกใหม่ถูกควบคุม โดยคุณ); หรืออาจจะดูที่ popen() เช่นกัน

person user6856855    schedule 21.09.2016