ไฟล์ใดในเคอร์เนลระบุ fork (), vfork () ... เพื่อใช้การเรียกระบบ sys_clone ()


9

เมื่อ ltrace ใช้สำหรับการติดตามการเรียกของระบบฉันเห็นว่า fork () ใช้ sys_clone () มากกว่า sys_fork () แต่ฉันไม่สามารถหาแหล่งที่มาของลินุกซ์ที่มีการกำหนดไว้

โปรแกรมของฉันคือ

#include<stdio.h>
main()
{
        int pid,i=0,j=0;
        pid=fork();
        if(pid==0)
                printf("\nI am child\n");
        else
                printf("\nI am parent\n");

}

และเอาท์พุท ltrace คือ

SYS_brk(NULL)                                                                               = 0x019d0000
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_mmap(0, 8192, 3, 34, 0xffffffff)                                                        = 0x7fe3cf84f000
SYS_access("/etc/ld.so.preload", 04)                                                        = -2
SYS_open("/etc/ld.so.cache", 0, 01)                                                         = 3
SYS_fstat(3, 0x7fff47007890)                                                                = 0
SYS_mmap(0, 103967, 1, 2, 3)                                                                = 0x7fe3cf835000
SYS_close(3)                                                                                = 0
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_open("/lib/x86_64-linux-gnu/libc.so.6", 0, 00)                                          = 3
SYS_read(3, "\177ELF\002\001\001", 832)                                                     = 832
SYS_fstat(3, 0x7fff470078e0)                                                                = 0
SYS_mmap(0, 0x389858, 5, 2050, 3)                                                           = 0x7fe3cf2a8000
SYS_mprotect(0x7fe3cf428000, 2097152, 0)                                                    = 0
SYS_mmap(0x7fe3cf628000, 20480, 3, 2066, 3)                                                 = 0x7fe3cf628000
SYS_mmap(0x7fe3cf62d000, 18520, 3, 50, 0xffffffff)                                          = 0x7fe3cf62d000
SYS_close(3)                                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf834000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf833000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf832000
SYS_arch_prctl(4098, 0x7fe3cf833700, 0x7fe3cf832000, 34, 0xffffffff)                        = 0
SYS_mprotect(0x7fe3cf628000, 16384, 1)                                                      = 0
SYS_mprotect(0x7fe3cf851000, 4096, 1)                                                       = 0
SYS_munmap(0x7fe3cf835000, 103967)                                                          = 0
__libc_start_main(0x40054c, 1, 0x7fff47008298, 0x4005a0, 0x400590 <unfinished ...>
fork( <unfinished ...>
SYS_clone(0x1200011, 0, 0, 0x7fe3cf8339d0, 0)                                               = 5967
<... fork resumed> )                                                                        = 5967
puts("\nI am parent" <unfinished ...>
SYS_fstat(1, 0x7fff47008060)                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff
)                                                        = 0x7fe3cf84e000
I am child
SYS_write(1, "\n", 1
)                                                                       = 1
SYS_write(1, "I am parent\n", 12)                                                           = -512
--- SIGCHLD (Child exited) ---
SYS_write(1, "I am parent\n", 12I am parent
)                                                           = 12
<... puts resumed> )                                                                        = 13
SYS_exit_group(13 <no return ...>
+++ exited (status 13) +++

สิ่งนี้อาจมีประโยชน์สำหรับคุณ: lxr.linux.no/linux+v3.10.9
เล่นซ้ำ

@ mauro.stettler ฉันหาไม่พบใน lxr
user3539

คุณหมายถึงgit.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ …รอบ ๆ บรรทัด 1700 หรือไม่ สิ่งที่คุณหวังที่จะหา
msw

คำตอบ:


29

The fork()และvfork()wrappers ใน glibc ถูกใช้งานผ่านการclone()เรียกของระบบ เพื่อให้เข้าใจความสัมพันธ์ระหว่างfork()และclone()เราต้องพิจารณาความสัมพันธ์ระหว่างกระบวนการและเธรดใน Linux

ตามเนื้อผ้าfork()จะเผยแพร่ทรัพยากรทั้งหมดที่เป็นของกระบวนการหลักและมอบหมายสำเนาให้กับกระบวนการย่อย วิธีการนี้ incurs exec()ค่าใช้จ่ายเป็นจำนวนมากซึ่งทั้งหมดอาจจะเพื่ออะไรถ้าเด็กสายทันที ใน Linux fork()ใช้ประโยชน์จากเพจที่เขียนเพื่อเขียนเพื่อหน่วงเวลาหรือหลีกเลี่ยงการคัดลอกข้อมูลที่สามารถใช้ร่วมกันระหว่างกระบวนการหลักและลูก ดังนั้นค่าโสหุ้ยเพียงอย่างเดียวที่เกิดขึ้นในระหว่างการปกติfork()คือการคัดลอกตารางหน้าของผู้ปกครองและการกำหนดโครงสร้างตัวบอกกระบวนการที่ไม่ซ้ำกันtask_structสำหรับเด็ก

ลินุกซ์ยังใช้วิธีการที่ยอดเยี่ยมในการเธรด ใน Linux เธรดเป็นเพียงกระบวนการทั่วไปที่เกิดขึ้นเพื่อแบ่งปันทรัพยากรบางอย่างกับกระบวนการอื่น นี่เป็นวิธีการที่แตกต่างกันอย่างสิ้นเชิงกับเธรดเมื่อเทียบกับระบบปฏิบัติการอื่นเช่น Windows หรือ Solaris ที่กระบวนการและเธรดเป็นสัตว์ชนิดต่าง ๆ โดยสิ้นเชิง ในลีนุกซ์แต่ละเธรดมีสามัญtask_structของตนเองซึ่งเพิ่งเกิดขึ้นเพื่อเซ็ตอัพในแบบที่มันแชร์ทรัพยากรบางอย่างเช่นพื้นที่ที่อยู่ด้วยกระบวนการพาเรนต์

flagsพารามิเตอร์ของclone()ระบบโทรรวมถึงชุดของธงที่แสดงทรัพยากรซึ่งถ้ามีผู้ปกครองและเด็กกระบวนการควรแบ่งปัน กระบวนการและหัวข้อมีทั้งที่สร้างขึ้นผ่านทางที่แตกต่างเพียงอย่างเดียวคือชุดของค่าสถานะที่ถูกส่งไปยังclone()clone()

ปกติfork()สามารถนำมาใช้เป็น:

clone(SIGCHLD, 0);

สิ่งนี้จะสร้างงานที่ไม่แชร์ทรัพยากรใด ๆ กับพาเรนต์และตั้งค่าให้ส่งSIGCHLDสัญญาณการเลิกจ้างไปยังพาเรนต์เมื่อออก

ในทางตรงกันข้ามงานที่ใช้พื้นที่ที่อยู่ทรัพยากรระบบไฟล์ตัวอธิบายไฟล์และตัวจัดการสัญญาณกับผู้ปกครองในคำอื่น ๆด้ายสามารถสร้างด้วย:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

vfork()ในทางกลับกันจะดำเนินการผ่านCLONE_VFORKธงแยกซึ่งจะทำให้กระบวนการหลักที่จะนอนหลับจนกว่ากระบวนการเด็กปลุกด้วยสัญญาณ เด็กจะเป็นเธรดเดียวของการดำเนินการในเนมสเปซของผู้ปกครองจนกว่าจะมีการเรียกexec()หรือออก เด็กไม่ได้รับอนุญาตให้เขียนไปยังหน่วยความจำ การclone()เรียกที่สอดคล้องกันอาจเป็นดังนี้:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

การดำเนินงานของsys_clone()สถาปัตยกรรมเฉพาะ แต่เป็นกลุ่มของการทำงานที่เกิดขึ้นในที่กำหนดไว้ในdo_fork() kernel/fork.cฟังก์ชันนี้เรียกใช้สแตติกclone_process()ซึ่งสร้างกระบวนการใหม่เป็นสำเนาของพาเรนต์ แต่ยังไม่เริ่ม clone_process()สำเนาลงทะเบียนที่กำหนด PID กับงานใหม่และทั้ง dublicates flagsหรือหุ้นชิ้นส่วนที่เหมาะสมของสภาพแวดล้อมการดำเนินการตามที่ระบุโดยโคลน เมื่อclone_process()ส่งคืนdo_clone()จะปลุกกระบวนการที่สร้างขึ้นใหม่และกำหนดเวลาให้ทำงาน


2
+1 คำอธิบายที่ดีเกี่ยวกับความสำคัญของclone()ความสัมพันธ์กับเธรดและส้อม
goldilocks


2

องค์ประกอบที่รับผิดชอบในการแปลฟังก์ชั่นการโทรของระบบ userland เป็นการเรียกระบบเคอร์เนลภายใต้ Linux คือ libc ใน GLibC ไลบรารี NPTL จะเปลี่ยนเส้นทางไปยังการclone(2)เรียกของระบบ

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