जवाबों:
Cygwin ने विंडोज पर फोर्क () को पूरी तरह से चित्रित किया है। इस प्रकार यदि Cygwin का उपयोग करना आपके लिए स्वीकार्य है, तो समस्या का हल हो जाता है मामले में प्रदर्शन कोई समस्या नहीं है।
अन्यथा आप इस पर एक नज़र डाल सकते हैं कि साइगविन कैसे कांटा () लागू करता है। एक बहुत पुराने Cygwin के आर्किटेक्चर डॉक से :
5.6। प्रक्रिया निर्माण Cygwin में कांटा कॉल विशेष रूप से दिलचस्प है क्योंकि यह Win32 एपीआई के शीर्ष पर अच्छी तरह से मैप नहीं करता है। यह सही ढंग से लागू करने के लिए बहुत मुश्किल बनाता है। वर्तमान में, Cygwin कांटा एक गैर-कॉपी-ऑन-राइट कार्यान्वयन है जो UNIX के शुरुआती स्वादों में मौजूद था।
पहली बात यह है कि जब एक माता-पिता बच्चे की प्रक्रिया की तलाश करते हैं, तो यह होता है कि माता-पिता बच्चे के लिए सिग्विन प्रक्रिया तालिका में एक स्थान की गणना करते हैं। यह तब Win32 CreateProcess कॉल का उपयोग करके एक निलंबित बच्चे की प्रक्रिया बनाता है। इसके बाद, माता-पिता प्रक्रिया अपने स्वयं के संदर्भ को बचाने के लिए सेटजम्प को कॉल करते हैं और एक सिग्विन साझा मेमोरी क्षेत्र (सभी साइगविन कार्यों के बीच साझा) में इस पर एक संकेतक सेट करते हैं। इसके बाद यह बच्चे के .data और .bs सेक्शन में भर जाता है और उसके अपने एड्रेस स्पेस से निलंबित बच्चे के एड्रेस स्पेस में कॉपी हो जाता है। बच्चे के पते की जगह को शुरू करने के बाद, बच्चे को चलाया जाता है, जबकि माता-पिता म्यूटेक्स पर इंतजार करते हैं। बच्चे को पता चलता है कि यह बचा हुआ है और सहेजे गए कूदने वाले बफर का उपयोग करके लॉन्गजंप करता है। बच्चा तब म्यूटेक्स सेट करता है जिसे माता-पिता प्रतीक्षा कर रहे होते हैं और दूसरे म्यूटेक्स पर ब्लॉक करते हैं। यह माता-पिता के लिए अपने स्टैक और ढेर को बच्चे में कॉपी करने का संकेत है, जिसके बाद यह म्यूटेक्स को रिलीज़ करता है जिस पर बच्चा प्रतीक्षा कर रहा है और कांटा कॉल से वापस आ जाता है। अंत में, बच्चा अंतिम म्यूटेक्स पर अवरुद्ध होने से जागता है, साझा किए गए क्षेत्र के माध्यम से पारित किसी भी मेमोरी-मैप किए गए क्षेत्रों को फिर से बनाता है, और कांटा से ही लौटता है।
जबकि हमारे पास कुछ विचार हैं कि माता-पिता और बच्चे की प्रक्रिया के बीच संदर्भ स्विच की संख्या को कम करके अपने कांटे के कार्यान्वयन को कैसे तेज किया जाए, Win32 के तहत कांटा लगभग निश्चित रूप से अक्षम होगा। सौभाग्य से, ज्यादातर परिस्थितियों में Cygwin द्वारा प्रदान किए गए कॉल के स्पॉन परिवार को केवल थोड़े प्रयास के साथ एक कांटा / निष्पादन जोड़ी के लिए प्रतिस्थापित किया जा सकता है। ये कॉल Win32 एपीआई के शीर्ष पर सफाई से नक्शा बनाते हैं। नतीजतन, वे बहुत अधिक कुशल हैं। कांटा के बजाय स्पॉन को कॉल करने के लिए संकलक के ड्राइवर प्रोग्राम को बदलना एक तुच्छ परिवर्तन था और हमारे परीक्षणों में संकलन गति में बीस से तीस प्रतिशत की वृद्धि हुई।
हालांकि, स्पॉन और एग्जीक्यूटिव कठिनाइयों के अपने सेट को प्रस्तुत करते हैं। क्योंकि Win32 के तहत एक वास्तविक निष्पादन करने का कोई तरीका नहीं है, Cygwin को अपनी स्वयं की प्रोसेस आईडी (PID) का आविष्कार करना होगा। नतीजतन, जब कोई प्रक्रिया कई निष्पादन कॉल करता है, तो एक एकल सिग्विन पीआईडी के साथ जुड़े कई विंडोज पीआईडी होंगे। कुछ मामलों में, इन Win32 प्रक्रियाओं में से प्रत्येक के स्टब पर लगाम लग सकती है, उनके निष्कासन के लिए प्रतीक्षा करने की Cygwin प्रक्रिया का इंतजार करना होगा।
बहुत काम की तरह लगता है, है ना? और हाँ, यह स्लोवू है।
संपादित करें: दस्तावेज़ पुराना है, कृपया अपडेट के लिए यह उत्कृष्ट उत्तर देखें
fork
फिर भी यह इसे टपका हुआ समाधान के साथ पूरा करता है और आपको अप्रत्याशित परिस्थितियों के लिए तैयार रहना चाहिए।
मुझे निश्चित रूप से इस पर विवरण नहीं पता है क्योंकि मैंने इसे कभी नहीं किया है, लेकिन मूल NT API में एक प्रक्रिया को कांटा करने की क्षमता है (Windows पर POSIX सबसिस्टम को इस क्षमता की आवश्यकता है - मुझे यकीन नहीं है कि POSIX उपतंत्र अब भी समर्थित है)।
ZwCreateProcess () के लिए एक खोज आपको कुछ और विवरण प्राप्त करना चाहिए - उदाहरण के लिए मैक्सिम सैल्स्कॉर्स से इस जानकारी के बारे में :
यहां सबसे महत्वपूर्ण पैरामीटर सेक्शनहैंडल है। यदि यह पैरामीटर NULL है, तो कर्नेल वर्तमान प्रक्रिया को कांटा देगा। अन्यथा, यह पैरामीटर ZwCreateProcess () को कॉल करने से पहले EXE फ़ाइल पर बनाई गई SEC_IMAGE अनुभाग ऑब्जेक्ट का एक हैंडल होना चाहिए।
हालांकि ध्यान दें कि Corinna Vinschen इंगित करता है कि Cygwin ZwCreateProcess () अभी भी अविश्वसनीय का उपयोग कर पाया :
इकर अरिज़मेन्दी ने लिखा:
> Because the Cygwin project relied solely on Win32 APIs its fork > implementation is non-COW and inefficient in those cases where a fork > is not followed by exec. It's also rather complex. See here (section > 5.6) for details: > > http://www.redhat.com/support/wpapers/cygnus/cygnus_cygwin/architecture.html
यह दस्तावेज़ पुराना है, 10 साल या उससे अधिक पुराना है। जब हम अभी भी कांटा का अनुकरण करने के लिए Win32 कॉल का उपयोग कर रहे हैं, तो विधि में उल्लेखनीय बदलाव आया है। विशेष रूप से, हम अब निलंबित स्थिति में बच्चे की प्रक्रिया नहीं बनाते हैं, जब तक कि बच्चे को कॉपी करने से पहले विशिष्ट डेटास्ट्रेक्ट को माता-पिता में एक विशेष हैंडलिंग की आवश्यकता नहीं होती है। वर्तमान 1.5.25 रिलीज में एक निलंबित बच्चे के लिए एकमात्र मामला माता-पिता में खुली कुर्सियां हैं। आगामी 1.7.0 रिलीज बिल्कुल भी स्थगित नहीं होगी।
ZwCreateProcess का उपयोग नहीं करने का एक कारण यह था कि 1.5.25 रिलीज तक हम अभी भी विंडोज 9x उपयोगकर्ताओं का समर्थन कर रहे हैं। हालाँकि, NT- आधारित सिस्टम पर ZwCreateProcess का उपयोग करने के दो प्रयास एक कारण या किसी अन्य के लिए विफल रहे।
यह वास्तव में अच्छा होगा यदि यह सामान बेहतर होगा या सभी प्रलेखित होगा, विशेष रूप से डेटास्ट्रक्चर के एक जोड़े और एक सबसिस्टम के लिए एक प्रक्रिया को कैसे जोड़ा जाए। जबकि कांटा एक Win32 अवधारणा नहीं है, मुझे नहीं लगता कि कांटा को लागू करने के लिए आसान बनाने के लिए यह एक बुरी बात होगी।
fork
तत्काल के साथ " चाहते हैं exec
, तो शायद CreateProcess एक उम्मीदवार है। लेकिन इसके fork
बिना exec
अक्सर वांछनीय है और यह वही है जो ड्राइवर लोगों को एक असली के लिए पूछने के लिए fork
।
खैर, विंडोज़ वास्तव में ऐसा कुछ भी नहीं है। विशेषकर चूंकि कांटा का उपयोग * निक्स में एक थ्रेड या एक प्रक्रिया को बनाने के लिए किया जा सकता है।
तो, मुझे कहना पड़ेगा:
CreateProcess()
/CreateProcessEx()
तथा
CreateThread()
(मैंने सुना है कि सी अनुप्रयोगों के लिए, _beginthreadex()
बेहतर है)।
लोगों ने विंडोज पर कांटा लगाने की कोशिश की है। यह मेरे लिए सबसे निकटतम चीज है:
इससे लिया गया: http://doxygen.scilab.org/5.3/d0/d8f/forkWindows_8c_source.html#l00216
static BOOL haveLoadedFunctionsForFork(void);
int fork(void)
{
HANDLE hProcess = 0, hThread = 0;
OBJECT_ATTRIBUTES oa = { sizeof(oa) };
MEMORY_BASIC_INFORMATION mbi;
CLIENT_ID cid;
USER_STACK stack;
PNT_TIB tib;
THREAD_BASIC_INFORMATION tbi;
CONTEXT context = {
CONTEXT_FULL |
CONTEXT_DEBUG_REGISTERS |
CONTEXT_FLOATING_POINT
};
if (setjmp(jenv) != 0) return 0; /* return as a child */
/* check whether the entry points are
initilized and get them if necessary */
if (!ZwCreateProcess && !haveLoadedFunctionsForFork()) return -1;
/* create forked process */
ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa,
NtCurrentProcess(), TRUE, 0, 0, 0);
/* set the Eip for the child process to our child function */
ZwGetContextThread(NtCurrentThread(), &context);
/* In x64 the Eip and Esp are not present,
their x64 counterparts are Rip and Rsp respectively. */
#if _WIN64
context.Rip = (ULONG)child_entry;
#else
context.Eip = (ULONG)child_entry;
#endif
#if _WIN64
ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Rsp,
MemoryBasicInformation, &mbi, sizeof mbi, 0);
#else
ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Esp,
MemoryBasicInformation, &mbi, sizeof mbi, 0);
#endif
stack.FixedStackBase = 0;
stack.FixedStackLimit = 0;
stack.ExpandableStackBase = (PCHAR)mbi.BaseAddress + mbi.RegionSize;
stack.ExpandableStackLimit = mbi.BaseAddress;
stack.ExpandableStackBottom = mbi.AllocationBase;
/* create thread using the modified context and stack */
ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess,
&cid, &context, &stack, TRUE);
/* copy exception table */
ZwQueryInformationThread(NtCurrentThread(), ThreadBasicInformation,
&tbi, sizeof tbi, 0);
tib = (PNT_TIB)tbi.TebBaseAddress;
ZwQueryInformationThread(hThread, ThreadBasicInformation,
&tbi, sizeof tbi, 0);
ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress,
&tib->ExceptionList, sizeof tib->ExceptionList, 0);
/* start (resume really) the child */
ZwResumeThread(hThread, 0);
/* clean up */
ZwClose(hThread);
ZwClose(hProcess);
/* exit with child's pid */
return (int)cid.UniqueProcess;
}
static BOOL haveLoadedFunctionsForFork(void)
{
HANDLE ntdll = GetModuleHandle("ntdll");
if (ntdll == NULL) return FALSE;
if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory &&
ZwCreateThread && ZwGetContextThread && ZwResumeThread &&
ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose)
{
return TRUE;
}
ZwCreateProcess = (ZwCreateProcess_t) GetProcAddress(ntdll,
"ZwCreateProcess");
ZwQuerySystemInformation = (ZwQuerySystemInformation_t)
GetProcAddress(ntdll, "ZwQuerySystemInformation");
ZwQueryVirtualMemory = (ZwQueryVirtualMemory_t)
GetProcAddress(ntdll, "ZwQueryVirtualMemory");
ZwCreateThread = (ZwCreateThread_t)
GetProcAddress(ntdll, "ZwCreateThread");
ZwGetContextThread = (ZwGetContextThread_t)
GetProcAddress(ntdll, "ZwGetContextThread");
ZwResumeThread = (ZwResumeThread_t)
GetProcAddress(ntdll, "ZwResumeThread");
ZwQueryInformationThread = (ZwQueryInformationThread_t)
GetProcAddress(ntdll, "ZwQueryInformationThread");
ZwWriteVirtualMemory = (ZwWriteVirtualMemory_t)
GetProcAddress(ntdll, "ZwWriteVirtualMemory");
ZwClose = (ZwClose_t) GetProcAddress(ntdll, "ZwClose");
if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory &&
ZwCreateThread && ZwGetContextThread && ZwResumeThread &&
ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose)
{
return TRUE;
}
else
{
ZwCreateProcess = NULL;
ZwQuerySystemInformation = NULL;
ZwQueryVirtualMemory = NULL;
ZwCreateThread = NULL;
ZwGetContextThread = NULL;
ZwResumeThread = NULL;
ZwQueryInformationThread = NULL;
ZwWriteVirtualMemory = NULL;
ZwClose = NULL;
}
return FALSE;
}
fork
क्रैश होता है, तो क्या यह प्रोग्राम क्रैश करता है, या थ्रेड सिर्फ क्रैश होता है? यदि यह प्रोग्राम क्रैश करता है, तो यह वास्तव में फोर्किंग नहीं है। बस उत्सुक, क्योंकि मैं एक वास्तविक समाधान की तलाश में हूं, और आशा है कि यह एक सभ्य विकल्प हो सकता है।
Microsoft ने अपने नए "लिनक्स सबसिस्टम फॉर विंडोज" विकल्प को पेश करने से पहले, विंडोज CreateProcess()
को सबसे करीबी चीज माना था fork()
, लेकिन विंडोज को उस प्रक्रिया में चलाने के लिए एक निष्पादन योग्य निर्दिष्ट करना होगा।
UNIX प्रक्रिया निर्माण विंडोज के लिए काफी अलग है। इसकी fork()
कॉल मूल रूप से वर्तमान प्रक्रिया को लगभग कुल मिलाकर प्रत्येक को अपने स्वयं के पता स्थान में दोहराती है, और उन्हें अलग-अलग चलाना जारी रखती है। जबकि प्रक्रियाएं खुद अलग हैं, वे अभी भी एक ही कार्यक्रम चला रहे हैं । मॉडल के अच्छे अवलोकन के लिए यहां देखें fork/exec
।
दूसरे तरीके से वापस जाना, विंडोज के बराबर यूनिक्स में कार्यों CreateProcess()
की fork()/exec()
जोड़ी है।
यदि आप विंडोज के लिए सॉफ्टवेयर को पोर्ट कर रहे थे और आपको ट्रांसलेशन लेयर पर कोई आपत्ति नहीं है, तो साइग्विन ने वह क्षमता प्रदान की, जो आप चाहते हैं, लेकिन यह बहुत ही हास्यास्पद था।
बेशक, के साथ नए लिनक्स सबसिस्टम , निकटतम बात विंडोज के लिए है fork()
है वास्तव में fork()
:-)
fork
एक औसत, गैर-WSL अनुप्रयोग में उपयोग कर सकता हूँ ?
निम्नलिखित दस्तावेज़ UNIX से Win32 में पोर्टिंग कोड पर कुछ जानकारी प्रदान करता है: https://msdn.microsoft.com/en-us/library/y23kc048.aspx
अन्य बातों के अलावा, यह इंगित करता है कि प्रक्रिया मॉडल दो प्रणालियों के बीच काफी भिन्न है और CreateProcess और CreateThread पर विचार करने की अनुशंसा करता है जहां कांटा () - जैसे व्यवहार की आवश्यकता होती है।
"जैसे ही आप फ़ाइल एक्सेस या प्रिंटफ़ करना चाहते हैं तो io मना कर दिया जाता है"
आप अपना केक नहीं खा सकते हैं और इसे भी खा सकते हैं ... msvcrt.dll में, printf () कंसोल एपीआई पर आधारित है, जो अपने आप में कंसोल सबसिस्टम (csrss.exe) के साथ संचार करने के लिए lpc का उपयोग करता है। सीएसआर के साथ कनेक्शन प्रक्रिया स्टार्ट-अप पर शुरू किया गया है, जिसका अर्थ है कि कोई भी प्रक्रिया जो "निष्पादन को" बीच में शुरू करती है, उस कदम को छोड़ दिया जाएगा। जब तक आपके पास ऑपरेटिंग सिस्टम के स्रोत कोड तक पहुंच नहीं है, तब तक मैन्युअल रूप से सीएसआरएस से कनेक्ट करने की कोशिश करने का कोई मतलब नहीं है। इसके बजाय, आपको अपना खुद का सबसिस्टम बनाना चाहिए, और तदनुसार कांटा () का उपयोग करने वाले अनुप्रयोगों में कंसोल कार्यों से बचें।
एक बार जब आप अपना सबसिस्टम लागू कर लेते हैं, तो बच्चे की प्रक्रिया के लिए माता-पिता के सभी हैंडल की नकल करना न भूलें;;
"इसके अलावा, आपको संभवतः Zw * फ़ंक्शन का उपयोग नहीं करना चाहिए जब तक कि आप कर्नेल मोड में नहीं हैं, आपको संभवतः Nt * फ़ंक्शन का उपयोग करना चाहिए।"
ZwGetContextThread (NtCurrentThread (), & reference);
कांटा () शब्दार्थ आवश्यक है जहां बच्चे को तत्काल कांटा () के रूप में माता-पिता की वास्तविक स्मृति स्थिति तक पहुंच की आवश्यकता होती है। मेरे पास सॉफ्टवेयर का एक टुकड़ा है जो तत्काल कांटा () के रूप में मेमोरी कॉपी के निहित म्यूटेक्स पर निर्भर करता है, जिसे थ्रेड्स का उपयोग करना असंभव बनाता है। (यह कॉपी-ऑन-राइट / अपडेट-मेमोरी-टेबल शब्दार्थ के माध्यम से आधुनिक * निक्स प्लेटफार्मों पर अनुकरण किया गया है।)
Windows पर एक syscall के रूप में मौजूद निकटतम CreateProcess है। जो सबसे अच्छा किया जा सकता है वह माता-पिता के लिए उस समय के दौरान अन्य सभी थ्रेड्स को फ्रीज करने के लिए है कि यह नई प्रक्रिया की मेमोरी स्पेस में मेमोरी की नकल कर रहा है, फिर उन्हें पिघलाएं। एरिक डेस कोर्टिस ने न तो साइग्विन फ्रॉक [sic] क्लास और न ही सिलाब कोड को थ्रेड-फ्रीजिंग किया, जिसे मैं देख सकता हूं।
इसके अलावा, आपको संभवतः Zw * फ़ंक्शन का उपयोग नहीं करना चाहिए जब तक कि आप कर्नेल मोड में नहीं हैं, आपको संभवतः Nt * फ़ंक्शन का उपयोग करना चाहिए। एक अतिरिक्त शाखा है जो यह जांचती है कि क्या आप कर्नेल मोड में हैं और यदि नहीं, तो सभी जाँच और पैरामीटर सत्यापन करते हैं जो कि Nt हमेशा करते हैं। इस प्रकार, उपयोगकर्ता मोड से उन्हें कॉल करने के लिए यह बहुत कम कुशल है।
आपके सबसे अच्छे विकल्प CreateProcess () या CreateThread () हैं । यहां पोर्टिंग के बारे में अधिक जानकारी है ।
विंडोज पर फोर्क () का अनुकरण करने का कोई आसान तरीका नहीं है।
मैं आपको इसके बजाय धागे का उपयोग करने का सुझाव देता हूं।
fork
था जो साइगविन ने किया था। लेकिन, यदि आप कभी भी पढ़ते हैं कि उन्होंने यह कैसे किया है, तो "कोई आसान तरीका नहीं है", यह एक गलत गलतफहमी है :-)
निकटतम आप कहते हैं ... मुझे लगता है ... यह कांटा होना चाहिए () मुझे लगता है :)
विवरण के लिए देखें क्या इंटरिक्स कांटा लागू करता है ()?
जैसा कि अन्य उत्तरों में उल्लेख किया गया है, NT (विंडोज के कर्नेल अंतर्निहित आधुनिक संस्करण) में यूनिक्स फोर्क () के बराबर है। यह समस्या नहीं है।
समस्या यह है कि एक प्रक्रिया की पूरे राज्य में क्लोनिंग आम तौर पर करने के लिए एक समझदार चीज नहीं है। यह यूनिक्स दुनिया में उतना ही सच है जितना कि विंडोज में है, लेकिन यूनिक्स दुनिया में, हर समय कांटा () का उपयोग किया जाता है, और पुस्तकालयों को इससे निपटने के लिए डिज़ाइन किया गया है। विंडोज लाइब्रेरी नहीं हैं।
उदाहरण के लिए, सिस्टम DLLs कर्नेल 32.dll और user32.dll Win32 सर्वर प्रक्रिया csrss.exe के लिए एक निजी कनेक्शन बनाए रखता है। एक कांटा के बाद, उस कनेक्शन के क्लाइंट अंत पर दो प्रक्रियाएं होती हैं, जो समस्याओं का कारण बनने जा रही है। बच्चे की प्रक्रिया को अपने अस्तित्व के csrss.exe को सूचित करना चाहिए और एक नया संबंध बनाना चाहिए - लेकिन ऐसा करने के लिए कोई इंटरफ़ेस नहीं है, क्योंकि इन पुस्तकालयों को कांटा () को ध्यान में रखकर डिजाइन नहीं किया गया था।
तो आपके पास दो विकल्प हैं। एक कर्नेल 32 और user32 के उपयोग को रोकने के लिए है और अन्य पुस्तकालयों को फोर्क करने के लिए डिज़ाइन नहीं किया गया है - किसी भी लाइब्रेरी को शामिल करना, जो प्रत्यक्ष या अप्रत्यक्ष रूप से कर्नेल 32 या उपयोगकर्ता 32 से लिंक करता है, जो कि वास्तव में उन सभी में से है। इसका मतलब है कि आप विंडोज डेस्कटॉप के साथ बिल्कुल भी बातचीत नहीं कर सकते हैं, और अपनी अलग यूनिक्स दुनिया में फंस गए हैं। यह NT के लिए विभिन्न यूनिक्स उपतंत्रों द्वारा लिया गया दृष्टिकोण है।
अन्य विकल्प कांटा () के साथ काम करने के लिए अनजान पुस्तकालयों को प्राप्त करने की कोशिश करने के लिए कुछ प्रकार की भयानक हैक का सहारा लेना है। यही साइगविन करता है। यह एक नई प्रक्रिया बनाता है, इसे इनिशियलाइज़ करने देता है (जिसमें खुद को csrss..exe के साथ पंजीकृत करना शामिल है), फिर पुरानी प्रक्रिया से अधिकांश डायनेमिक स्थिति की प्रतिलिपि बनाता है और सर्वश्रेष्ठ की उम्मीद करता है। यह मुझे आश्चर्यचकित करता है कि यह कभी काम करता है। यह निश्चित रूप से मज़बूती से काम नहीं करता है - भले ही यह पता स्थान संघर्ष के कारण बेतरतीब ढंग से विफल न हो, लेकिन आपके द्वारा उपयोग किए जा रहे किसी भी पुस्तकालय को चुपचाप टूटी हुई स्थिति में छोड़ा जा सकता है। वर्तमान स्वीकृत उत्तर का दावा है कि साइगविन के पास "पूरी तरह से चित्रित कांटा ()" है ... संदिग्ध।
सारांश: एक इंटरिक्स जैसे माहौल में, आप कांटा () कॉल करके कांटा कर सकते हैं। अन्यथा, कृपया इसे करने की इच्छा से खुद को दूर करने का प्रयास करें। यहां तक कि अगर आप साइग्विन को लक्षित कर रहे हैं, तब तक कांटा () का उपयोग न करें जब तक कि आपके पास बिल्कुल न हो।
यदि आप केवल एक सबप्रोसेस बनाने और उसकी प्रतीक्षा करने के बारे में परवाह करते हैं, तो शायद _spawn * API की प्रक्रिया में पर्याप्त हैं। यहाँ उस के बारे में अधिक जानकारी है:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/process-and-environment-control https://en.wikipedia.org/wiki/Process.h