Setiap contoh program yang sedang berjalan dikenal sebagai proses. Konsep proses merupakan hal mendasar bagi sistem operasi UNIX / Linux. Sebuah proses memiliki identitasnya sendiri dalam bentuk PID atau ID proses. PID untuk setiap proses ini unik di seluruh sistem operasi. Juga, setiap proses memiliki ruang alamat prosesnya sendiri di mana segmen memori seperti segmen kode, segmen data, segmen tumpukan dll ditempatkan. Konsep proses sangat luas dan dapat secara luas diklasifikasikan ke dalam pembuatan proses, eksekusi proses dan penghentian proses.
Linux Processes Series:part 1, part 2, part 3, part 4 (artikel ini).
Pada artikel ini kita akan berkonsentrasi pada aspek pembuatan proses dari sudut pandang pemrograman. Kami akan fokus pada fungsi fork() dan memahami cara kerjanya.
Fungsi garpu()
Fungsi fork() digunakan untuk membuat proses baru dengan menduplikasi proses yang sudah ada yang memanggilnya. Proses yang ada dari mana fungsi ini dipanggil menjadi proses induk dan proses yang baru dibuat menjadi proses anak. Seperti yang telah dinyatakan bahwa anak adalah salinan duplikat dari orang tua tetapi ada beberapa pengecualian untuk itu.
- Anak memiliki PID unik seperti proses lain yang berjalan di sistem operasi.
- Anak memiliki ID proses induk yang sama dengan PID dari proses yang membuatnya.
- Penggunaan sumber daya dan penghitung waktu CPU disetel ulang ke nol dalam proses turunan.
- Set sinyal tertunda di anak kosong.
- Anak tidak mewarisi pengatur waktu dari induknya
Perhatikan bahwa daftar di atas tidak lengkap. Ada banyak poin yang disebutkan di halaman manual fork(). Saya sangat menyarankan pembaca artikel ini untuk membaca poin-poin tersebut di halaman manual fungsi fork().
Tipe Pengembalian
Fork() memiliki perilaku yang menarik saat kembali ke metode pemanggilan. Jika fungsi fork() berhasil maka akan kembali dua kali. Setelah kembali dalam proses anak dengan nilai kembali '0' dan kemudian kembali dalam proses induk dengan PID anak sebagai nilai kembali. Perilaku ini karena fakta bahwa setelah fork dipanggil, proses turunan dibuat dan karena proses turunan berbagi segmen teks dengan proses induk dan melanjutkan eksekusi dari pernyataan berikutnya di segmen teks yang sama, maka fork kembali dua kali (sekali di induk dan sekali pada anak).
Contoh Fork C
Mari kita ambil contoh untuk menggambarkan penggunaan fungsi garpu.
#include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> int var_glb; /* A global variable*/ int main(void) { pid_t childPID; int var_lcl = 0; childPID = fork(); if(childPID >= 0) // fork was successful { if(childPID == 0) // child process { var_lcl++; var_glb++; printf("\n Child Process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb); } else //Parent process { var_lcl = 10; var_glb = 20; printf("\n Parent process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb); } } else // fork failed { printf("\n Fork failed, quitting!!!!!!\n"); return 1; } return 0; }
Pada kode di atas :
- Variabel lokal dan global (var_lcl dan var_glb ) dideklarasikan dan diinisialisasi dengan nilai '0'
- Selanjutnya fungsi fork() dipanggil dan nilai kembaliannya disimpan dalam variabel childPID.
- Sekarang, nilai childPID diperiksa untuk memastikan bahwa fungsi fork() lulus.
- Selanjutnya berdasarkan nilai childPID, kode parent dan child dieksekusi.
- Satu hal yang perlu diperhatikan di sini adalah mengapa variabel var_lcl dan var_glb digunakan?
- Mereka digunakan untuk menunjukkan bahwa proses anak dan induk bekerja pada salinan terpisah dari variabel-variabel ini.
- Nilai terpisah dari variabel-variabel ini digunakan untuk menunjukkan fakta yang disebutkan di atas.
- Di linux, mekanisme copy-on-write digunakan di mana-baik anak dan orang tua tetap bekerja pada salinan variabel yang sama sampai salah satu dari mereka mencoba mengubah nilainya.
- Setelah percabangan, apakah anak yang akan dijalankan terlebih dahulu atau orang tua bergantung pada penjadwal.
Sekarang, ketika kode di atas dikompilasi dan dijalankan :
$ ./fork Parent process :: var_lcl = [10], var_glb[20] Child Process :: var_lcl = [1], var_glb[1]
Kami melihat bahwa pada output di atas, proses anak dan induk dijalankan dan log menunjukkan nilai var_lcl dan var_glb yang terpisah. Ini menyimpulkan bahwa orang tua dan anak memiliki salinan var_lcl dan var_glb mereka sendiri.
CATATAN:Fungsi getpid() dapat digunakan untuk mengambil ID proses dari proses pemanggilan dan fungsi getppid() dapat digunakan untuk mengambil PID dari proses induk.