عربيالفرنسيةالإسبانية

Ad


OnWorks فافيكون

شرح_lca2010 - عبر الإنترنت في السحابة

قم بتشغيلشرح_lca2010 في مزود الاستضافة المجاني من OnWorks عبر Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

هذا هو الأمر شرح_lca2010 الذي يمكن تشغيله في مزود الاستضافة المجانية OnWorks باستخدام إحدى محطات العمل المجانية المتعددة عبر الإنترنت مثل Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

برنامج:

اسم


شرح_lca2010 - لم يتم العثور على وسيط: عندما يحين وقت التوقف عن محاولة القراءة الرعب(3)
عقل.

التحفيز


خطرت لي فكرة libexplain في أوائل الثمانينيات. كلما مكالمة نظام
إرجاع خطأ ، النواة تعرف بالضبط الخطأ الذي حدث ... وتضغط هذا في
أقل من 8 بت من تخطئ. مساحة المستخدم لديها حق الوصول إلى نفس البيانات مثل النواة
يجب أن تكون مساحة المستخدم ممكنة لمعرفة ما حدث بالضبط لاستفزاز الخطأ
العودة ، واستخدام هذا لكتابة رسائل خطأ جيدة.

هل من الممكن ان تكون بتلك السهولة؟

خطأ رسائل as براعة
غالبًا ما تكون رسائل الخطأ الجيدة هي مهام "واحد بالمائة" التي يتم تجاهلها عند الجدول الزمني
الضغط يضغط على مشروعك. ومع ذلك ، يمكن لرسالة خطأ جيدة أن تؤدي إلى
تحسن غير متناسب في تجربة المستخدم ، عندما يتجول المستخدم في حالة من الخوف
منطقة غير معروفة لا تصادف عادة. هذا المتحان ليس سهل.

بصفته مبرمجًا لليرقات ، لم يرى المؤلف مشكلة الخطأ (الدقيق تمامًا)
رسائل مثل هذه:
استثناء عائم (الأساسية ملقاة)
حتى تمت الإشارة إلى التفسير البديل غير المبرمج. لكن هذا ليس
الشيء الوحيد الخاطئ في رسائل خطأ يونكس. كم مرة ترى رسائل خطأ مثل:
$ ./غبي
لا يمكن فتح الملف
$
يوجد خياران للمطور في هذه المرحلة:

1.
يمكنك تشغيل مصحح أخطاء ، مثل جدب(1) ، أو

2.
يمكنك استخدام عنيد(1) أو حزم(1) للنظر في الداخل.

· تذكر أن المستخدمين قد لا يكون لديهم حتى إمكانية الوصول إلى هذه الأدوات ، ناهيك عن القدرة
لاستخدامها. (لقد مضى وقت طويل منذ ذلك الحين يونكس مبتدئ يعني "كتب فقط صورة واحدة؟
برنامج تشغيل الجهاز ".)

في هذا المثال ، ومع ذلك ، باستخدام عنيد(1) يكشف
$ عنيد -e تتبع = فتح ./غبي
فتح ("بعض / ملف" ، O_RDONLY) = -1 متاح (لا يوجد مثل هذا الملف أو الدليل)
لا يمكن فتح الملف
$
هذه معلومات أكثر بكثير مما توفره رسالة الخطأ. عادةً ما يكون ملف
يبدو أن شفرة المصدر غبية مثل هذا
int fd = open ("شئ ما"، O_RDONLY) ؛
إذا (fd <0)
{
fprintf (stderr، "لا يمكن فتح الملف \ n") ؛
خروج(1)
}
لم يتم إخبار المستخدم التي ملف ، وكذلك فشل في إخبار المستخدم التي خطأ. كان الملف
حتى هناك؟ هل كانت هناك مشكلة أذونات؟ يخبرك أنه كان يحاول فتح ملف
الملف ، ولكن ربما كان ذلك عن طريق الصدفة.

أمسك عصا الدليل واضرب معها مبرمج اليرقات. أخبره عنها رعب(3).
في المرة التالية التي تستخدم فيها البرنامج ، ستظهر لك رسالة خطأ مختلفة:
$ ./غبي
مفتوح: لا يوجد مثل هذا الملف أو الدليل
$
التقدم ، ولكن ليس ما كنا نتوقعه. كيف يمكن للمستخدم إصلاح المشكلة إذا كانت رسالة الخطأ
لا تخبره ما هي المشكلة؟ بالنظر إلى المصدر ، نرى
int fd = open ("شئ ما"، O_RDONLY) ؛
إذا (fd <0)
{
perror ("فتح") ؛
خروج(1)
}
حان الوقت لتشغيل آخر باستخدام عصا الدليل. هذه المرة ، تأخذ رسالة الخطأ خطوة واحدة
إلى الأمام وخطوة إلى الوراء:
$ ./غبي
شئ ما: لا يوجد ملف او مجلد
$
نحن نعرف الآن الملف الذي كان يحاول فتحه ، لكن لم نعد نعلم أنه كان كذلك جاكيت 2
التي فشلت. في هذه الحالة ربما لا تكون مهمة ، لكنها قد تكون مهمة بالنسبة لـ
مكالمات النظام الأخرى. كان من الممكن ان يكون يخلق(2) بدلاً من ذلك ، عملية تدل على ذلك
أذونات مختلفة ضرورية.
اسم ملف const char * = "شئ ما";
int fd = open (filename، O_RDONLY) ؛
إذا (fd <0)
{
perror (اسم الملف) ؛
خروج(1)
}
ولسوء الحظ ، فإن رمز المثال أعلاه هو نموذجي للمبرمجين غير اليرقيين أيضًا. وقت
لإخبار متعلم بادوان لدينا عن الرعب(3) استدعاء النظام.
$ ./غبي
جاكيت شئ ما: لا يوجد ملف او مجلد
$
هذا يزيد من المعلومات التي يمكن تقديمها للمستخدم. يبدو الرمز
هذه:
اسم ملف const char * = "شئ ما";
int fd = open (filename، O_RDONLY) ؛
إذا (fd <0)
{
fprintf (stderr ، "فتح٪ s:٪ s \ n" ، اسم الملف ، strerror (errno)) ؛
خروج(1)
}
الآن لدينا استدعاء النظام واسم الملف وسلسلة الخطأ. هذا يحتوي على جميع ملفات
المعلومات التي عنيد(1) مطبوعة. هذا جيد كما يحصل.

أو هو؟

القيود of رعب و الرعب
كانت المشكلة التي رآها المؤلف ، في الثمانينيات ، أن رسالة الخطأ غير مكتملة.
هل "لا يوجد مثل هذا الملف أو الدليل" يشير إلى "بعض"أو إلى"شيء" إملأ
ال "بعض" الدليل؟

نظرة سريعة على صفحة الرجل الخاصة بـ الرعب(3) يقول:
strerror - سلسلة إرجاع تصف رقم الخطأ
لاحظ جيدًا: إنه يصف الخطأ عدد، ليس الخطأ.

من ناحية أخرى ، النواة يعرف ما هو الخطأ. كانت هناك نقطة محددة في
رمز kernel ، بسبب حالة معينة ، حيث تشعبت شفرة kernel وقالت "لا".
هل يمكن لبرنامج فضاء المستخدم معرفة الشرط المحدد وكتابة خطأ أفضل
رسالة؟

ومع ذلك ، فإن المشكلة أعمق. ماذا لو حدثت المشكلة أثناء اقرأ(2) نظام
دعوة ، بدلاً من جاكيت (2) دعوة؟ إنه بسيط لرسالة الخطأ المرتبطة بـ
جاكيت (2) لتضمين اسم الملف ، هناك مباشرة. ولكن لتتمكن من تضمين اسم الملف
في الخطأ المرتبط ب اقرأ(2) استدعاء النظام ، يجب عليك تمرير اسم الملف بالكامل
الطريق إلى أسفل مكدس الاستدعاءات ، بالإضافة إلى واصف الملف.

وهنا هو الشيء الذي يزعج: النواة تعرف بالفعل اسم الملف للملف
واصف يرتبط بـ. لماذا يجب على المبرمج تمرير كل البيانات الزائدة عن الحاجة
الطريق إلى أسفل مكدس المكالمات فقط لتحسين رسالة خطأ قد لا يتم إصدارها أبدًا؟ في
في الواقع ، العديد من المبرمجين لا يزعجهم ، ورسائل الخطأ الناتجة هي الأسوأ
هنا.

ولكن كان ذلك في الثمانينيات ، في PDP1980 ، بموارد محدودة وعدم وجود مكتبات مشتركة. خلف
بعد ذلك ، لم يتم تضمين نكهة يونكس / إجراءات حتى في شكل بدائي ، و lsof(1) برنامج
كان على بعد أكثر من عقد. لذلك تم وضع الفكرة على الرف باعتبارها غير عملية.

مستوى اللامحدودية الدعم الفني
تخيل أنك تتمتع بمستوى الدعم اللانهائي. وصف وظيفتك يقول أنك لم تفعل ذلك أبدًا
أبدا يجب التحدث إلى المستخدمين. لماذا ، إذن ، لا يزال هناك تيار مستمر من الناس يريدون
أنت ، خبير يونكس المحلي ، لفك رسالة خطأ أخرى؟

الغريب ، بعد 25 عامًا ، على الرغم من نظام أذونات بسيط ، تم تنفيذه بالكامل
التناسق ، لا يزال معظم مستخدمي يونكس ليس لديهم أي فكرة عن كيفية فك تشفير "لا يوجد ملف أو دليل" ،
أو أي من رسائل الخطأ المشفرة الأخرى التي يشاهدونها كل يوم. أو ، على الأقل ، غامض لـ
لهم.

ألن يكون لطيفًا إذا لم يكن الدعم الفني من المستوى الأول بحاجة إلى فك تشفير رسائل الخطأ؟
ألن يكون من الجيد وجود رسائل خطأ يمكن للمستخدمين فهمها دون الاتصال
دعم تقني؟

هذه الأيام / إجراءات على Linux أكثر من قادر على توفير المعلومات اللازمة لفك الشفرة
الغالبية العظمى من رسائل الخطأ ، وتوجيه المستخدم إلى السبب المباشر لها
مشكلة. على الأنظمة ذات / إجراءات التنفيذ ، و lsof(1) يمكن ملء الأمر
العديد من الثغرات.

في عام 2008 ، حدث تدفق طلبات الترجمة للمؤلف كثيرًا. كان
حان الوقت لإعادة فحص تلك الفكرة البالغة من العمر 25 عامًا ، وكانت النتيجة libexplain.

باستخدام ال مكتبة


تحاول واجهة المكتبة أن تكون متسقة ، حيثما أمكن ذلك. لنبدأ بـ
سبيل المثال باستخدام الرعب(3):
إذا (إعادة تسمية (old_path، new_path) <0)
{
fprintf (stderr، "إعادة تسمية٪ s٪ s:٪ s \ n"، old_path، new_path،
strerror (errno)) ؛
خروج(1)
}
الفكرة من libexplain هي توفير ملف الرعب(3) ما يعادل كل استدعاء النظام
مصممة خصيصًا لاستدعاء النظام هذا ، بحيث يمكن أن توفر خطأً أكثر تفصيلاً
تحتوي على الكثير من المعلومات التي تراها ضمن عنوان القسم "أخطاء"
2 و3 رجل صفحات ، مدعومة بمعلومات حول الظروف الفعلية ، والحجة الفعلية
القيم وقيود النظام.

الاشارات الإطار
الرعب(3) الاستبدال:
إذا (إعادة تسمية (old_path، new_path) <0)
{
fprintf (stderr، "٪ s \ n" ،شرح_rename (old_path، new_path)) ؛
خروج(1)
}

إرنو الإطار
من الممكن أيضا تمرير صريح تخطئ(3) القيمة ، إذا كان يجب عليك أولاً القيام ببعض
المعالجة التي من شأنها أن تزعجك تخطئ، مثل استعادة الأخطاء:
إذا (إعادة تسمية (old_path ، new_path <0))
{
int old_errno = errno ؛
الكود أن يزعج تخطئ
fprintf (stderr، "٪ s \ n" ،شرح_errno_rename (old_errno،
old_path ، new_path)) ؛
خروج(1)
}

موضوع متعدد الحالات
بعض التطبيقات متعددة الخيوط ، وبالتالي فهي غير قادرة على مشاركة libexplain الداخلية
متعادل. يمكنك توفير المخزن المؤقت الخاص بك باستخدام
إذا (إلغاء الربط (اسم المسار))
{
رسالة شار [3000] ؛
شرح_رسالة_ unlink (رسالة ، حجم(رسالة) ، اسم المسار) ؛
error_dialog(رسالة)؛
عودة -1 ؛
}
ومن أجل الاكتمال ، كلاهما تخطئ(3) وخيط ‐ آمن:
ssize_t nbytes = read (fd، data، sizeof (data)) ؛
إذا (ن بايت <0)
{
رسالة شار [3000] ؛
int old_errno = errno ؛
خطأ استرجاع
شرح_رسالة_رسالة_قراءة (رسالة ، حجم(رسالة)،
old_errno ، fd ، data ، sizeof (data)) ؛
error_dialog(رسالة)؛
عودة -1 ؛
}

هذه بدائل لـ strerror_r(3) ، على الأنظمة التي لديها ذلك.

السطح البيني السكر
تمت إضافة مجموعة من الوظائف كوظائف ملائمة ، لجذب المبرمجين لاستخدام
مكتبة libexplain ، أصبحت أكثر وظائف libexplain استخدامًا للمؤلف في
برامج سطر الأوامر:
int fd =شرح_creat_or_die (اسم الملف ، 0666) ؛
تحاول هذه الوظيفة إنشاء ملف جديد. إذا لم يستطع ، فإنه يطبع رسالة خطأ و
مخارج مع EXIT_FAILURE. إذا لم يكن هناك خطأ ، فإنه يقوم بإرجاع واصف الملف الجديد.

وظيفة ذات صلة:
int fd = شرح_creat_on_error (اسم الملف ، 0666) ؛
سيطبع رسالة الخطأ عند الفشل ، ولكنه يعرض أيضًا نتيجة الخطأ الأصلية ، و
تخطئ(3) غير متحرش كذلك.

الكل ال آخر نظام المكالمات
بشكل عام ، كل استدعاء نظام له ملف التضمين الخاص به
#يشملالاسم.h>
التي تحدد النماذج الأولية للوظائف لست وظائف:

· يشرح_الاسم,

· شرح_errno_الاسم,

· شرح_رسالة_الاسم,

· شرح_رسالة_errno_الاسم,

· يشرح_الاسم_or_die و

· يشرح_الاسم_عند_الخطأ.

يحتوي كل نموذج أولي لوظيفة على وثائق Doxygen ، وهذه الوثائق is ليس جردت
عندما يتم تثبيت ملفات التضمين.

انتظر(2) استدعاء النظام (والأصدقاء) لديهم بعض المتغيرات الإضافية التي تفسر الفشل أيضًا
لتكون حالة خروج ليست EXIT_SUCCESS. وهذا ينطبق على نظام(3) و pإغلاق(3) مثل
حسن.

تشمل التغطية 221 مكالمة نظام و 547 طلب ioctl. هناك الكثير من النظام
دعوات لتنفيذها. استدعاءات النظام التي لا تعود أبدًا ، مثل خروج(2) ، غير موجودة
في المكتبة ، ولن يكون أبدًا. ال EXEC عائلة مكالمات النظام . مدعوم ، لأن
يعودون عندما يكون هناك خطأ.

قط
هذا ما يمكن أن يبدو عليه برنامج "cat" الافتراضي ، مع الإبلاغ الكامل عن الأخطاء ،
باستخدام libexplain.
#يشمل
#تتضمن
#يشمل
هناك واحد مشمول في libexplain ، بالإضافة إلى المشتبه بهم المعتادين. (إذا كنت ترغب في تقليل
تحميل المعالج المسبق ، يمكنك استخدام محددالاسم.h> يتضمن.)
الفراغ ثابت
عملية (FILE * fp)
{
ل (؛؛)
{
شار عازلة [4096] ؛
size_t n = expl_fread_or_die (المخزن المؤقت ، 1 ، sizeof (المخزن المؤقت) ، fp) ؛
إذا (! ن)
كسر؛
شرح_fwrite_or_die (المخزن المؤقت ، 1 ، n ، stdout) ؛
}
}
عملية المعالجة وظيفة نسخ دفق ملف إلى الإخراج القياسي. في حالة حدوث خطأ
بالنسبة للقراءة أو الكتابة ، يتم الإبلاغ عنها (وسيتم تضمين اسم المسار في ملف
خطأ) ويخرج الأمر مع EXIT_FAILURE. نحن لا نقلق حتى بشأن تتبع ملفات
أسماء المسارات ، أو تمريرها إلى أسفل مكدس الاستدعاءات.
مادبا
main (int argc، char ** argv)
{
ل (؛؛)
{
int c = getopt (argc، argv، "o:") ؛
إذا (c == EOF)
كسر؛
مفتاح (ج)
{
الحالة "س":
شرح_freopen_or_die (optarg ، "w" ، stdout) ؛
كسر؛
الجزء الممتع من هذا الرمز هو أن libexplain يمكنه الإبلاغ عن الأخطاء بما فيها ال اسم المسار حتى
إذا كنت لا إعادة فتح stdout صراحة كما هو الحال هنا. نحن لا نقلق حتى
تتبع اسم الملف.
الافتراضي:
fprintf (stderr، "الاستخدام:٪ ss [-o ] ...\ن"،
argv [0]) ؛
عودة EXIT_FAILURE ؛
}
}
إذا (optind == argc)
عملية (stdin) ؛
آخر
{
while (optind <argc)
{
FILE * fp =شرح_fopen_or_die (argv [optind] ++، "r") ؛
عملية (fp) ؛
شرح_fclose_or_die (fp) ؛
}
}
سيتم إغلاق الإخراج القياسي ضمنيًا ، ولكن بعد فوات الأوان بالنسبة لتقرير الخطأ
تم إصداره ، لذلك نقوم بذلك هنا ، فقط في حالة عدم كتابة I / O المؤقت أي شيء بعد ، و
يوجد خطأ ENOSPC أو شيء من هذا القبيل.
Explan_fflush_or_die (stdout) ؛
عودة EXIT_SUCCESS ؛
}
هذا كل شئ. الإبلاغ عن خطأ كامل ، رمز واضح.

روستي حجم of السطح البيني الطبيعة
بالنسبة لأولئك الذين ليسوا على دراية به ، رستي راسل "كيف أجعل من الصعب إساءة استخدام هذا؟"
الصفحة يجب قراءتها لمصممي API.
http://ozlabs.org/~rusty/index.cgi/tech/2008-03‐30.html

10 انها مستحيل إلى دولار فقط واحصل على خصم XNUMX% على جميع خطأ.

يجب أن تكون الأهداف عالية وطموحة حتى لا تحققها وتعتقد أنك كذلك
تنتهي عندما لا تكون كذلك.

تكتشف مكتبة libexplain المؤشرات الزائفة والعديد من معلمات استدعاء النظام الزائفة الأخرى ،
ويحاول بشكل عام تجنب segfaults حتى في أكثر الظروف صعوبة.

تم تصميم مكتبة libexplain لتكون آمنة للخيط. من المرجح أن يكون هناك استخدام أكثر واقعية في العالم
تكشف عن الأماكن التي يمكن تحسين هذا.

أكبر مشكلة مع أسماء الوظائف الفعلية نفسها. لأن C لا تملك
فضاءات الاسم ، تستخدم مكتبة libexplain دائمًا بادئة name. هذا ال
الطريقة التقليدية لإنشاء مساحة اسم مستعارة لتجنب تعارض الرموز.
ومع ذلك ، فإنه ينتج عنه بعض الأسماء التي تبدو غير طبيعية.

9. مترجم or وصلات ولن اسمحوا لصحتك! دولار فقط واحصل على خصم XNUMX% على جميع it خطأ.

والخطأ الشائع هو استخدام expl_open حيث كان الغرض من الشرح open_open_or_die.
لحسن الحظ ، غالبًا ما يُصدر المترجم خطأ في النوع في هذه المرحلة (على سبيل المثال لا يمكن التنازل
const char * rvalue إلى قيمة int lvalue).

8. مترجم سوف حذر if لصحتك! دولار فقط واحصل على خصم XNUMX% على جميع it خطأ.

إذا تم استخدامشرح_رينامي عندما كان الغرض من شرح_رينام_أو_دي ، أن يؤدي ذلك إلى حدوث أشياء أخرى
مشاكل. يحتوي GCC على سمة دالة warn_unused_result مفيدة ، و libexplain
مكتبة تعلقها على كل شرح_الاسم المكالمات الوظيفية لإصدار تحذير عندما تقوم بذلك
ارتكب هذا الخطأ. ادمج هذا مع دول مجلس التعاون الخليجي -خطأ لترقية هذا إلى المستوى 9 من الخير.

7. واضح تستخدم is (من المحتمل) ال تصحيح .

تم اختيار أسماء الوظائف للتعبير عن معناها ، ولكن هذا ليس دائمًا
ناجح. أثناء الشرحالاسم_أو_دي وشرح_الاسم_الخطأ وصفية إلى حد ما ،
يصعب فك تشفير المتغيرات الآمنة ذات الخيط الأقل استخدامًا. النماذج الأولية للوظيفة تساعد في
المترجم نحو الفهم ، وتعليقات Doxygen في ملفات الرأس تساعد المستخدم
نحو التفاهم.

6. الاسم يروي لصحتك! كيف إلى تستخدم هنا.

من المهم بشكل خاص قراءة شرح_الاسم_or_die كـ "شرح (الاسم أو مت)".
استخدام بادئة متناسقةشرح_الاسم ‐ مسافة له بعض الآثار الجانبية المؤسفة في ملف
قسم الوضوح كذلك.

يشير ترتيب الكلمات في الأسماء أيضًا إلى ترتيب الوسائط. الحجة
قوائم دائما النهاية بنفس الوسيطات التي تم تمريرها إلى استدعاء النظام ؛ من جميع of هم. إذا
تظهر _errno_ في الاسم ، وتسبق وسيطتها دائمًا وسائط استدعاء النظام. لو
تظهر _message_ في الاسم ، وتأتي دائمًا وسيطتيها أولاً.

5. Do it حق or it سوف استراحة at مدة العرض.

تكتشف مكتبة libexplain المؤشرات الزائفة والعديد من معلمات استدعاء النظام الزائفة الأخرى ،
ويحاول بشكل عام تجنب segfaults حتى في أكثر الظروف صعوبة. أنه ينبغي
لا تتعطل أبدًا في وقت التشغيل ، ولكن الاستخدام الواقعي بشكل أكبر سيؤدي بلا شك إلى تحسين ذلك.

تستهدف بعض رسائل الخطأ المطورين والمشرفين بدلاً من المستخدمين النهائيين ، مثل هذا
يمكن أن تساعد في حل الخلل. ليس هناك الكثير من "الاستراحة في وقت التشغيل" بقدر ما "تكون مفيدة في
وقت التشغيل "(بعد شريط استدعاء النظام).

4. تابعني: مشترك اتفاقية و عليك دولار فقط واحصل على خصم XNUMX% على جميع it حق.

نظرًا لأن لغة C لا تحتوي على مسافات أسماء ، فإن مكتبة libexplain تستخدم دائمًا اسمشرح
بادئة. هذه هي الطريقة التقليدية لإنشاء مساحة اسم مستعارة من أجل تجنبها
تعارض الرموز.

تتطابق الوسائط اللاحقة لجميع استدعاء libexplain مع استدعاء النظام لهم
يصفون. يهدف هذا إلى توفير اتفاقية متسقة مشتركة مع
النظام يدعو أنفسهم.

3. عرض ال توثيق و عليك دولار فقط واحصل على خصم XNUMX% على جميع it حق.

تهدف مكتبة libexplain إلى الحصول على وثائق Doxygen كاملة لكل منها
استدعاء API العام (وداخليًا أيضًا).

رسالة CONTENT


يشبه العمل على libexplain النظر إلى الجانب السفلي من سيارتك عندما تكون في وضع التشغيل
الرافعة عند الميكانيكي. هناك بعض الأشياء القبيحة هناك ، بالإضافة إلى الطين والوحل ، و
نادرا ما يراه المستخدمون. يجب أن تكون رسالة الخطأ الجيدة مفيدة ، حتى بالنسبة للمستخدم
لقد كان محظوظًا بما يكفي لعدم الاضطرار إلى النظر إلى الجانب السفلي كثيرًا ، وكذلك أيضًا
إعلامية للميكانيكي الذي يستمع إلى وصف المستخدم عبر الهاتف. هذا هو
ليست مهمة سهلة.

بالرجوع إلى مثالنا الأول ، قد ترغب الشفرة في هذا إذا كانت تستخدم libexplain:
int fd =شرح_open_or_die ("بعض / شيء" ، O_RDONLY ، 0) ؛
سوف تفشل مع رسالة خطأ مثل هذه
فتح (اسم المسار = "بعض / ملف" ، العلامات = O_RDONLY) فشل ، لا يوجد مثل هذا الملف أو الدليل
(2، ENOENT) لأنه لا يوجد دليل "بعض" في الدليل الحالي
هذا ينقسم إلى ثلاث قطع
نظام استدعاء فشل، خطأ في النظام لان
تفسير

قبل لأن
من الممكن رؤية جزء الرسالة قبل "لأن" على أنه فني أكثر من اللازم لغير
المستخدمين التقنيين ، في الغالب كنتيجة لطباعة النظام بدقة على استدعاء نفسه في
بداية رسالة الخطأ. ويبدو أن عنيد(1) الإخراج ، لمكافأة المهوس
نقاط.
فتح (اسم المسار = "بعض / ملف" ، العلامات = O_RDONLY) فشل ، لا يوجد مثل هذا الملف أو الدليل
(2 ، كافي)
هذا الجزء من رسالة الخطأ ضروري للمطور عندما يكتب الكود ،
وعلى نفس القدر من الأهمية للمشرف الذي يتعين عليه قراءة تقارير الأخطاء وإصلاح الأخطاء في
شفرة. تقول بالضبط ما فشل.

إذا لم يتم تقديم هذا النص للمستخدم ، فلن يتمكن المستخدم من نسخه ‐ ولصقه في ملف
تقرير الخطأ ، وإذا لم يكن موجودًا في تقرير الخطأ ، فلا يمكن للمشرف معرفة ما حدث بالفعل
خطأ.

كثيرا ما سيستخدم فريق التكنولوجيا عنيد(1) أو حزم(1) للحصول على هذه المعلومات الدقيقة ، ولكن
هذا الطريق غير مفتوح عند قراءة تقارير الأخطاء. نظام مراسل الأخطاء بعيد جدًا
بعيدًا ، والآن ، في حالة مختلفة تمامًا. وبالتالي ، يجب أن تكون هذه المعلومات في
تقرير الشوائب ، مما يعني أنه يجب أن يكون في رسالة الخطأ.

يعطي تمثيل استدعاء النظام أيضًا سياقًا لبقية الرسالة. عند الحاجة
تنشأ ، قد تتم الإشارة إلى وسيطة استدعاء النظام المخالفة بالاسم في الشرح
بعد "بسبب". بالإضافة إلى ذلك ، يتم اقتباس جميع السلاسل بالكامل ومهرب منها ، لذلك
لن تتسبب الأسطر الجديدة المضمنة والأحرف غير المطبوعة في انتقال الجهاز الطرفي للمستخدم
أحمق.

خطأ في النظام هو ما يخرج منه الرعب(2) بالإضافة إلى رمز الخطأ. الصبر و
يمكن لمسؤولي النظام الخبراء التوقف عن القراءة في هذه المرحلة ، ولكن تجربة المؤلف حتى الآن هي
أن القراءة أكثر مجزية. (إذا لم تكن مجزية ، فمن المحتمل أن تكون منطقة
libexplain التي يمكن تحسينها. نرحب بإسهامات الكود بالطبع.)

بعد لأن
هذا هو الجزء من رسالة الخطأ الموجه للمستخدمين غير التقنيين. يتطلع إلى ما وراء ذلك
وسيطات استدعاء النظام البسيطة ، ويبحث عن شيء أكثر تحديدًا.
لا يوجد دليل "بعض" في الدليل الحالي
يحاول هذا الجزء شرح السبب القريب للخطأ بلغة واضحة ، وهو
هنا أن التدويل ضروري.

بشكل عام ، فإن السياسة هي تضمين أكبر قدر ممكن من المعلومات ، بحيث يكون المستخدم
لا تحتاج إلى البحث عنه (ولا تتركه خارج تقرير الخطأ).

التجارة في الخارج
تم تدويل معظم رسائل الخطأ في مكتبة libexplain. هناك
لا توجد ترجمات حتى الآن ، لذلك إذا كنت تريد التفسيرات بلغتك الأم ،
الرجاء المساهمة.

الشرط "الأكثر" ، أعلاه ، يتعلق بحقيقة أن مفهوم الإثبات
التنفيذ لم يشمل دعم التدويل. قاعدة التعليمات البرمجية يجري
تنقيح تدريجي ، عادة نتيجة لإعادة بناء الرسائل بحيث كل خطأ
تظهر سلسلة الرسالة في الرمز مرة واحدة بالضبط.

تم توفير اللغات التي تحتاج إلى تجميع أجزاء من
نظام استدعاء فشل، خطأ في النظام لان تفسير
بترتيب مختلف للقواعد النحوية الصحيحة في رسائل الخطأ المترجمة.

بعد الوفاة
هناك أوقات لا يزال يتعين فيها على البرنامج استخدام libexplain ، ولا يمكنك استخدام عنيد1
أيضاً. هناك شرح(1) مرفق مع libexplain يمكن استخدامه
فك تشفير رسائل الخطأ ، إذا لم تتغير حالة النظام الأساسي كثيرًا.
$ شرح إعادة تسمية فو / tmp / بار / باز -e كافي
إعادة تسمية (oldpath = "foo" ، newpath = "/ tmp / bar / baz") فشل ، لا يوجد مثل هذا الملف أو الدليل
(2، ENOENT) لأنه لا يوجد دليل "شريط" في المسار الجديد "/ تمة" الدليل
$
لاحظ كيف يتم حل غموض المسار باستخدام اسم وسيطة استدعاء النظام. ل
بالطبع ، عليك أن تعرف الخطأ واستدعاء النظام شرح(1) أن تكون مفيدة. باعتباره
جانباً ، هذه إحدى الطرق التي تستخدمها مجموعة الاختبار التلقائي libexplain للتحقق من ذلك
libexplain يعمل.

فلسفة
"أخبرني بكل شيء ، بما في ذلك الأشياء التي لم أكن أعرف أن أبحث عنها."

يتم تنفيذ المكتبة بطريقة أنه عندما يتم ربطها بشكل ثابت ، فقط الرمز هو أنت
في الواقع سيتم ربط الاستخدام. يتم تحقيق ذلك من خلال وجود وظيفة واحدة لكل ملف مصدر ،
كلما كان ذلك ممكنا.

عندما يكون من الممكن توفير المزيد من المعلومات ، سيقوم libexplain بذلك. كلما قل المستخدم
يجب أن يتعقبوا لأنفسهم ، كان ذلك أفضل. هذا يعني أن UIDs مصحوبة بامتداد
اسم المستخدم ، GIDs مصحوبة باسم المجموعة ، PIDs مصحوبة بالعملية
الاسم ، واصفات الملفات والجداول مصحوبة باسم المسار ، إلخ.

عند تحديد المسارات ، في حالة عدم وجود مكون مسار ، سيبحث libexplain عن ما شابه
أسماء ، من أجل اقتراح بدائل للأخطاء المطبعية.

تحاول مكتبة libexplain استخدام أقل قدر ممكن من الكومة ، وعادة لا شيء. هذا هو
لتجنب اضطراب حالة العملية ، قدر الإمكان ، على الرغم من أنه في بعض الأحيان
لا مفر منه.

تحاول مكتبة libexplain أن تكون خيطًا آمنًا ، من خلال تجنب المتغيرات العالمية ، وحفظها
الدولة على المكدس قدر الإمكان. هناك مخزن مؤقت واحد مشترك للرسائل ، و
تم توثيق الوظائف التي تستخدمه على أنها ليست آمنة للتداول.

لا تزعج مكتبة libexplain معالجات إشارة العملية. هذا يجعل
تحديد ما إذا كان المؤشر سيخطئ التحدي ، ولكن ليس مستحيلًا.

عندما تكون المعلومات متاحة عبر مكالمة نظام وكذلك متوفرة من خلال a / إجراءات
الدخول ، يفضل استدعاء النظام. هذا لتجنب الإخلال بحالة العملية.
هناك أيضًا أوقات لا تتوفر فيها واصفات ملفات.

يتم تجميع مكتبة libexplain بدعم ملف كبير. لا يوجد كبير / صغير
فُصام. حيث يؤثر ذلك على أنواع الوسيطات في واجهة برمجة التطبيقات ، وسيصدر الخطأ
إذا كان الملف الكبير اللازم لتعريف غائب.

FIXME: هناك حاجة إلى العمل للتأكد من معالجة حصص نظام الملفات في التعليمات البرمجية. هذا
ينطبق على البعض com.getrlimit(2) الحدود كذلك.

هناك حالات عندما تكون مسارات الأقارب غير مفيدة. على سبيل المثال: شياطين النظام ،
الخوادم والعمليات الخلفية. في هذه الحالات ، يتم استخدام المسارات المطلقة في الخطأ
التفسيرات.

PATH القرار


نسخة قصيرة: انظر الحل(7).

نسخة طويلة: معظم المستخدمين لم يسمعوا بها من قبل الحل(7) والعديد من المستخدمين المتقدمين
لم يقرؤوه من قبل. هذه نسخة مشروحة:

خطوة 1: آبدأ of ال قرار عملية المعالجة
إذا بدأ اسم المسار بحرف الشرطة المائلة ("/") ، فإن دليل بدء البحث هو
الدليل الجذر لعملية الاستدعاء.

إذا لم يبدأ اسم المسار بحرف الشرطة المائلة ("/") ، فيتم البحث عن البداية
دليل عملية القرار هو دليل العمل الحالي للعملية.

خطوة 2: سير على طول ال مسار
قم بتعيين دليل البحث الحالي إلى دليل بدء البحث. الآن ، لكل شخص غير
المكون الأخير لاسم المسار ، حيث يكون المكون عبارة عن سلسلة فرعية محددة بشرطة مائلة ("/")
الأحرف ، يتم البحث عن هذا المكون في دليل البحث الحالي.

إذا لم يكن للعملية إذن بحث في دليل البحث الحالي ، فإن EACCES
تم إرجاع الخطأ ("تم رفض الإذن").
فتح (اسم المسار = "/home/archives/.ssh/private_key" ، فشلت العلامات = O_RDONLY) ،
تم رفض الإذن (13 ، EACCES) لأن العملية لا تحتوي على إذن بحث
إلى دليل اسم المسار "/home/archives/.ssh" ، العملية فعالة GID 1000
"pmiller" لا يتطابق مع دليل المالك 1001 "المحفوظات" لذلك المالك
يتم تجاهل وضع الإذن "rwx" ووضع إذن الآخرين هو "---" و
العملية ليست لها امتيازات (ليس لديها قدرة DAC_READ_SEARCH)

إذا لم يتم العثور على المكون ، يتم إرجاع خطأ ENOENT ("لا يوجد مثل هذا الملف أو الدليل").
فشل فك الارتباط (اسم المسار = "/ home / microsoft / rubbish") ، لا يوجد مثل هذا الملف أو الدليل (2 ،
ENOENT) لأنه لا يوجد دليل "Microsoft" في اسم المسار "/ الرئيسية" الدليل

يوجد أيضًا بعض الدعم للمستخدمين عندما يخطئون في كتابة أسماء المسار ، ويقدمون اقتراحات متى
تم إرجاع ENOENT:
فتح (اسم المسار = "/user/include/fcntl.h" ، أعلام = O_RDONLY) فشل ، لا يوجد مثل هذا الملف أو
الدليل (2 ، ENOENT) لأنه لا يوجد دليل "مستخدم" في اسم المسار "/"
الدليل ، هل تقصد دليل "usr" بدلاً من ذلك؟

إذا تم العثور على المكون ، لكنه ليس دليلًا ولا ارتباطًا رمزيًا ، فإن ENOTDIR
تم إرجاع الخطأ ("ليس دليلاً").
open (pathname = "/home/pmiller/.netrc/lca" ، flags = O_RDONLY) فشل ، وليس
الدليل (20 ، ENOTDIR) لأن الملف العادي ".netrc" في اسم المسار
يتم استخدام دليل "/ home / pmiller" كدليل عندما لا يكون كذلك

إذا تم العثور على المكون وكان دليلًا ، فسنقوم بتعيين دليل البحث الحالي على ذلك
الدليل ، وانتقل إلى المكون التالي.

إذا تم العثور على المكون وكان رابطًا رمزيًا (رابط رمزي) ، فسنحل أولاً هذا الرمز
link (مع دليل البحث الحالي كدليل بدء البحث). عند الخطأ ، هذا
تم إرجاع الخطأ. إذا لم تكن النتيجة دليلاً ، فسيتم إرجاع خطأ ENOTDIR.
فشل فك الارتباط (اسم المسار = "/ tmp / التعلق / القمامة") ، لا يوجد ملف أو دليل (2 ،
ENOENT) لأن الرابط الرمزي "المتدلي" في اسم المسار "/ تمة" الدليل
يشير إلى "لا مكان" غير موجود
إذا كان تحليل الارتباط الرمزي ناجحًا وأعاد دليلًا ، فسنقوم بتعيين الملف الحالي
ابحث عن دليل ذلك الدليل ، وانتقل إلى المكون التالي. نلاحظ أن
عملية القرار هنا تتضمن العودية. من أجل حماية النواة من المكدس
تجاوز ، وكذلك للحماية من رفض الخدمة ، هناك حدود على الحد الأقصى
عمق العودية ، وعلى أقصى عدد من الروابط الرمزية المتبعة. خطأ ELOOP هو
يتم إرجاعها عند تجاوز الحد الأقصى ("مستويات كثيرة جدًا من الروابط الرمزية").
فتح (اسم المسار = "/ tmp / المتدلية" ، العلامات = O_RDONLY) فشل ، مستويات كثيرة جدًا من
روابط رمزية (40 ، ELOOP) لأنه تمت مصادفة حلقة ارتباط رمزية في
اسم المسار ، بدءًا من "/ tmp / hangling"
من الممكن أيضًا الحصول على خطأ ELOOP أو EMLINK إذا كان هناك عدد كبير جدًا من الارتباطات الرمزية ، ولكن لا
تم الكشف عن حلقة.
فتح (اسم المسار = "/ tmp / rabbit ‐ hole" ، الأعلام = O_RDONLY) فشل ، مستويات كثيرة جدًا من
الروابط الرمزية (40 ، ELOOP) نظرًا لوجود عدد كبير جدًا من الروابط الرمزية في
اسم المسار (8)
لاحظ كيف تتم طباعة الحد الفعلي أيضًا.

خطوة 3: ال نهائي دخول
البحث عن المكون النهائي لاسم المسار يسير تمامًا مثل كل العناصر الأخرى
المكونات ، كما هو موضح في الخطوة السابقة ، مع اختلافين:

(ط) لا يلزم أن يكون المكون النهائي دليلاً (على الأقل بقدر دقة المسار
العملية المعنية. قد يكون من الضروري أن يكون دليلًا ، أو ليس دليلًا ، بسبب
متطلبات استدعاء النظام المحدد).

(الثاني)
ليس بالضرورة أن يكون خطأ إذا لم يتم العثور على المكون النهائي ؛ ربما نحن فقط
إنشائه. يتم وصف التفاصيل الخاصة بمعالجة الإدخال النهائي في
صفحات دليل مكالمات النظام المحددة.

(الثالث)
من الممكن أيضًا وجود مشكلة مع المكون الأخير إذا كان ارتباطًا رمزيًا
ولا ينبغي اتباعه. على سبيل المثال ، باستخدام ملف جاكيت (2) علم O_NOFOLLOW:
فتح (اسم المسار = "a ‐ symlink" ، فشلت الأعلام = O_RDONLY | O_NOFOLLOW) ، مستويات كثيرة جدًا من
روابط رمزية (ELOOP) لأنه تم تحديد O_NOFOLLOW لكن اسم المسار يشير إلى ملف
ارتباط رمزي

(رابعا)
من الشائع أن يرتكب المستخدمون أخطاء عند كتابة أسماء المسار. مكتبة libexplain
يحاول تقديم اقتراحات عند إرجاع ENOENT ، على سبيل المثال:
فتح (اسم المسار = "/usr/include/filecontrl.h" ، أعلام = O_RDONLY) فشل ، لا يوجد مثل هذا الملف أو
الدليل (2، ENOENT) نظرًا لعدم وجود ملف "filecontrl.h" العادي في اسم المسار
"/ البيرة / تتضمن"الدليل ، هل تقصد الملف العادي" fcntl.h "بدلاً من ذلك؟

(XNUMX) من الممكن أيضًا أن يكون المكون النهائي مطلوبًا ليكون شيئًا آخر غير a
ملف عادي:
readlink (اسم المسار = "ملف a ‐ فقط" ، فشل البيانات = 0x7F930A50 ، حجم البيانات = 4097) ،
وسيطة غير صالحة (22 ، EINVAL) لأن اسم المسار هو ملف عادي ، وليس رابطًا رمزيًا

(السادس)
FIXME: التعامل مع البت "t".

حدود
هناك عدد من الحدود فيما يتعلق بأسماء المسار وأسماء الملفات.

حد طول اسم المسار
يوجد حد أقصى لطول أسماء المسار. إذا كان اسم المسار (أو بعض الوسيط
اسم المسار الذي تم الحصول عليه أثناء حل الروابط الرمزية) طويل جدًا ، وهو ENAMETOOLONG
تم إرجاع الخطأ ("اسم الملف طويل جدًا"). لاحظ كيف يتم تضمين حد النظام
في رسالة الخطأ.
مفتوح (اسم المسار = "طويل جدا"، فشلت العلامات = O_RDONLY) ، اسم الملف طويل جدًا (36 ،
ENAMETOOLONG) لأن اسم المسار يتجاوز طول المسار الأقصى للنظام (4096)

حد طول اسم الملف
بعض متغيرات يونكس لها حد لعدد البايت في كل مكون من مكونات المسار.
بعضهم يتعامل مع هذا بصمت ، والبعض الآخر يعطي ENAMETOOLONG ؛ في libexplain
استخدامات المكتبة مسار(3) _PC_NO_TRUNC لمعرفة أيها. إذا حدث هذا الخطأ ، فإن ملف
مكتبة libexplain ستذكر الحد في رسالة الخطأ ، الحد هو
تم الحصول عليها من مسار(3) _PC_NAME_MAX. لاحظ كيف يتم تضمين حد النظام
في رسالة الخطأ.
مفتوح (اسم المسار = "system7 / only-had-14-حرفاً"، الإشارات = O_RDONLY) فشل ، الملف
الاسم طويل جدًا (36 ، ENAMETOOLONG) لأن المكون "المكون من 14 حرفًا فقط" هو
أطول من حد النظام (14)

اسم المسار فارغ
في نظام التشغيل Unix الأصلي ، يشير اسم المسار الفارغ إلى الدليل الحالي.
في الوقت الحاضر ، يأمر POSIX بأنه يجب ألا يتم حل اسم المسار الفارغ بنجاح.
فتح (اسم المسار = "" ، فشل العلامات = O_RDONLY) ، لا يوجد مثل هذا الملف أو الدليل (2 ،
ENOENT) لأن POSIX يقرر أنه لا يجب حل اسم المسار الفارغ
بنجاح

أذونات
تتكون أجزاء الإذن الخاصة بالملف من ثلاث مجموعات من ثلاث بتات. المجموعة الأولى من
ثلاثة عندما يكون معرف المستخدم الفعال لعملية الاتصال مساويًا لمعرف المالك الخاص بـ
ملف. يتم استخدام المجموعة الثانية المكونة من ثلاثة عندما يكون معرف المجموعة للملف إما يساوي
معرف المجموعة الفعال لعملية الاستدعاء ، أو هو أحد معرفات المجموعة التكميلية لـ
عملية الاتصال. عندما لا يحمل أي منهما ، يتم استخدام المجموعة الثالثة.
مفتوح (اسم المسار = "/ الخ / باسود"، flags = O_WRONLY) فشل، الإذن مرفوض (13،
EACCES) لأن العملية ليس لديها إذن كتابة إلى "passwd" العادي
ملف في اسم المسار "/ الخ"الدليل ، العملية الفعالة UID 1000" pmiller "
لا يتطابق مع مالك الملف العادي 0 "root" لذلك وضع إذن المالك "rw-"
تم تجاهله ، ووضع إذن الآخرين هو "r -" ، والعملية ليست مميزة
(لا يحتوي على إمكانية DAC_OVERRIDE)
يتم إعطاء مساحة كبيرة لهذا التفسير ، لأن معظم المستخدمين لا يعرفون ذلك
هي كيف يعمل نظام الأذونات. على وجه الخصوص: المالك والمجموعة وغيرهم
الأذونات حصرية ، فهي ليست "أو" معًا.

غريب لأي لبس مثير للإعجاب نظام المكالمات


غالبًا ما تكشف عملية كتابة معالج خطأ محدد لكل استدعاء نظام
مراوغات مثيرة للاهتمام وظروف حدودية ، أو غامضة تخطئ(3) القيم.

ENOMEDIUM ، لا متوسط وجدت
كان عمل نسخ قرص مضغوط مصدر عنوان هذه الورقة.
$ dd إذا = / ديف / قرص مدمج من = fubar.iso
dd: فتح "/ dev / cdrom": لم يتم العثور على وسيط
$
تساءل المؤلف عن سبب إخبار جهاز الكمبيوتر الخاص به بأنه لا يوجد شيء اسمه نفساني
واسطة. بصرف النظر عن حقيقة أن عددًا كبيرًا من الناطقين باللغة الإنجليزية ليسوا كذلك
تدرك حتى أن "media" هي جمع ، ناهيك عن أن "الوسيط" هو مفردها ، الخيط
عاد من قبل الرعب(3) بالنسبة إلى ENOMEDIUM ، فهي مقتضبة بحيث تكون خالية تمامًا تقريبًا
المحتوى.

متى جاكيت (2) تعيد ENOMEDIUM ، سيكون من الجيد أن تقوم مكتبة libexplain بتوسيع ملف
القليل على هذا ، بناءً على نوع محرك الأقراص. على سبيل المثال:
... لأنه لا يوجد قرص في محرك الأقراص المرنة
... بسبب عدم وجود قرص في محرك الأقراص المضغوطة
... لأنه لا يوجد شريط في محرك الشريط
... لأنه لا توجد شريحة ذاكرة في قارئ البطاقات

وهكذا حدث ...
open (pathname = "/ dev / cdrom" ، flags = O_RDONLY) فشل ، لم يتم العثور على وسيط (123 ،
ENOMEDIUM) لأنه لا يبدو أن هناك قرصًا في محرك الأقراص المضغوطة
الحيلة ، التي لم يكن المؤلف على دراية بها سابقًا ، هي فتح الجهاز باستخدام
علامة O_NONBLOCK ، والتي ستسمح لك بفتح محرك أقراص بدون وسيط فيه. أنت بعد ذلك
إصدار جهاز محدد IOCTL(2) يطلب حتى تعرف ما هو هيك. (لا
متأكد مما إذا كان هذا هو POSIX ، ولكن يبدو أيضًا أنه يعمل بهذه الطريقة في BSD و Solaris ، وفقًا لـ
ال الوديم(1) المصادر.)

لاحظ أيضًا الاستخدامات المختلفة لكل من "القرص" و "القرص" في السياق. نشأ معيار القرص المضغوط
في فرنسا ، ولكن كل شيء آخر يحتوي على "k".

EFAULT ، سيئة العنوان
يمكن لأي استدعاء نظام يأخذ وسيطة مؤشر إرجاع EFAULT. مكتبة libexplain
يمكن أن يكتشف الحجة المخطئة ، ويفعل ذلك دون الإخلال بالعملية
(أو الخيط) معالجة الإشارات.

عند توفرها ، مينكور(2) يتم استخدام استدعاء النظام للسؤال عما إذا كانت منطقة الذاكرة صالحة.
يمكن أن ترجع ثلاث نتائج: مخطط ولكن ليس في الذاكرة الفعلية ، ومعينًا وفيزيائيًا
الذاكرة ، وليس تعيينها. عند اختبار صحة المؤشر ، فإن أول اثنين هما "نعم"
وآخرها "لا".

يعد التحقق من سلاسل C أكثر صعوبة ، لأننا فقط بدلاً من المؤشر والحجم
لديها مؤشر. لتحديد الحجم سيتعين علينا العثور على NUL ، ويمكن أن يحدث ذلك
segfault ، قبض ‐ 22.

لحل هذا الأمر ، تستخدم مكتبة libexplain امتداد الملف lstat(2) استدعاء نظام (مع معروف
وسيطة ثانية جيدة) لاختبار صحة سلاسل C. عودة الفشل && errno == EFAULT
هي "لا" ، وأي شيء آخر هو "نعم". هذا ، بالطبع يحد من السلاسل إلى PATH_MAX
الأحرف ، ولكن هذا عادةً لا يمثل مشكلة بالنسبة لمكتبة libexplain ، لأن هذا هو
دائمًا تقريبًا أطول السلاسل التي تهتم بها.

EMFILE ، أيضا كثير جاكيت ملفات
يحدث هذا الخطأ عندما يكون للعملية بالفعل الحد الأقصى لعدد واصفات الملفات المفتوحة.
إذا كان سيتم طباعة الحد الفعلي ، وحاولت مكتبة libexplain القيام بذلك ، فلا يمكنك فتحه
ملف بتنسيق / إجراءات لقراءة ما هو عليه.
open_max = sysconf (_SC_OPEN_MAX) ،
هذا لن يكون صعبًا جدًا ، فهناك ملف com.sysconf(3) طريقة الحصول على الحد.

إنفيل ، أيضا كثير جاكيت ملفات in نظام
يحدث هذا الخطأ عندما يكون حد النظام على العدد الإجمالي للملفات المفتوحة
وصل. في هذه الحالة لا يوجد مفيد com.sysconf(3) طريقة الحصول على الحد.

عند التعمق أكثر ، قد يكتشف المرء أن هناك ملف / إجراءات الدخول يمكن أن نقرأ له
الحصول على هذه القيمة. Catch ‐ 22: نفدت لدينا واصفات الملفات ، لذلك لا يمكننا فتح ملف
اقرأ الحد.

في Linux ، هناك استدعاء للنظام للحصول عليه ، لكن ليس لديه وظيفة غلاف glibc ، لذا
عليك أن تقوم بكل ذلك بعناية شديدة:
التداول الطويل
شرح_ملف ماكس (باطل)
{
#ifdef __لينكس__
Struct __sysctl_args args؛
int32_t maxfile ؛
size_t maxfile_size = حجم(maxfile) ؛
اسم int [] = {CTL_FS، FS_MAXFILE} ،
memset (& args، 0، sizeof (Struct __sysctl_args)) ؛
args.name = الاسم ؛
args.nlen = 2 ؛
args.oldval = & maxfile ؛
args.oldlenp = & maxfile_size ؛
إذا (syscall (SYS__sysctl، & args)> = 0)
عودة maxfile
#endif
عودة -1 ؛
}
يسمح هذا بالحد المراد تضمينه في رسالة الخطأ ، عند توفرها.

اينفال "غير صالح دعوى" vs اينوسيس "وظيفة ليس مُنفّذ"
الإجراءات غير المدعومة (مثل الارتباط الرمزي(2) على نظام ملفات FAT) لم يتم الإبلاغ عنها
باستمرار من مكالمة نظام إلى أخرى. من الممكن أن يكون لديك إما EINVAL أو
عاد ENOSYS.

نتيجة لذلك ، يجب الانتباه إلى حالات الخطأ هذه لتصحيحها ، على وجه الخصوص
حيث يمكن أن يشير EINVAL أيضًا إلى مشاكل مع وسيطة أو أكثر من وسيطات استدعاء النظام.

ملاحظات أن تخطئ3 is ليس دائما طقم
هناك أوقات يكون من الضروري فيها قراءة المصادر [e] glibc لتحديد كيف و
عندما يتم إرجاع أخطاء لبعض مكالمات النظام.

عداء(3) رقم الملف3
غالبًا ما يُفترض أن هذه الوظائف لا يمكنها إرجاع خطأ. هذا صحيح فقط إذا
ال مجرى الحجة صحيحة ، لكنها قادرة على اكتشاف ما هو غير صالح
المؤشر.

com.fpathconf(3) مسار3
القيمة المرجعة لـ com.fpathconf(2) و مسار(2) يمكن أن تكون -1 شرعياً ، لذا فهي كذلك
ضروري لمعرفة ما إذا كان تخطئ(3) تم تعيينه صراحة.

IOCTL2
القيمة المرجعة لـ IOCTL(2) يمكن أن تكون -1 بشكل شرعي ، لذلك من الضروري معرفة ما إذا كان
تخطئ(3) تم تعيينه صراحة.

readdir3
القيمة المرجعة لـ readdir(3) هو NULL لكل من الأخطاء ونهاية الملف. إنها
ضروري لمعرفة ما إذا كان تخطئ(3) تم تعيينه صراحة.

سيتبوف(3) setbuffer(3) com.setlinebuf(3) سيتفبوف3
جميع هذه الوظائف ما عدا الأخيرة تُرجع باطلة. و سيتفبوف(3) موثق فقط كـ
إرجاع "غير الصفر" عند الخطأ. من الضروري معرفة ما إذا كان تخطئ(3) تم صراحة
تعيين.

سترتود(3) سترتول(3) متشعب(3) نزهة(3) سترتول(3) com.strtoull3
ترجع هذه الدالات القيمة 0 عند الخطأ ، ولكنها أيضًا قيمة إرجاع مشروعة. إنها
ضروري لمعرفة ما إذا كان تخطئ(3) تم تعيينه صراحة.

com.ungetc3
بينما يتم تفويض حرف واحد فقط من النسخ الاحتياطي بواسطة معيار ANSI C ، فإنه يتحول
خارج أن [e] glibc يسمح بالمزيد ... ولكن هذا يعني أنه يمكن أن يفشل مع ENOMEM. يمكن
تفشل أيضًا مع EBADF إذا fp هو زائف. الأصعب من ذلك كله ، إذا قمت بتمرير خطأ EOF
عودة تحدث ، ولكن لم يتم تعيين errno.

تكتشف مكتبة libexplain كل هذه الأخطاء بشكل صحيح ، حتى في الحالات التي يكون فيها ملف
قيم الخطأ موثقة بشكل سيئ ، على كل حال.

اينوسك ، لا الفضاء اليسار on جهاز
عندما يشير هذا الخطأ إلى ملف موجود على نظام الملفات ، تقوم مكتبة libexplain بطباعة التحميل
نقطة نظام الملفات مع المشكلة. هذا يمكن أن يجعل مصدر الخطأ كثيرا
أوضح.
الكتابة (fildes = 1 "example" ، data = 0xbfff2340 ، data_size = 5) فشلت ، لا توجد مساحة متبقية
على الجهاز (28 ، ENOSPC) لأن نظام الملفات يحتوي على fildes ("/ الرئيسية") لا يملك
مساحة أكبر للبيانات
مع إضافة المزيد من الدعم الخاص للجهاز ، من المتوقع أن تتضمن رسائل الخطأ الجهاز
الاسم والحجم الفعلي للجهاز.

EROFS ، يقرأ فقط ملف نظام
عندما يشير هذا الخطأ إلى ملف موجود على نظام الملفات ، تقوم مكتبة libexplain بطباعة التحميل
نقطة نظام الملفات مع المشكلة. هذا يمكن أن يجعل مصدر الخطأ كثيرا
أوضح.

مع إضافة المزيد من الدعم الخاص للجهاز ، من المتوقع أن تتضمن رسائل الخطأ الجهاز
الاسم والنوع.
فتح (اسم المسار = "/ dev / fd0" ، O_RDWR ، 0666) فشل ، نظام ملفات للقراءة فقط (30 ، EROFS)
لأن القرص المرن يحتوي على مجموعة علامات تبويب الحماية ضد الكتابة

... لأن القرص المضغوط غير قابل للكتابة
... لأن بطاقة الذاكرة بها مجموعة علامات التبويب للحماية من الكتابة
... لأن الشريط المغناطيسي بوصة لا يحتوي على حلقة كتابة

إعادة تسمية
إعادة تسمية(2) يتم استخدام استدعاء النظام لتغيير مكان أو اسم الملف ونقله
بين الدلائل إذا لزم الأمر. إذا كان اسم المسار الوجهة موجودًا بالفعل فسيكون كذلك
استبدلت ذريًا ، بحيث لا توجد نقطة تحاول عندها عملية أخرى
الوصول سيجده مفقودًا.

ومع ذلك ، هناك قيود: يمكنك فقط إعادة تسمية دليل فوق دليل آخر
الدليل إذا لم يكن دليل الوجهة فارغًا.
فشل إعادة التسمية (oldpath = "foo" ، newpath = "bar") ، الدليل ليس فارغًا (39،
ENOTEMPTY) لأن newpath ليس دليلاً فارغًا ؛ أي أنه يحتوي على مداخل
غير ذلك "." و ".."
لا يمكنك إعادة تسمية دليل أعلى دليل غير أيضًا.
إعادة تسمية (oldpath = "foo" ، newpath = "bar") فشل ، ليس دليلًا (20 ، ENOTDIR)
لأن oldpath هو دليل ، لكن newpath هو ملف عادي وليس دليل
ولا العكس
إعادة تسمية (oldpath = "foo" ، newpath = "bar") فشل ، هو دليل (21 ، EISDIR)
لأن newpath هو دليل ، لكن oldpath هو ملف عادي وليس دليل

هذا ، بالطبع ، يجعل مهمة مكتبة libexplain أكثر تعقيدًا ، لأن
فك ارتباط(2) أو RMDIR(2) يسمى استدعاء النظام ضمنيًا بواسطة إعادة تسمية(2) وهكذا كل من
فك ارتباط(2) أو RMDIR(2) يجب الكشف عن الأخطاء ومعالجتها أيضًا.

مزدوج 2
مزدوج 2(2) يتم استخدام استدعاء النظام لإنشاء واصف ملف ثانٍ يشير إلى ملف
نفس الكائن مثل واصف الملف الأول. عادة ما يستخدم هذا لتنفيذ مدخلات قذيفة
وإعادة توجيه الإخراج.

الشيء الممتع هو ذلك ، تمامًا إعادة تسمية(2) يمكنه إعادة تسمية ملف ذريًا أعلى ملف
الملف الموجود وإزالة الملف القديم ، مزدوج 2(2) يمكنه القيام بذلك على ملف مفتوح بالفعل
واصف.

مرة أخرى ، هذا يجعل مهمة مكتبة libexplain أكثر تعقيدًا ، لأن ملف اغلق2
يسمى استدعاء النظام ضمنيًا بواسطة مزدوج 2(2) وهكذا كل من اغلق(2) يجب أن تكون أخطاء
تم اكتشافها والتعامل معها أيضًا.

مغامرات IN IOCTL الدعم


IOCTL(2) يوفر استدعاء النظام لمؤلفي برامج تشغيل الجهاز طريقة للتواصل معهم
مساحة مستخدم لا تتناسب مع واجهة برمجة تطبيقات kernel الحالية. يرى ioctl_list(2).

فك أطلب أرقام
من نظرة خاطفة على IOCTL(2) يبدو أن هناك واجهة كبيرة ولكنها محدودة
عدد ممكن IOCTL(2) طلبات. كل مختلف IOCTL(2) الطلب فعال
استدعاء نظام آخر ، ولكن بدون أي نوع ‐ أمان على الإطلاق - لا يستطيع المترجم مساعدة ملف
مبرمج الحصول على هذه الحق. ربما كان هذا هو الدافع وراء ذلك com.tcflush(3) و
هل نبقى اصدقاء.

الانطباع الأولي هو أنه يمكنك فك الشفرة IOCTL(2) طلبات باستخدام مفتاح ضخم
إفادة. تبين أن هذا غير ممكن لأن المرء يكتشف بسرعة أنه كذلك
من المستحيل تضمين كافة رؤوس النظام الضرورية لتعريف المتنوع IOCTL2
الطلبات ، لأنهم يجدون صعوبة في اللعب بشكل جيد مع بعضهم البعض.

يكشف نظرة أعمق أن هناك مجموعة من أرقام الطلبات "الخاصة" ، والجهاز
يتم تشجيع مؤلفي السائقين على استخدامها. هذا يعني أن هناك إمكانية أكبر بكثير
مجموعة من الطلبات ، بأرقام طلبات غامضة ، مما يتضح على الفور. أيضًا،
هناك بعض الغموض التاريخي أيضًا.

لقد علمنا بالفعل أن المفتاح كان غير عملي ، لكننا نعرف الآن ذلك لتحديد
اسم الطلب المناسب والشرح يجب أن نأخذ في الاعتبار ليس فقط رقم الطلب ولكن
أيضا واصف الملف.

تنفيذ IOCTL(2) الدعم داخل مكتبة libexplain هو الحصول على جدول
مؤشرات ل IOCTL(2) طلب واصفات. يتضمن كل من هذه الواصفات اختياريًا
مؤشر لوظيفة توضيح.

يتم تنفيذ كل طلب فعليًا في ملف مصدر منفصل ، بحيث يكون ضروريًا
تضمين الملفات يتم إعفاؤهم من الالتزام باللعب بشكل جيد مع الآخرين.

التمثيل
الفلسفة الكامنة وراء مكتبة libexplain هي توفير أكبر قدر من المعلومات
ممكن ، بما في ذلك تمثيل دقيق لاستدعاء النظام. في حالة
IOCTL(2) يعني هذا طباعة رقم الطلب الصحيح (بالاسم) وأيضًا طباعة (أو
على الأقل مفيد) تمثيل الوسيطة الثالثة.

IOCTL(2) النموذج الأولي يشبه هذا:
int ioctl (int fildes، int request، ...) ؛
التي ينبغي أن تنطلق إنذارات السلامة من النوع الخاص بك. داخلي ل glibc ، هذا تحول
في أشكال متنوعة:
int __ioctl (int fildes، int request، long arg) ؛
int __ioctl (int fildes، int request، void * arg) ؛
وتتوقع واجهة Linux kernel syscall
asmlinkage long sys_ioctl (ملفات int غير موقعة ، طلب int غير موقعة ، بدون توقيع طويل
arg) ؛
التباين الشديد للحجة الثالثة يمثل تحديًا عند مكتبة libexplain
يحاول طباعة تمثيل تلك الوسيطة الثالثة. ومع ذلك ، بمجرد رقم الطلب
تم توضيحه ، فكل إدخال في جدول ioctl الخاص بمكتبة libexplain يحتوي على ملف
وظيفة print_data مخصصة (يتم إجراء OO يدويًا).

تفسيرات
هناك مشاكل أقل في تحديد الشرح الذي سيتم استخدامه. بمجرد رقم الطلب
تم توضيح ذلك ، فكل إدخال في جدول ioctl الخاص بمكتبة libexplain يحتوي على مخصص
وظيفة print_explanation (مرة أخرى ، تم إجراء OO يدويًا).

على عكس القسم 2 و القسم 3 ، فإن معظم المكالمات IOCTL(2) الطلبات لا تحتوي على أخطاء
موثقة. هذا يعني ، لإعطاء أوصاف خطأ جيدة ، من الضروري قراءة kernel
مصادر لاكتشافها

· ماذا تخطئ(3) قد يتم إرجاع القيم ، و

· سبب كل خطأ.

نظرًا لطبيعة OO لدالة استدعاء الإرسال مع kernel ، فأنت بحاجة إلى القراءة
من جميع مصادر تنفيذ ذلك IOCTL(2) طلب ، وليس فقط التنفيذ العام. هو - هي
هو توقع أن النوى المختلفة سيكون لها أرقام أخطاء مختلفة ومهارة
أسباب خطأ مختلفة.

اينفال vs إنوتي
الوضع أسوأ بالنسبة ل IOCTL(2) طلبات من مكالمات النظام ، مع EINVAL و
ENOTTY يتم استخدام كلاهما للإشارة إلى أن ملف IOCTL(2) طلب غير لائق في ذلك
السياق ، وأحيانًا ENOSYS و ENOTSUP و EOPNOTSUPP (من المفترض استخدامها للمآخذ)
حسنًا. هناك تعليقات في مصادر Linux kernel يبدو أنها تشير إلى تقدمي
التنظيف قيد التقدم. لمزيد من الفوضى ، تضيف BSD ENOIOCTL إلى الارتباك.

نتيجة لذلك ، يجب الانتباه إلى حالات الخطأ هذه لتصحيحها ، على وجه الخصوص
حيث يمكن أن يشير EINVAL أيضًا إلى مشاكل مع وسيطة أو أكثر من وسيطات استدعاء النظام.

intptr_t
يحدد معيار C99 نوع عدد صحيح مضمون ليكون قادرًا على الاحتفاظ بأي مؤشر
بدون خسارة التمثيل.

سيكون من الأفضل كتابة النموذج الأولي للدالة المذكورة أعلاه
طويل sys_ioctl (ملفات int غير موقعة ، طلب int غير موقعة ، intptr_t arg) ؛
المشكلة هي التنافر المعرفي الناجم عن جهاز محدد أو نظام ملفات محدد
IOCTL(2) تطبيقات ، مثل:
طويل vfs_ioctl (ملف هيكلي * filp ، cmd int بدون توقيع ، وسيط طويل بدون توقيع) ؛
الأغلبية IOCTL(2) الطلبات لها في الواقع وسيطة ثالثة int * arg. لكن امتلاكها
المعلنة الطويلة تؤدي إلى رمز يعامل هذا على أنه طويل * arg. هذا غير ضار على 32 بت
(sizeof (طويل) == sizeof (int)) ولكنه مقرف على 64 بت (sizeof (طويل)! = sizeof (int)).
اعتمادًا على القيمة الداخلية ، تحصل أو لا تحصل على القيمة التي تتوقعها ، ولكنك تحصل عليها دائما دولار فقط واحصل على خصم XNUMX% على جميع
ذاكرة خربشة أو كومة خربشة كذلك.

كتابة كل هذه بصيغة
int ioctl (int fildes، int request، ...) ؛
int __ioctl (int fildes، int request، intptr_t arg) ؛
طويل sys_ioctl (ملفات int غير موقعة ، طلب int غير موقعة ، intptr_t arg) ؛
طويل vfs_ioctl (ملف البنية * filp ، بدون إشارة int cmd ، intptr_t arg) ؛
يؤكد أن العدد الصحيح ليس سوى عدد صحيح لتمثيل كمية تكاد تكون
دائمًا من نوع مؤشر غير ذي صلة.

الخلاصة


استخدم libexplain ، وسيحب المستخدمون ذلك.

حقوق الطبع والنشر


libexplain الإصدار 1.4
حقوق النشر (C) 2008 ، 2009 ، 2010 ، 2011 ، 2012 ، 2013 ، 2014 Peter Miller

استخدمشرح_lca2010 عبر الإنترنت باستخدام خدمات onworks.net


خوادم ومحطات عمل مجانية

قم بتنزيل تطبيقات Windows و Linux

  • 1
    جرعة كبيرة
    جرعة كبيرة
    SWIG هي أداة لتطوير البرمجيات
    يربط البرامج المكتوبة باللغتين C و
    C ++ مع مجموعة متنوعة من المستويات العالية
    لغات البرمجة. يستخدم SWIG مع
    مختلف...
    تنزيل SWIG
  • 2
    موضوع WooCommerce Nextjs React
    موضوع WooCommerce Nextjs React
    React WooCommerce theme ، الذي تم إنشاؤه باستخدام
    التالي JS و Webpack و Babel و Node و
    Express ، باستخدام GraphQL و Apollo
    عميل. متجر WooCommerce في React (
    يحتوي على: المنتجات ...
    قم بتنزيل WooCommerce Nextjs React Theme
  • 3
    Archlabs_repo
    Archlabs_repo
    حزمة إعادة الشراء لـ ArchLabs هذا ملف
    التطبيق الذي يمكن جلبه أيضًا
    تبدأ من
    https://sourceforge.net/projects/archlabs-repo/.
    تم استضافته في OnWorks في ...
    تحميل برنامج Archlabs_repo
  • 4
    مشروع زفير
    مشروع زفير
    مشروع Zephyr هو جيل جديد
    نظام التشغيل في الوقت الحقيقي (RTOS)
    يدعم أجهزة متعددة
    معماريات. لأنه يقوم على أ
    نواة بصمة صغيرة ...
    تحميل مشروع زفير
  • 5
    سلبيات
    سلبيات
    SCons هي أداة لبناء البرمجيات
    هذا بديل ممتاز لـ
    الكلاسيكية "Make" أداة البناء التي
    كلنا نعرف ونحب. SCons هو
    نفذت ...
    تنزيل SCons
  • 6
    PSeInt
    PSeInt
    PSeInt هو مترجم شفوي زائف لـ
    طلاب البرمجة الناطقين بالإسبانية.
    الغرض الرئيسي منه هو أن تكون أداة لـ
    التعلم وفهم الأساسيات
    تصور ...
    تنزيل PSeInt
  • أكثر "

أوامر لينكس

Ad