هل تسفر Waitpid عن معلومات الحالة صالحة لعملية الطفل التي خرجت بالفعل؟
سؤال
اذا انا fork
عملية الطفل ، وتخرج عملية الطفل قبل استدعاء الوالد waitpid
, ، إذن هي معلومات حالة الخروج التي يتم تعيينها بواسطة waitpid
لا تزال صالحة؟ إذا كان الأمر كذلك ، متى يصبح غير صالح ؛ أي كيف يمكنني التأكد من أنني أتمكن من الاتصال waitpid
على PID الطفل واستمر في الحصول على معلومات حالة الخروج صالحة بعد فترة زمنية تعسفية ، وكيف يمكنني "التنظيف" (أخبر نظام التشغيل أنني لم أعد مهتمًا بمعلومات حالة الخروج لعملية الطفل النهائية)؟
كنت ألعب مع الكود التالي ، ويبدو أن معلومات حالة الخروج صالحة لبضع ثوان على الأقل بعد انتهاء الطفل ، لكنني لا أعرف كم من الوقت أو كيفية إبلاغ نظام التشغيل الذي لن أكون عليه الدعوة waitpid
تكرارا:
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Failed to fork\n");
return EXIT_FAILURE;
}
else if (pid == 0) { // code for child process
_exit(17);
}
else { // code for parent
sleep(3);
int status;
waitpid(pid, &status, 0);
waitpid(pid, &status, 0); // call `waitpid` again just to see if the first call had an effect
assert(WIFEXITED(status));
assert(WEXITSTATUS(status) == 17);
}
return EXIT_SUCCESS;
}
المحلول
نعم، waitpid
سيعمل بعد خروج الطفل. سيبقي نظام التشغيل إدخال عملية الطفل في جدول العملية (بما في ذلك حالة الخروج) حتى يتصل الأصل waitpid
(أو آخر wait
وظيفة العائلة) أو حتى يخرج الوالد (عند هذه النقطة يتم جمع الحالة بواسطة init
معالجة). هذا هو ما هي عملية "Zombie": عملية خرجت من قبل لا تزال مقيمة في جدول العملية لهذا الغرض بالضبط.
يجب أن يختفي إدخال العملية في الجدول بعد المكالمة الأولى waitpid
. أظن أن السبب في أنك في مثالك يبدو أنك قادر على الاتصال waitpid
مرتين ببساطة بسبب waitpid
لن يعدل status
حجة إذا pid
لم يعد موجودا. لذلك يجب أن تعمل المكالمة الأولى وتملأ status
, ، ويجب أن تكون المكالمة الثانية هي إرجاع رمز الخطأ وعدم التغيير status
. يمكنك التحقق من ذلك من خلال فحص قيم إرجاع waitpid
المكالمات و/أو استخدام اثنين مختلفين status
المتغيرات.
نصائح أخرى
يحافظ نظام التشغيل على إنهاء العملية في أ ولاية غيبوبة حتى والدها (والتي قد تكون init
إذا تم إنهاء عملية الوالد الأصلية سابقًا) تجمع حالة الخروج هذه wait(2)
استدعاء النظام. لذا فإن الجواب هو - حالة خروج العملية لا يصبح غير صالح.
نعم.
من صفحة الرجل:
الطفل الذي ينتهي ، ولكن لم يتم انتظاره يصبح "غيبوبة". تحافظ kernel على الحد الأدنى من المعلومات حول عملية الزومبي (PID ، حالة الإنهاء ، معلومات استخدام الموارد) من أجل السماح للوالد بإجراء انتظار لاحقًا للحصول على معلومات حول الطفل.