كيف يمكنني تفريخ شيطان في Uclinux باستخدام Vfork؟
سؤال
سيكون هذا سهلاً مع Fork () ، لكن ليس لدي MMU. لقد سمعت أن Vfork () يحجب عملية الوالدين حتى يخرج الطفل أو ينفذ exec (). كيف يمكنني إنجاز شيء كهذا؟:
pid_t pid = vfork();
if (pid == -1) {
// fail
exit(-1);
}
if (pid == 0) {
// child
while(1) {
// Do my daemon stuff
}
// Let's pretend it exits sometime
exit();
}
// Continue execution in parent without blocking.....
المحلول
يبدو أنه لا توجد طريقة للقيام بذلك تمامًا كما لديك هنا. exec
أو _exit
يجب أن يتم استدعاء الوالد لمواصلة التنفيذ. إما وضع رمز الخفي في آخر قابل للتنفيذ و exec
أو استخدام الطفل لتفرخ المهمة الأصلية. النهج الثاني هو الطريقة المتستر ، ويتم وصفها هنا.
نصائح أخرى
وظيفة Daemon () لأنظمة Uclinux بدون MMU و Fork () ، بواسطة Jamie Lokier ، بتنسيق التصحيح
لا يمكنك عمل Daemon () مع Vfork (). لإنشاء شيء مشابه لخفي على! MMU باستخدام Vfork () ، لا تموت العملية الوالدية (لذلك هناك عمليات إضافية) ، ويجب عليك الاتصال بالخفي على الخلفية (أي عن طريق إلحاقها وإلى سطر الأوامر على الصدف).
من ناحية أخرى ، يوفر Linux Clone (). مسلحًا بذلك ، والمعرفة والرعاية ، من الممكن تنفيذ Daemon () لـ! MMU. لدى جيمي لوكير وظيفة للقيام بذلك على ARM و I386 ، احصل عليه من هنا.
يحرر: صنع الرابط إلى Daemon's Daemon () لـ Jamie Lokier لـ! MMU Linux أكثر بروزًا.
كنت أعتقد أن هذا سيكون نوعًا من المشكلة التي واجهها العديد من الآخرين من قبل ، لكنني واجهت صعوبة في العثور على أي شخص يتحدث عن مشاكل "قتل الوالد".
اعتقدت في البداية أنك يجب أن تكون قادرًا على القيام بذلك باستخدام دعوة بسيطة (ليس كذلك ، ولكن نوعًا ما) clone
, ، مثله:
pid_t new_vfork(void) {
return clone(child_func, /* child function */
child_stack, /* child stack */
SIGCHLD | CLONE_VM, /* flags */
NULL, /* argument to child */
NULL, /* pid of the child */
NULL, /* thread local storage for child */
NULL); /* thread id of child in child's mem */
}
باستثناء أن تحديد child_stack و child_func من العمل بالطريقة التي يحدث بها مع Vfork أمر صعب للغاية لأن Child_func يجب أن يكون عنوان الإرجاع من استدعاء Clone و Child_stack يجب أن يكون الجزء العلوي من المكدس عند النقطة يتم إجراء استدعاء النظام الفعلي (sys_clone).
ربما يمكنك محاولة الاتصال sys_clone
مباشرة مع
pid_t new_vfork(void) {
return sys_clone( SIGCHLD | CLONE_VM, NULL);
}
الذي أعتقد أنه قد يحصل على ما تريد. إن تمرير الوسيطة الثانية ، وهو مؤشر child_stack ، يؤدي إلى أن يفعل kernel نفس الشيء كما هو الحال في Vfork و Fork ، وهو استخدام نفس المكدس مثل الوالد.
لم أستخدمها أبدًا sys_clone
مباشرة ولم تختبر هذا ، لكنني أعتقد أنه يجب أن ينجح. أعتقد أن:
sys_clone( SIGCHLD | CLONE_VM | CLONE_VFORK, NULL);
يعادل vfork
.
إذا لم ينجح هذا (ولا يمكنك معرفة كيفية القيام بشيء مماثل) ، فقد تتمكن من استخدام مكالمة الاستنساخ العادية مع setjump
و longjmp
مكالمات لمحاكاة ذلك ، أو قد تكون قادرًا على الالتزام بالحاجة إلى دلالات "العودة مرتين" fork
و vfork
.