Saya kira pertanyaan itu menjelaskan semuanya.
Saya ingin bercabang di Windows. Operasi apa yang paling mirip dan bagaimana cara menggunakannya.
Cygwin memiliki garpu berfitur lengkap () di Windows. Jadi jika menggunakan Cygwin dapat diterima untuk Anda, maka masalahnya teratasi jika kinerja kasus tidak menjadi masalah.
Jika tidak, Anda dapat melihat bagaimana Cygwin mengimplementasikan fork (). Dari dokumen arsitektur Cygwin yang cukup tua :
5.6. Proses Pembuatan Panggilan garpu di Cygwin sangat menarik karena tidak dipetakan dengan baik di atas Win32 API. Ini membuatnya sangat sulit untuk diterapkan dengan benar. Saat ini, percabangan Cygwin adalah implementasi non-copy-on-write yang mirip dengan yang ada di versi awal UNIX.
Hal pertama yang terjadi ketika proses orang tua membagi proses anak adalah bahwa orang tua menginisialisasi spasi dalam tabel proses Cygwin untuk anak tersebut. Ini kemudian membuat proses anak ditangguhkan menggunakan panggilan Win32 CreateProcess. Selanjutnya, proses induk memanggil setjmp untuk menyimpan konteksnya sendiri dan menetapkan penunjuk ke ini di area memori bersama Cygwin (dibagi di antara semua tugas Cygwin). Ini kemudian mengisi bagian .data dan .bss anak dengan menyalin dari ruang alamatnya sendiri ke ruang alamat anak yang ditangguhkan. Setelah ruang alamat anak diinisialisasi, anak dijalankan sementara orang tua menunggu di mutex. Anak tersebut menemukan bahwa ia telah bercabang dan longjump menggunakan buffer lompat yang disimpan. Anak itu kemudian menyetel mutex yang ditunggunya oleh induknya dan memblokirnya di mutex lain. Ini adalah sinyal bagi induk untuk menyalin tumpukan dan heap-nya ke dalam anak, setelah itu melepaskan mutex yang ditunggu oleh anak dan kembali dari panggilan fork. Akhirnya, anak tersebut terbangun dari pemblokiran pada mutex terakhir, membuat ulang area yang dipetakan memori yang diteruskan kepadanya melalui area bersama, dan kembali dari fork itu sendiri.
Meskipun kami memiliki beberapa ide tentang bagaimana mempercepat implementasi fork kami dengan mengurangi jumlah pengalih konteks antara proses induk dan anak, fork hampir pasti selalu tidak efisien di bawah Win32. Untungnya, dalam banyak situasi, keluarga panggilan yang disediakan oleh Cygwin dapat diganti dengan pasangan fork / exec dengan hanya sedikit usaha. Panggilan ini dipetakan dengan rapi di atas Win32 API. Hasilnya, mereka jauh lebih efisien. Mengubah program driver kompiler untuk memanggil spawn dan bukan fork adalah perubahan yang sepele dan meningkatkan kecepatan kompilasi sebesar dua puluh hingga tiga puluh persen dalam pengujian kami.
Namun, spawn dan exec menghadirkan kesulitan mereka sendiri. Karena tidak ada cara untuk melakukan eksekusi sebenarnya di bawah Win32, Cygwin harus menciptakan ID Proses (PID) sendiri. Akibatnya, ketika suatu proses melakukan beberapa panggilan exec, akan ada beberapa PID Windows yang terkait dengan satu Cygwin PID. Dalam beberapa kasus, rintisan dari masing-masing proses Win32 ini mungkin tertinggal, menunggu proses Cygwin yang dijalankan mereka untuk keluar.
Kedengarannya banyak pekerjaan, bukan? Dan ya, itu slooooow.
EDIT: dokumen sudah usang, silakan lihat jawaban luar biasa ini untuk pembaruan
fork
namun menyelesaikan ini dengan solusi yang bocor dan Anda harus siap menghadapi situasi yang tidak terduga.Saya tentu tidak tahu detailnya karena saya belum pernah melakukannya, tetapi NT API asli memiliki kemampuan untuk melakukan fork suatu proses (subsistem POSIX pada Windows membutuhkan kemampuan ini - Saya tidak yakin apakah subsistem POSIX bahkan didukung lagi).
Pencarian untuk ZwCreateProcess () akan memberi Anda beberapa detail lebih lanjut - misalnya sedikit informasi dari Maxim Shatskih ini :
Meskipun perhatikan bahwa Corinna Vinschen menunjukkan bahwa Cygwin ditemukan menggunakan ZwCreateProcess () masih tidak dapat diandalkan :
sumber
fork
dengan segeraexec
", maka mungkin CreateProcess adalah kandidatnya. Tetapifork
tanpaexec
sering diinginkan dan ini adalah apa yang mendorong orang untuk meminta secara nyatafork
.Nah, jendela sebenarnya tidak memiliki sesuatu yang seperti itu. Terutama karena garpu dapat digunakan secara konseptual untuk membuat utas atau proses di * nix.
Jadi, saya harus mengatakan:
CreateProcess()
/CreateProcessEx()
dan
CreateThread()
(Saya pernah mendengar bahwa untuk aplikasi C,_beginthreadex()
lebih baik).sumber
Orang-orang telah mencoba menerapkan garpu di Windows. Ini adalah hal terdekat yang dapat saya temukan:
Diambil dari: http://doxygen.scilab.org/5.3/d0/d8f/forkWindows_8c_source.html#l00216
sumber
fork
macet, apakah program macet, atau utas macet begitu saja? Jika program membuat crash, maka ini sebenarnya bukan forking. Hanya penasaran, karena saya sedang mencari solusi nyata, dan berharap ini bisa menjadi alternatif yang layak.Sebelum Microsoft memperkenalkan opsi "Linux subsystem for Windows" mereka yang baru,
CreateProcess()
adalah hal yang paling dekat dengan Windowsfork()
, tetapi Windows mengharuskan Anda menentukan executable untuk dijalankan dalam proses itu.Proses pembuatan UNIX sangat berbeda dengan Windows. Its
fork()
panggilan pada dasarnya duplikat proses saat ini hampir secara total, masing-masing dalam ruang alamat mereka sendiri, dan terus berjalan secara terpisah. Meskipun prosesnya sendiri berbeda, mereka masih menjalankan program yang sama . Lihat di sini untuk gambaran umum yang baik tentangfork/exec
model tersebut.Kembali ke arah lain, padanan dari Windows
CreateProcess()
adalahfork()/exec()
pasangan fungsi di UNIX.Jika Anda mem-porting perangkat lunak ke Windows dan Anda tidak keberatan dengan lapisan terjemahan, Cygwin menyediakan kemampuan yang Anda inginkan tetapi itu agak kludgey.
Tentu saja, dengan yang baru subsistem Linux , hal yang paling dekat Windows memiliki untuk
fork()
ini benar-benarfork()
:-)sumber
fork
rata-rata aplikasi non-WSL?Dokumen berikut ini menyediakan beberapa informasi tentang kode port dari UNIX ke Win32: https://msdn.microsoft.com/en-us/library/y23kc048.aspx
Antara lain, ini menunjukkan bahwa model proses sangat berbeda antara kedua sistem dan merekomendasikan pertimbangan CreateProcess dan CreateThread di mana perilaku seperti fork () diperlukan.
sumber
"segera setelah Anda ingin mengakses file atau printf maka io ditolak"
Anda tidak dapat memiliki kue dan memakannya juga ... di msvcrt.dll, printf () didasarkan pada API Konsol, yang dengan sendirinya menggunakan lpc untuk berkomunikasi dengan subsistem konsol (csrss.exe). Koneksi dengan csrss dimulai saat proses start-up, yang berarti bahwa setiap proses yang memulai eksekusinya "di tengah" akan melewatkan langkah tersebut. Kecuali Anda memiliki akses ke kode sumber sistem operasi, tidak ada gunanya mencoba menyambung ke csrs secara manual. Sebagai gantinya, Anda harus membuat subsistem Anda sendiri, dan karenanya menghindari fungsi konsol dalam aplikasi yang menggunakan fork ().
setelah Anda mengimplementasikan subsistem Anda sendiri, jangan lupa untuk juga menduplikasi semua pegangan induk untuk proses anak ;-)
"Selain itu, Anda mungkin sebaiknya tidak menggunakan fungsi Zw * kecuali Anda dalam mode kernel, Anda mungkin harus menggunakan fungsi Nt * sebagai gantinya."
ZwGetContextThread (NtCurrentThread (), & konteks);
sumber
semantik fork () diperlukan jika anak memerlukan akses ke status memori aktual dari induk saat fork () instan dipanggil. Saya memiliki perangkat lunak yang bergantung pada mutex implisit dari penyalinan memori saat garpu instan () dipanggil, yang membuat utas tidak mungkin digunakan. (Ini diemulasikan pada platform * nix modern melalui semantik copy-on-write / update-memory-table.)
Yang terdekat yang ada di Windows sebagai syscall adalah CreateProcess. Hal terbaik yang dapat dilakukan adalah agar induknya membekukan semua utas lainnya selama ia menyalin memori ke ruang memori proses baru, lalu mencairkannya. Baik kelas Cygwin frok [sic] maupun kode Scilab yang diposting Eric des Courtis tidak melakukan pembekuan thread, yang bisa saya lihat.
Selain itu, Anda mungkin sebaiknya tidak menggunakan fungsi Zw * kecuali Anda dalam mode kernel, Anda mungkin harus menggunakan fungsi Nt * sebagai gantinya. Ada cabang tambahan yang memeriksa apakah Anda dalam mode kernel dan, jika tidak, melakukan semua pemeriksaan batas dan verifikasi parameter yang selalu dilakukan Nt *. Jadi, sangat kurang efisien untuk memanggilnya dari mode pengguna.
sumber
Pilihan terbaik Anda adalah CreateProcess () atau CreateThread () . Ada lebih banyak informasi tentang porting di sini .
sumber
Tidak ada cara mudah untuk meniru fork () di Windows.
Saya menyarankan Anda untuk menggunakan utas sebagai gantinya.
sumber
fork
adalah persis apa yang Cygwin lakukan. Tapi, jika Anda pernah membaca tentang bagaimana mereka melakukannya, "tidak mudah" adalah kesalahpahaman yang besar :-)Yang paling dekat yang Anda katakan ... Biar saya pikirkan ... Ini pasti garpu () kurasa :)
Untuk detailnya, lihat Apakah Interix mengimplementasikan fork ()?
sumber
Seperti jawaban lain yang telah disebutkan, NT (kernel yang mendasari versi modern Windows) memiliki persamaan dengan Unix fork (). Bukan itu masalahnya.
Masalahnya adalah bahwa mengkloning seluruh status proses secara umum bukanlah hal yang waras untuk dilakukan. Ini sama benarnya di dunia Unix seperti di Windows, tetapi di dunia Unix, fork () digunakan sepanjang waktu, dan perpustakaan dirancang untuk menghadapinya. Perpustakaan Windows tidak.
Misalnya, sistem DLL kernel32.dll dan user32.dll mempertahankan sambungan pribadi ke proses server Win32 csrss.exe. Setelah bercabang, ada dua proses di ujung klien dari koneksi tersebut, yang akan menyebabkan masalah. Proses anak harus memberi tahu csrss.exe keberadaannya dan membuat koneksi baru - tetapi tidak ada antarmuka untuk melakukannya, karena pustaka ini tidak dirancang dengan fork ().
Jadi Anda punya dua pilihan. Salah satunya adalah melarang penggunaan kernel32 dan user32 dan pustaka lain yang tidak dirancang untuk bercabang - termasuk pustaka apa pun yang menautkan secara langsung atau tidak langsung ke kernel32 atau user32, yang hampir semuanya. Ini berarti Anda tidak dapat berinteraksi dengan desktop Windows sama sekali, dan terjebak di dunia Unixy Anda yang terpisah. Ini adalah pendekatan yang diambil oleh berbagai subsistem Unix untuk NT.
Opsi lainnya adalah menggunakan semacam peretasan yang mengerikan untuk mencoba membuat perpustakaan yang tidak sadar bekerja dengan fork (). Itulah yang dilakukan Cygwin. Ini menciptakan proses baru, memungkinkannya menginisialisasi (termasuk mendaftarkan dirinya dengan csrss.exe), lalu menyalin sebagian besar status dinamis dari proses lama dan berharap yang terbaik. Sungguh mengherankan saya bahwa ini pernah berhasil. Itu pasti tidak bekerja dengan andal - bahkan jika tidak gagal secara acak karena konflik ruang alamat, perpustakaan apa pun yang Anda gunakan mungkin diam-diam dibiarkan dalam keadaan rusak. Klaim jawaban yang diterima saat ini bahwa Cygwin memiliki "garpu berfitur lengkap ()" adalah ... meragukan.
Ringkasan: Dalam lingkungan seperti Interix, Anda bisa bercabang dengan memanggil fork (). Jika tidak, cobalah untuk melepaskan diri Anda dari keinginan untuk melakukannya. Bahkan jika Anda menargetkan Cygwin, jangan gunakan fork () kecuali Anda benar-benar harus melakukannya.
sumber
Jika Anda hanya peduli tentang membuat subproses dan menunggunya, mungkin _spawn * API dalam proses.h sudah cukup. Berikut informasi lebih lanjut tentang itu:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/process-and-environment-control https://en.wikipedia.org/wiki/Process.h
sumber