Saya mencoba membuat daemon dengan python. Saya telah menemukan pertanyaan berikut , yang memiliki beberapa sumber daya bagus di dalamnya yang sedang saya ikuti, tetapi saya ingin tahu mengapa garpu ganda diperlukan. Saya telah menjelajahi Google dan menemukan banyak sumber daya yang menyatakan bahwa itu perlu, tetapi tidak mengapa.
Beberapa menyebutkan bahwa itu untuk mencegah daemon dari memperoleh terminal pengendali. Bagaimana cara melakukan ini tanpa garpu kedua? Apa akibatnya?
fork()
panggilan mengembalikan PID anak ke orang tua, sehingga mudah untuk mendapatkan PID dari proses anak, tetapi tidak begitu mudah untuk dapatkan PID dari proses cucu ).Jawaban:
Melihat kode yang dirujuk dalam pertanyaan, pembenarannya adalah:
Jadi itu adalah untuk memastikan bahwa daemon di-parented kembali ke init (kalau-kalau proses menendang daemon itu berumur panjang), dan menghilangkan kemungkinan daemon mendapatkan kembali tty kontrol. Jadi, jika tidak satu pun dari kasus ini berlaku, maka satu garpu harus cukup. " Pemrograman Jaringan Unix - Stevens " memiliki bagian yang bagus tentang ini.
sumber
p=fork(); if(p) exit(); setsid()
. Dalam hal ini, orang tua juga keluar dan proses anak pertama diperbaiki. Sihir garpu ganda hanya diperlukan untuk mencegah daemon memperoleh tty.forks
suatuchild
proses, proses anak pertama ini akan menjadisession leader
dan akan dapat membuka terminal TTY. Tetapi jika saya bercabang lagi dari anak ini dan mengakhiri anak pertama ini, anak bercabang kedua tidak akan menjadisession leader
dan tidak akan dapat membuka terminal TTY. Apakah pernyataan ini benar?setsid()
. Jadi, proses bercabang pertama menjadi pemimpin sesi setelah memanggilsetsid()
dan kemudian kami bercabang lagi sehingga proses, bercabang ganda terakhir tidak lagi menjadi pemimpin sesi. Selain persyaratansetsid()
untuk menjadi pemimpin sesi, Anda tepat.Saya mencoba memahami garpu ganda dan menemukan pertanyaan ini di sini. Setelah banyak penelitian, inilah yang saya temukan. Semoga ini akan membantu memperjelas hal-hal yang lebih baik bagi siapa pun yang memiliki pertanyaan yang sama.
Di Unix setiap proses milik grup yang pada gilirannya milik sesi. Inilah hierarki ...
Sesi (SID) → Grup Proses (PGID) → Proses (PID)
Proses pertama dalam grup proses menjadi pemimpin grup proses dan proses pertama dalam sesi menjadi pemimpin sesi. Setiap sesi dapat memiliki satu TTY yang terkait dengannya. Hanya pemimpin sesi yang bisa mengendalikan TTY. Agar suatu proses benar-benar di-daemonisasi (dijalankan di latar belakang) kita harus memastikan bahwa ketua sesi terbunuh sehingga tidak ada kemungkinan sesi tersebut pernah mengambil kendali atas TTY.
Saya menjalankan program contoh daemon python Sander Marechal dari situs ini di Ubuntu saya. Inilah hasilnya dengan komentar saya.
Perhatikan bahwa prosesnya adalah pemimpin sesi setelah itu
Decouple#1
, karena ituPID = SID
. Itu masih bisa mengendalikan TTY.Perhatikan bahwa
Fork#2
tidak lagi pemimpin sesiPID != SID
. Proses ini tidak pernah bisa mengendalikan TTY. Benar-benar dianemonisasi.Saya pribadi menemukan istilah garpu-dua kali membingungkan. Ungkapan yang lebih baik mungkin fork-decouple-fork.
Tautan minat tambahan:
sumber
fork()
sudah mencegah pembuatan zombie, asalkan Anda menutup induknya.setsid()
sebelum satufork()
? Sebenarnya saya kira jawaban dari pertanyaan ini adalah jawabannya.Sebenarnya, garpu ganda tidak ada hubungannya dengan mengasuh kembali daemon sebagai anak
init
. Semua yang diperlukan untuk menjadi orang tua kembali anak adalah bahwa orang tua harus keluar. Ini dapat dilakukan dengan hanya satu garpu. Selain itu, melakukan double-fork dengan sendirinya tidak menjadi proses ulang daemoninit
; orang tua daemon harus keluar. Dengan kata lain, orang tua selalu keluar saat forking daemon yang tepat sehingga proses daemon di-parent kembaliinit
.Jadi mengapa garpu ganda? POSIX.1-2008 Bagian 11.1.3, " The Controlling Terminal ", memiliki jawabannya (penekanan ditambahkan):
Ini memberitahu kita bahwa jika proses daemon melakukan sesuatu seperti ini ...
... maka proses daemon mungkin diperoleh
/dev/console
sebagai terminal pengendali, tergantung pada apakah proses daemon adalah pemimpin sesi, dan tergantung pada implementasi sistem. Program dapat menjamin bahwa panggilan di atas tidak akan mendapatkan terminal pengendali jika program pertama memastikan bahwa itu bukan pemimpin sesi.Biasanya, ketika meluncurkan daemon,
setsid
dipanggil (dari proses anak setelah memanggilfork
) untuk memisahkan daemon dari terminal pengendali. Namun, panggilansetsid
juga berarti bahwa proses panggilan akan menjadi pemimpin sesi sesi baru, yang membuka kemungkinan bahwa daemon dapat memperoleh kembali terminal pengendali. Teknik garpu ganda memastikan bahwa proses daemon bukan pemimpin sesi, yang kemudian menjamin bahwa panggilan untukopen
, seperti dalam contoh di atas, tidak akan mengakibatkan proses daemon mendapatkan kembali terminal pengendali.Teknik garpu ganda agak paranoid. Mungkin tidak perlu jika Anda tahu bahwa daemon tidak akan pernah membuka file perangkat terminal. Juga, pada beberapa sistem mungkin tidak diperlukan bahkan jika daemon benar-benar membuka file perangkat terminal, karena perilaku itu didefinisikan oleh implementasi. Namun, satu hal yang tidak didefinisikan implementasi adalah bahwa hanya pemimpin sesi yang dapat mengalokasikan terminal pengendali. Jika suatu proses bukan pemimpin sesi, itu tidak dapat mengalokasikan terminal pengendali. Oleh karena itu, jika Anda ingin menjadi paranoid dan memastikan bahwa proses daemon tidak dapat secara tidak sengaja memperoleh terminal pengendali, terlepas dari implementasi spesifik yang ditentukan, maka teknik garpu ganda sangat penting.
sumber
LogFile=/dev/console
. Program tidak selalu memiliki kontrol waktu kompilasi atas file mana yang mungkin dibuka;)Diambil dari Bad CTK :
"Pada beberapa rasa Unix, kamu terpaksa melakukan double-fork saat startup, untuk masuk ke mode daemon. Ini karena forking tunggal tidak dijamin untuk terlepas dari terminal pengendali."
sumber
setsid
setelah fork awal. Ini kemudian memastikan bahwa ia tetap terlepas dari terminal pengendali dengan bercabang lagi dan meminta ketua sesi (proses yang disebutsetsid
) keluar.fork
itu terlepas dari terminal pengendali. Itusetsid
yang melakukannya. Tetapisetsid
akan gagal jika dipanggil dari pemimpin grup proses. Jadi inisialfork
harus dilakukan sebelumnyasetsid
untuk memastikan yangsetsid
dipanggil dari proses yang bukan pemimpin grup proses. Yang keduafork
memastikan bahwa proses akhir (yang akan menjadi daemon) bukan pemimpin sesi. Hanya pemimpin sesi yang dapat memperoleh terminal pengendali, jadi garpu kedua ini menjamin bahwa daemon tidak akan secara tidak sengaja mendapatkan kembali terminal pengendali. Ini berlaku untuk OS POSIX apa pun.Menurut "Pemrograman Lanjutan di Lingkungan Unix", oleh Stephens dan Rago, garpu kedua lebih merupakan rekomendasi, dan itu dilakukan untuk menjamin bahwa daemon tidak memperoleh terminal pengendali pada sistem berbasis sistem V.
sumber
Salah satu alasannya adalah bahwa proses induk dapat segera wait_pid () untuk anak, dan kemudian melupakannya. Ketika cucu itu meninggal, orang tuanya adalah init, dan ia akan menunggu () untuk itu - dan membawanya keluar dari keadaan zombie.
Hasilnya adalah bahwa proses induk tidak perlu mewaspadai anak-anak bercabang, dan itu juga memungkinkan untuk memotong proses yang berjalan lama dari libs dll.
sumber
Panggilan daemon () memiliki panggilan induk _exit () jika berhasil. Motivasi asli mungkin untuk memungkinkan orang tua melakukan beberapa pekerjaan ekstra saat anak melakukan dasemonisasi.
Ini juga mungkin didasarkan pada kepercayaan yang salah bahwa itu diperlukan untuk memastikan daemon tidak memiliki proses induk dan diulangi untuk init - tetapi ini akan tetap terjadi begitu orang tua meninggal dalam kasus garpu tunggal.
Jadi saya kira itu semua hanya bermuara pada tradisi pada akhirnya - garpu tunggal sudah cukup selama orang tua meninggal dalam waktu singkat.
sumber
Diskusi yang layak tampaknya di http://www.developerweb.net/forum/showthread.php?t=3025
Mengutip mlampkin dari sana:
sumber
Mungkin lebih mudah dipahami dengan cara ini:
sumber