Ketika ltrace digunakan untuk melacak panggilan sistem, saya bisa melihat bahwa fork () menggunakan sys_clone () daripada sys_fork (). Tapi saya tidak bisa menemukan sumber linux di mana ia didefinisikan.
Program saya adalah
#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");
}
Dan output ltrace adalah
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) +++
linux
linux-kernel
system-calls
trace
ltrace
user3539
sumber
sumber
Jawaban:
The
fork()
danvfork()
pembungkus di glibc dilaksanakan melaluiclone()
system call. Untuk lebih memahami hubungan antarafork()
danclone()
, kita harus mempertimbangkan hubungan antara proses dan utas di Linux.Secara tradisional,
fork()
akan mempublikasikan semua sumber daya yang dimiliki oleh proses induk dan menetapkan salinan untuk proses anak. Pendekatan ini menimbulkan biaya overhead yang besar, yang semuanya mungkin sia-sia jika anak itu segera meneleponexec()
. Di Linux,fork()
menggunakan halaman copy-on-write untuk menunda atau sama sekali menghindari menyalin data yang dapat dibagi antara proses induk dan anak. Dengan demikian, satu-satunya overhead yang dikeluarkan selama normalfork()
adalah menyalin tabel halaman induk dan penugasan struct deskriptor proses yang uniktask_struct
,, untuk anak.Linux juga mengambil pendekatan yang luar biasa untuk utas. Di Linux, utas hanyalah proses biasa yang berbagi sumber daya dengan proses lain. Ini adalah pendekatan yang sangat berbeda untuk utas dibandingkan dengan sistem operasi lain seperti Windows atau Solaris, di mana proses dan utas adalah jenis binatang yang sama sekali berbeda. Di Linux, setiap utas memiliki kebiasaan
task_struct
sendiri yang kebetulan diatur sedemikian rupa sehingga berbagi sumber daya tertentu, seperti ruang alamat, dengan proses induk.The
flags
parameterclone()
system call mencakup seperangkat bendera yang menunjukkan mana sumber daya, jika ada, proses orangtua dan anak harus berbagi. Proses dan utas sama-sama dibuat melaluiclone()
, satu-satunya perbedaan adalah set bendera yang diteruskan keclone()
.Normal
fork()
dapat diimplementasikan sebagai:Ini menciptakan tugas yang tidak membagikan sumber daya apa pun dengan induknya, dan diatur untuk mengirim
SIGCHLD
sinyal terminasi ke induk ketika ia keluar.Sebaliknya, tugas yang berbagi ruang alamat, sumber daya sistem file, deskriptor file dan penangan sinyal dengan induknya, dengan kata lain utas , dapat dibuat dengan:
vfork()
pada gilirannya diimplementasikan melaluiCLONE_VFORK
bendera terpisah , yang akan menyebabkan proses induk tidur sampai proses anak membangunkannya melalui sinyal. Anak akan menjadi satu-satunya utas eksekusi di ruang nama orang tua, sampai panggilanexec()
atau keluar. Anak tidak diperbolehkan menulis ke memori.clone()
Panggilan yang sesuai bisa sebagai berikut:Implementasi
sys_clone()
adalah arsitektur spesifik, tetapi sebagian besar pekerjaan terjadi dido_fork()
didefinisikan dalamkernel/fork.c
. Fungsi ini memanggil statisclone_process()
, yang menciptakan proses baru sebagai salinan dari induknya, tetapi belum memulainya.clone_process()
menyalin register, menetapkan PID untuk tugas baru, dan baik mempublikasikan atau berbagi bagian yang sesuai dari lingkungan proses seperti yang ditentukan oleh klonflags
. Ketikaclone_process()
kembali,do_clone()
akan membangunkan proses yang baru dibuat dan menjadwalkannya untuk berjalan.sumber
clone()
kaitan dengan utas dan garpu.Komponen yang bertanggung jawab untuk menerjemahkan fungsi-fungsi panggilan sistemlandland menjadi panggilan sistem kernel di Linux adalah libc. Dalam GLibC, perpustakaan NPTL mengarahkan ini ke
clone(2)
panggilan sistem.sumber