Kapan harus memanggil fork () dan exec () sendiri?

9

Saya belajar tentang perintah fork () dan exec (). Sepertinya fork () dan exec () biasanya dipanggil bersama. (fork () membuat proses anak baru, dan exec () menggantikan gambar proses saat ini dengan yang baru.) Namun, dalam skenario apa Anda dapat memanggil masing-masing fungsi sendiri? Apakah ada skenario seperti ini?

quil
sumber
2
Forkbomb tradisional: while (1) fork (); untuk sumber daya sistem babi.
Joshua

Jawaban:

22

Tentu! Pola umum dalam program "wrapper" adalah melakukan berbagai hal dan kemudian menggantinya dengan beberapa program lain hanya dengan execpanggilan (tanpa garpu)

#!/bin/sh
export BLAH_API_KEY=blub
...
exec /the/thus/wrapped/program "$@"

Contoh nyata dari ini adalah GIT_SSH(meskipun git(1)juga menawarkan GIT_SSH_COMMANDjika Anda tidak ingin melakukan metode program pembungkus di atas).

Fork-only digunakan ketika memunculkan sekelompok proses yang biasanya dikerjakan oleh pekerja (mis. Apache httpddalam mode fork (meskipun fork-only lebih baik untuk proses yang perlu membakar CPU dan bukan yang mengutak-atik ibu jari mereka menunggu jaringan I / O terjadi) ) atau untuk pemisahan hak istimewa yang digunakan oleh sshddan program lain di OpenBSD (tidak ada eksekutif)

$ doas pkg_add pstree
...
$ pstree | grep sshd
 |-+= 70995 root /usr/sbin/sshd
 | \-+= 28571 root sshd: jhqdoe [priv] (sshd)
 |   \-+- 14625 jhqdoe sshd: jhqdoe@ttyp6 (sshd)

The rootsshd telah pada klien connect bercabang off salinan dirinya (28.571) dan kemudian salinan lain (14.625) untuk pemisahan hak istimewa.

thrig
sumber
14

Ada banyak.

Program yang memanggil fork()tanpa exec()biasanya mengikuti pola pemijahan anak pekerja proses untuk melakukan berbagai tugas dalam proses terpisah untuk yang utama. Anda akan menemukan ini di program beragam seperti dhclient, php-fpm, dan urxvtd.

Suatu program yang memanggil exec()tanpa fork()adalah pemuatan berantai , melapisi prosesnya dengan gambar program yang berbeda. Ada seluruh subkultur utilitas pemuatan rantai yang melakukan hal-hal tertentu untuk memproses keadaan dan kemudian menjalankan program lain untuk dijalankan dengan keadaan proses yang direvisi. Utilitas seperti itu biasa terjadi pada keluarga daemontools dari layanan dan tool manajemen sistem, tetapi tidak terbatas pada itu saja. Beberapa contoh:

Toolsets daemontools keluarga memiliki banyak alat-alat tersebut, dari machineenvmelalui find-matching-jvmke runtool.

JdeBP
sumber
2

Selain jawaban lain, debugger, menggunakan ptrace, biasanya memanfaatkan celah antara forkdan exec. Seorang debuggee harus menandai dirinya sendiri PTRACE_TRACEMEuntuk menunjukkan bahwa ia sedang dilacak oleh proses induknya - debugger. Ini untuk memberikan izin yang diperlukan kepada debugger.

Jadi seorang debugger pertama-tama akan melakukan fork sendiri. Anak akan memanggil ptracedengan PTRACE_TRACEMEdan kemudian memanggil exec. Program apa pun yang dijalankan oleh eksekutif anak sekarang dapat dilacak oleh orang tua.

bytefire
sumber
Ada banyak contoh melakukan hal-hal antara fork dan exec, yang paling umum adalah mengarahkan I / O (misalnya menyiapkan pipa). Tetapi pertanyaannya adalah tentang melakukan garpu tanpa eksekutif sama sekali.
Barmar
0

exec tanpa garpu

Setidaknya ada dua alasan mengapa Anda ingin melakukan hal seperti itu:

  1. Memuat rantai. Gambar proses saat ini diganti dengan sesuatu yang berbeda.
  2. Mulai ulang program yang sedang berjalan (misalnya, bisa terjadi ketika Anda SIGHUP atau proses server semacam itu, memuat ulang semuanya dan melakukan awal yang benar-benar baru). Dalam beberapa cara, orang dapat berargumen ini adalah pemuatan rantai, hanya secara kebetulan dengan program yang sama.

garpu tanpa exec

Itulah yang dilakukan setiap daemon setiap kali dimulai (dua kali, memang). Ini melakukan beberapa hal, di antaranya shell tidak menggantung (karena proses asli bahwa shell menunggu berakhir) dan daemon tidak lagi dikendalikan oleh terminal, jadi menutup jendela shell tidak membunuh daemon.

Penggunaan umum lainnya adalah forking pekerja anak-anak, yang dipopulerkan oleh server web apache sekitar 25 tahun yang lalu (saat ini ini tidak dianggap canggih karena sangat rentan terhadap masalah kawanan petir, tapi itu pasti memberikan sangat sederhana, server paling kuat mungkin).

Namun penggunaan umum lainnya adalah untuk membuat snapshot yang konsisten. forktidak hanya menciptakan proses, tetapi juga menyalin (secara teori, pada kenyataannya itu hanya menandai halaman copy-on-write) ruang alamat. Ini (secara atomis) membuat snapshot dari data program lengkap yang tidak dapat diubah lagi oleh induknya.
Beberapa program memanfaatkannya. Misalnya redis menyimpan data ke disk (dalam kondisi yang konsisten) sementara pada saat yang sama memodifikasi set data secara bersamaan. Ini hanya berfungsi karena forkmembuat snapshot yang konsisten yang tidak melihat modifikasi yang dibuat oleh proses induk.

Damon
sumber
Ini sebenarnya sangat sedikit demon saat ini, dengan sebagian besar tidak melakukan ini sebagai standar atau memiliki mode yang umum digunakan untuk tidak melakukannya. Ini adalah kesalahan untuk bercabang yang mengarah ke ketidakcocokan kesiapan dan kengerian , dan merupakan salah satu kesalahan dari kesalahan dmonmonisasi . Kesalahan ini akhirnya tidak disukai lagi.
JdeBP