GNU/Linux >> Belajar Linux >  >> Linux

Apa yang terjadi ketika sebuah benang bercabang?

Proses baru akan menjadi anak dari utas utama yang membuat utas. Saya pikir.

fork menciptakan proses baru. Induk dari suatu proses adalah proses lain, bukan utas. Jadi induk dari proses baru adalah proses lama.

Perhatikan bahwa proses anak hanya akan memiliki satu utas karena fork hanya menggandakan (tumpukan untuk) utas yang memanggil fork . (Ini tidak sepenuhnya benar:seluruh memori digandakan, tetapi proses anak hanya akan memiliki satu utas aktif.)

Jika induknya selesai terlebih dahulu, proses baru akan dilampirkan ke proses init.

Jika orang tua menyelesaikan SIGHUP terlebih dahulu sinyal dikirim ke anak. Jika anak tidak keluar sebagai akibat dari SIGHUP itu akan mendapatkan init sebagai induk barunya. Lihat juga halaman manual untuk nohup dan signal(7) untuk informasi lebih lanjut tentang SIGHUP .

Dan induknya adalah utas utama, bukan utas yang membuatnya.

Induk dari suatu proses adalah proses, bukan utas khusus, jadi tidak masuk akal untuk mengatakan bahwa utas utama atau anak adalah induknya. Seluruh proses adalah orang tua.

Satu catatan terakhir:Mencampur benang dan garpu harus dilakukan dengan hati-hati. Beberapa jebakan dibahas di sini.


Koreksi saya jika saya salah.

Akan dilakukan :)

Sebagai fork() adalah panggilan sistem POSIX, perilakunya didefinisikan dengan baik:

Sebuah proses harus dibuat dengan satu utas . Jika proses multi-utas memanggil fork(), proses baru harus berisi replika utas pemanggil dan seluruh ruang alamatnya, mungkin termasuk status mutex dan sumber daya lainnya. Akibatnya, untuk menghindari kesalahan, proses anak hanya dapat menjalankan operasi aman sinyal asinkron hingga salah satu fungsi exec dipanggil.

https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html

Anak bercabang adalah duplikat persis dari induknya, namun hanya utas yang disebut fork() di induk, masih ada di anak dan merupakan utas utama baru dari anak tersebut hingga Anda memanggil exec() .

Deskripsi POSIX "harus dibuat dengan satu utas" menyesatkan karena pada kenyataannya sebagian besar implementasi akan benar-benar membuat duplikat yang tepat dari proses induk, sehingga semua utas lainnya dan memorinya juga digandakan, yang berarti utas tersebut sebenarnya ada di sana , mereka tidak dapat berjalan lagi karena sistem tidak pernah memberikan waktu CPU apa pun kepada mereka; mereka sebenarnya tidak ada di tabel penjadwal utas kernel.

Gambaran mental yang lebih mudah adalah sebagai berikut:

Saat induk memanggil fork, seluruh proses dibekukan sesaat, diduplikasi secara atomik, dan kemudian induk dicairkan secara keseluruhan, namun pada anak hanya satu utas yang disebut garpu yang dicairkan, yang lainnya tetap dibekukan.

Itulah mengapa tidak aman untuk melakukan panggilan sistem tertentu di antara fork() dan exec() seperti yang juga ditunjukkan oleh standar POSIX. Idealnya Anda tidak boleh melakukan lebih dari mungkin menutup atau menggandakan deskriptor file, menyetel atau memulihkan penangan sinyal, lalu memanggil exec() .


Namun, apa yang akan terjadi jika utas membuat proses baru menggunakan fork()?

Proses baru akan dibuat dengan menyalin utas panggilan ruang alamat (bukan seluruh ruang alamat dari proses ). Ini umumnya dianggap sebagai ide yang buruk karena sangat sulit untuk melakukannya dengan benar. POSIX mengatakan proses anak (dibuat dalam program multi-utas) hanya dapat memanggil fungsi async-signal-safe sampai memanggil salah satu dari exec* fungsi.

Jika induknya selesai terlebih dahulu, proses baru akan dilampirkan ke proses init.

Proses anak biasanya diwariskan oleh proses init. Jika proses induk adalah proses pengontrolan (misalnya shell), maka POSIX membutuhkan:

Jika prosesnya adalah proses pengontrolan, sinyal SIGHUP akan dikirim ke setiap proses di grup proses latar depan dari terminal pengontrol milik proses pemanggilan.

Namun, ini tidak berlaku untuk sebagian besar proses karena sebagian besar proses tidak mengendalikan proses.

Dan induknya adalah utas utama, bukan utas yang membuatnya.

Induk dari anak bercabang akan selalu menjadi proses yang disebut fork(). Jadi, PPID adalah proses anak yang akan menjadi PID program Anda.


masalah berasal dari perilaku fork(2) itu sendiri. Setiap kali proses anak baru dibuat dengan fork(2) proses baru mendapatkan ruang alamat memori baru tetapi semua yang ada di memori disalin dari proses lama (dengan copy-on-write itu tidak 100% benar, tetapi semantiknya sama).

Jika kita memanggil fork(2) dalam lingkungan multi-utas, utas yang melakukan panggilan sekarang menjadi utas utama dalam proses baru dan semua utas lainnya, yang berjalan dalam proses induk, mati. Dan semua yang mereka lakukan dibiarkan persis seperti sebelum panggilan ke fork(2).

Sekarang bayangkan bahwa utas lainnya dengan senang hati melakukan pekerjaannya sebelum panggilan ke fork (2) dan beberapa milidetik kemudian mereka mati. Bagaimana jika sesuatu yang sekarang sudah mati ini tidak dimaksudkan untuk ditinggalkan persis seperti sebelumnya?

Izinkan saya memberi Anda sebuah contoh. Katakanlah utas utama kami (yang akan memanggil garpu (2)) sedang tidur sementara kami memiliki banyak utas lainnya dengan senang hati melakukan beberapa pekerjaan. Mengalokasikan memori, menulis ke dalamnya, menyalin darinya, menulis ke file, menulis ke database, dan sebagainya. Mereka mungkin mengalokasikan memori dengan sesuatu seperti malloc(3). Nah, ternyata malloc(3) menggunakan mutex secara internal untuk menjamin keamanan benang. Dan justru inilah masalahnya.

Bagaimana jika salah satu utas ini menggunakan malloc (3) dan telah memperoleh kunci mutex pada saat yang sama persis dengan utas utama yang memanggil garpu (2)? Dalam proses anak baru, kunci masih dipegang - oleh utas yang sudah mati, yang tidak akan pernah mengembalikannya.

Proses anak baru tidak akan tahu apakah aman menggunakan malloc(3) atau tidak. Dalam kasus terburuk, itu akan memanggil malloc (3) dan memblokir sampai memperoleh kunci, yang tidak akan pernah terjadi, karena utas yang seharusnya mengembalikannya sudah mati. Dan ini hanya malloc(3). Pikirkan tentang semua mutex lain yang mungkin dan mengunci driver database, pustaka penanganan file, pustaka jaringan, dan sebagainya.

untuk penjelasan lengkapnya bisa melalui link ini.


Linux
  1. Linux – Apa Yang Terjadi Saat Anda Rsync Tanpa Jalur Tujuan??

  2. Apa Yang Terjadi Jika Batas Bandwidth Dilampaui?

  3. Apa itu proses yang tidak terputus?

  1. Apa yang harus dilakukan ketika Ctrl + C tidak dapat menghentikan proses?

  2. Kapan saya tidak boleh membunuh -9 proses?

  3. Ketika proses bercabang, apakah memori virtual atau residennya disalin?

  1. Linux – Kapan Saya Tidak Harus Membunuh -9 Proses?

  2. Apa yang terjadi saat mengirim SIGKILL ke Proses Zombie di Linux?

  3. Apa yang terjadi jika saya menghapus lost+found