سؤال

هل يعرف أحد كيف يتعامل باش مع إرسال البيانات عبر الأنابيب؟

cat file.txt | tail -20

هل يقوم هذا الأمر بطباعة كافة محتويات file.txt في مخزن مؤقت، ثم تتم قراءته بعد ذلك؟أم أن هذا الأمر، على سبيل المثال، يطبع محتويات ملف file.txt سطرًا تلو الآخر، ثم يتوقف مؤقتًا عند كل سطر حتى تتم معالجة الذيل، ثم يطلب المزيد من البيانات؟

سبب سؤالي هو أنني أكتب برنامجًا على جهاز مضمن يقوم بشكل أساسي بتنفيذ سلسلة من العمليات على جزء من البيانات، حيث يتم إرسال مخرجات إحدى العمليات كمدخل للعملية التالية.أود أن أعرف كيف يتعامل Linux (bash) مع هذا الأمر، لذا من فضلك أعطني إجابة عامة، وليس على وجه التحديد ما يحدث عندما أقوم بتشغيل "cat file.txt | tail -20".

شكرا مقدما على استجابتك!

يحرر:أشار Shog9 إلى مقالة ويكيبيديا ذات صلة، ولم يقودني هذا مباشرة إلى المقالة ولكنه ساعدني في العثور على هذا: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation والتي تحتوي على المعلومات التي كنت أبحث عنها.


أنا آسف لعدم توضيح نفسي.بالطبع أنت تستخدم أنبوبًا وبالطبع تستخدم stdin وstdout للأجزاء المعنية من الأمر.لقد افترضت أن هذا كان واضحًا جدًا بحيث لا يمكن ذكره.

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

هل كانت مفيدة؟

المحلول

قررت أن أكتب شرحًا أكثر تفصيلاً قليلاً.

"السحر" هنا يكمن في نظام التشغيل.يبدأ تشغيل كلا البرنامجين في نفس الوقت تقريبًا، ويعملان في نفس الوقت (يخصص نظام التشغيل لهما شرائح من الوقت على المعالج للتشغيل) كأي عملية أخرى يتم تشغيلها في نفس الوقت على جهاز الكمبيوتر الخاص بك (بما في ذلك التطبيق الطرفي والنواة) .لذا، قبل أن يتم تمرير أي بيانات، تقوم العمليات بكل ما هو ضروري من عمليات التهيئة.في المثال الخاص بك، يقوم tail بتحليل الوسيطة '-20' ويقوم cat بتحليل الوسيطة 'file.txt' ويفتح الملف.في مرحلة ما، سيصل الذيل إلى النقطة التي يحتاج فيها إلى إدخال وسيخبر نظام التشغيل بأنه ينتظر الإدخال.في مرحلة أخرى (سواء قبل ذلك أو بعده، لا يهم) سيبدأ cat في تمرير البيانات إلى نظام التشغيل باستخدام stdout.هذا يذهب إلى مخزن مؤقت في نظام التشغيل.في المرة التالية التي يحصل فيها الذيل على شريحة زمنية على المعالج بعد أن يتم وضع بعض البيانات في المخزن المؤقت بواسطة cat، فسوف يسترد بعضًا من تلك البيانات (أو كلها) مما يترك المخزن المؤقت على نظام التشغيل.عندما يكون المخزن المؤقت فارغًا، سيتعين على الذيل في مرحلة ما الانتظار حتى يقوم القط بإخراج المزيد من البيانات.إذا كانت القطة تقوم بإخراج البيانات بشكل أسرع بكثير من معالجة الذيل لها، فسوف يتوسع المخزن المؤقت.سينتهي cat في النهاية من إخراج البيانات، لكن سيظل الذيل قيد المعالجة، لذلك سيُغلق cat وسيقوم tail بمعالجة جميع البيانات المتبقية في المخزن المؤقت.سيشير نظام التشغيل إلى الذيل عندما لا يكون هناك المزيد من البيانات الواردة باستخدام EOF.سيقوم Tail بمعالجة البيانات المتبقية.في هذه الحالة، من المحتمل أن يتلقى الذيل جميع البيانات في مخزن مؤقت دائري مكون من 20 سطرًا، وعندما يرسل نظام التشغيل إشارة إليه بعدم وجود المزيد من البيانات الواردة، فإنه يقوم بعد ذلك بتفريغ آخر عشرين سطرًا إلى stdout الخاص به، والذي يتم عرضها فقط في المحطة.نظرًا لأن برنامج tail أبسط بكثير من برنامج cat، فمن المحتمل أن يقضي معظم الوقت في انتظار قيام cat بوضع البيانات في المخزن المؤقت.

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

للتعمق في المزيد من التفاصيل، إذا قمت بفتح نوع ما من أجهزة مراقبة العمليات (خاصة بنظام التشغيل) مثل 'top' في Linux، فسترى قائمة كاملة من العمليات الجارية، ومعظمها يستخدم بشكل فعال 0% من المعالج.معظم التطبيقات، ما لم تكن تقوم بمعالجة البيانات، تقضي معظم وقتها في عدم القيام بأي شيء.وهذا أمر جيد، لأنه يسمح للعمليات الأخرى بالوصول غير المقيد إلى المعالج وفقًا لاحتياجاتها.يتم تحقيق ذلك بثلاث طرق أساسية.يمكن أن تصل العملية إلى تعليمات نمط السكون (n) حيث تخبر النواة بشكل أساسي بالانتظار n ميلي ثانية قبل إعطائها شريحة زمنية أخرى للعمل معها.في أغلب الأحيان، يحتاج البرنامج إلى انتظار شيء ما من برنامج آخر، مثل "الذيل" في انتظار دخول المزيد من البيانات إلى المخزن المؤقت.في هذه الحالة، سيقوم نظام التشغيل بتنشيط العملية عند توفر المزيد من البيانات.وأخيرًا، يمكن للنواة أن تستبق عملية ما في منتصف التنفيذ، مما يمنح بعض شرائح وقت المعالج لعمليات أخرى."القط" و"الذيل" هما برنامجان بسيطان.في هذا المثال، يقضي Tail معظم وقته في انتظار المزيد من البيانات على المخزن المؤقت، ويقضي Cat معظم وقته في انتظار قيام نظام التشغيل باسترداد البيانات من القرص الصلب.عنق الزجاجة هو سرعة (أو بطء) الوسيط الفعلي الذي يتم تخزين الملف عليه.هذا التأخير الملحوظ الذي قد تكتشفه عند تشغيل هذا الأمر لأول مرة هو الوقت الذي تستغرقه رؤوس القراءة على محرك الأقراص للبحث عن الموضع على القرص الصلب حيث يوجد "file.txt".إذا قمت بتشغيل الأمر مرة ثانية، فمن المحتمل أن يحتوي نظام التشغيل على محتويات ملف file.txt مخزنة مؤقتًا في الذاكرة، ولن ترى على الأرجح أي تأخير ملموس (ما لم يكن file.txt كبيرًا جدًا، أو لم يعد الملف مخزنًا مؤقتًا .)

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

نصائح أخرى

لقد أشار Shog9 بالفعل إلى مقالة ويكيبيديا، لكن قسم التنفيذ لديه التفاصيل التي تريدها.التنفيذ الأساسي هو منطقة عازلة محدودة.

سيقوم cat فقط بطباعة البيانات إلى المستوى القياسي، والذي تتم إعادة توجيهه إلى المعيار في الذيل.يمكن رؤية ذلك في صفحة الدليل الخاصة بـ bash.

وبعبارة أخرى، لا يوجد توقف مؤقت، الذيل يقرأ فقط من المعيار إلى الداخل، والقطة تكتب فقط إلى الخارج.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top