Apakah utas disalin saat memanggil garpu?

31

Jika saya memiliki program yang berjalan dengan utas dan memanggil fork()sistem berbasis unix, apakah utas disalin? Saya tahu bahwa memori virtual untuk proses saat ini disalin 1: 1 ke proses baru yang dihasilkan. Saya tahu bahwa utas memiliki tumpukan mereka sendiri dalam memori virtual suatu proses. Jadi, setidaknya tumpukan utas juga harus disalin. Namun, saya tidak tahu apakah ada sesuatu yang lebih untuk utas yang tidak berada dalam memori virtual dan karenanya TIDAK disalin. Jika tidak, apakah kedua proses berbagi utas atau apakah itu salinan independen?

Jean-Baptiste Yunès
sumber

Jawaban:

29

Tidak.

Utas tidak disalin pada fork(). Spesifikasi POSIX mengatakan (menekankan milikku):

garpu - buat proses baru

Suatu proses harus dibuat dengan satu utas . Jika proses multi-utas memanggil fork (), proses baru harus berisi replika utas panggilan dan seluruh ruang alamatnya, mungkin termasuk status mutex dan sumber daya lainnya. Akibatnya, untuk menghindari kesalahan, proses anak hanya dapat menjalankan operasi async-signal-safe sampai saat salah satu fungsi exec dipanggil.

Untuk menghindari masalah ini, ada pthread_atfork()fungsi untuk membantu.

Jean-Baptiste Yunès
sumber
7

garpu pria :

Proses anak dibuat dengan satu utas — yang disebut fork (). Seluruh ruang alamat virtual induk direplikasi dalam anak, termasuk keadaan mutex, variabel kondisi, dan objek pthreads lainnya; penggunaan pthread_atfork (3) dapat membantu untuk mengatasi masalah yang dapat menyebabkan ini.

kaylum
sumber
Tapi itu tampak aneh: Mengapa tumpukan untuk utas dalam proses memanggil garpu disalin jika utas sebenarnya (yang saya tidak tahu berisi penyimpanan di tempat lain selain memori virtual) tidak?
Nah mengapa itu adalah pertanyaan yang berbeda sama sekali. Saya tidak tahu keputusan desain asli yang menyebabkan implementasi itu. Jika Anda tertarik, Anda harus menanyakannya sebagai pertanyaan terpisah.
kaylum
@dip tetapi tumpukan utas lainnya tidak disalin, siapa bilang?
Jean-Baptiste Yunès
1
@ Jean-BaptisteYunès Dalam sistem unix, ada sebuah struct yang mewakili memori virtual untuk suatu proses. Itu yang disalin. Bukan hanya tumpukan dan bss
6
Anda mendapatkan seluruh ruang memori - dan karenanya tumpukan semua utas. Anda memerlukannya karena tidak ada batasan tempat penunjuk yang tinggal di tumpukan (atau memori statis) yang dapat diakses oleh utas yang tersisa menunjuk - mereka bisa saja menunjuk ke data yang hidup di tumpukan ulir dalam proses aslinya
davidbak
4

Dari Spesifikasi Open Group Base Edisi 7, fork edisi 2018 :

Suatu proses harus dibuat dengan satu utas. Jika proses multi-utas memanggil fork () , proses baru harus berisi replika utas panggilan dan seluruh ruang alamatnya, mungkin termasuk status mutex dan sumber daya lainnya. Akibatnya, untuk menghindari kesalahan, proses anak hanya dapat menjalankan operasi async-signal-safe sampai saat salah satu fungsi exec dipanggil.

Ketika aplikasi memanggil fork () dari penangan sinyal dan salah satu dari penangan fork yang terdaftar oleh pthread_atfork () memanggil fungsi yang tidak aman-async-signal-safe, perilaku tidak terdefinisi.

Ian Abbott
sumber
-2

Awalnya, "garpu" dicapai dengan menulis tugas ke disk dan kemudian, daripada membaca di utas yang berbeda (yang akan dilakukan jika bertukar tugas dengan yang berbeda), memodifikasi ID tugas gambar masih dalam memori dan melanjutkan dengan eksekusi (sebagai tugas baru). Ini adalah modifikasi yang sangat sederhana untuk mekanisme switching tugas dasar, di mana hanya satu tugas yang akan menempati memori RAM pada suatu waktu.

Tentu saja, ketika manajemen memori menjadi lebih rumit, skema ini dimodifikasi agar sesuai dengan lingkungan baru.

Hot Licks
sumber
Ingin tahu mengapa ini tidak dipilih. Ini adalah cara Unix melakukannya.
Hot Licks
Ini adalah wawasan yang menarik, tetapi di mana ia menyebutkan utas? Tidak terlihat seperti jawaban untuk saya.
wastl