المصدر المفتوح: رمز الفكاهة ، رمز الحيل ، وليس رمز

أولد جليب vs نيو كلانج


عندما أتجول في برنامج متنوع مفتوح المصدر ، أجد بشكل دوري كل أنواع الأشياء المثيرة للاهتمام: أحيانًا يكون مجرد تعليق مضحك ، وأحيانًا يكون أمرًا بارعًا بمعنى أوسع. تظهر مجموعات مماثلة بشكل دوري على "الإنترنت العالمي" وعلى Habré - على سبيل المثال ، هناك سؤال معروف حول StackOverflow حول التعليقات في الكود ، ونشرت هنا مجموعة مختارة من الأسماء المضحكة للكيانات القانونية والأسماء الجغرافية. سأحاول أن أقوم بتركيب ما أجمع عليه تدريجياً. تحت القصاص ، تنتظر اقتباسات من QEMU و Linux kernel والمزيد.


نواة لينكس


أعتقد أنه بالنسبة للكثيرين ، ليس سراً أن الرسائل من Linux Kernel Mailing List تتحول بشكل دوري إلى علامات الاقتباس. لذلك دعونا نلقي نظرة أفضل على الكود. وفوراً ، يجتمع نظام التجميع kernel بنا بمفاجأة: كما تعلم ، فإن المشاريع التي أنشأتها Autoconf لها Makefile مع هدفين distclean للتنظيف: clean . بطبيعة الحال ، لم يتم بناء النواة باستخدام Autoconf ، وما mrproper فقط ، لذلك هناك المزيد من الأهداف هنا: clean ، clean ، و mrproper - نعم ، نعم ، Mr.Proper ، نظافة الأساسية مرتين بأسرع .


الحديث عن نظام التكوين: ذات مرة فوجئت عندما allnoconfig إلى جانب أوامر واضحة مثل allnoconfig ، allyesconfig (أظن أنه يمكن تجميع شيء ما لتصحيح الأخطاء ، لذلك الآن لن allnoconfig allyesconfig على أجهزة حقيقية .. .) و allmodconfig إلى الهدف الغامض allrandconfig . فكرت ، "هل يسخرون؟" ، ثم أخبرت صديقي عن هذه الملاحظة ، والتي أجاب عليها أنه ربما كان أمرًا ذا معنى تمامًا ، ولكن ليس للتجميع الحقيقي ، ولكن لاختبار صحة ترتيب التبعيات بين الخيارات - كما قلت سوف الآن ، وهو نوع من المعلمات التكوين الغامضة.


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


 Some warnings, first. * BIG FAT WARNING ********************************************************* * * If you touch anything on disk between suspend and resume... * ...kiss your data goodbye. * * If you do resume from initrd after your filesystems are mounted... * ...bye bye root partition. * [this is actually same case as above] * * ... 

الحيل الصغيرة


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


 /* SPDX-License-Identifier: GPL-2.0 */ // ... /* * This function doesn't exist, so you'll get a linker error if * something tries to do an invalidly-sized xchg(). */ extern void __xchg_called_with_bad_pointer(void); static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) { unsigned long ret, flags; switch (size) { case 1: #ifdef __xchg_u8 return __xchg_u8(x, ptr); #else local_irq_save(flags); ret = *(volatile u8 *)ptr; *(volatile u8 *)ptr = x; local_irq_restore(flags); return ret; #endif /* __xchg_u8 */ // ... default: __xchg_called_with_bad_pointer(); return x; } } 

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


هل تعلم


  • ... أن النواة لديها مترجم JIT bytecode من وضع المستخدم؟ تسمى هذه التقنية eBPF وتستخدم للتوجيه ، التتبع والمزيد. بالمناسبة ، إذا لم تكن خائفًا من الأدوات "النووية" التجريبية ، فراجع حزمة bpftools.
  • ... أن النواة يمكن أن تذهب لمدة خمس دقائق وقت المعالج؟ يوجد استدعاء لنظام sendfile بنسخ وحدات البايت من واصف ملف واحد إلى آخر. إذا أخبرته بنفس الواصف وقمت بتعيين الإزاحة الصحيحة في الملف ، فسيتم إرجاع نفس البيانات حتى ينسخ 2 غيغابايت.
  • ... أن هناك نوعًا مختلفًا من عمل السبات الذي تقوم به عملية المستخدم - لن يفاجأ إذا كان يمكنك حفظه على تخزين الشبكة أيضًا.

كيمو


بشكل عام ، عندما قرأت Robert Love عن جهاز Linux kernel ، ثم صعدت إلى مصادر QEMU ، كان لدي إحساس معين بـ deja vu. كانت هناك قوائم مضمنة في الهياكل حسب القيمة (وليس كما هو الحال في دورة البرمجة الأولية التي يتعلمونها - من خلال المؤشرات) ، ونظام فرعي RCU معين (ما هو عليه ، ما زلت لم أفهم تمامًا ، لكنه موجود أيضًا في النواة) ، و ربما الكثير أكثر مماثلة.


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


 1. Whitespace Of course, the most important aspect in any coding style is whitespace. Crusty old coders who have trouble spotting the glasses on their noses can tell the difference between a tab and eight spaces from a distance of approximately fifteen parsecs. Many a flamewar has been fought and lost on this issue. 

إليك السؤال الأبدي حول الحد الأقصى لطول الخط:


 Lines should be 80 characters; try not to make them longer. ... Rationale: - Some people like to tile their 24" screens with a 6x4 matrix of 80x24 xterms and use vi in all of them. The best way to punish them is to let them keep doing it. ... 

(هم ... إنه أكبر مرتين على كل محور من استخدامي في بعض الأحيان. هل هذا Linux HD؟)


لا يزال هناك الكثير للاهتمام - قراءة .


ومرة أخرى الحيل


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


على سبيل المثال ، يتم softmmu_template.h الملف softmmu_template.h في قاعدة كود QEMU. عندما رأيت هذا الاسم ، اعتقدت أنه كان من المفترض أن يتم نسخه في تطبيق الواجهة الخلفية لـ TCG وأنقر حتى تم تنفيذ تطبيق TLB الصحيح. لا يهم كيف! إليك كيفية استخدامه بشكل صحيح :


تسريع / tcg / cputlb.h:


 define DATA_SIZE 1 #include "softmmu_template.h" #define DATA_SIZE 2 #include "softmmu_template.h" #define DATA_SIZE 4 #include "softmmu_template.h" #define DATA_SIZE 8 #include "softmmu_template.h" 

كما ترون ، خفة اليد وليس C ++. ولكن هذا مثال بسيط جدا. ماذا عن شيء أكثر تعقيدا؟


يوجد مثل هذا الملف: tcg / tcg-opc.h . محتوياته غامضة إلى حد ما ويبدو مثل هذا:


 ... DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT) DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT) DEF(setcond_i32, 1, 2, 1, 0) DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32)) /* load/store */ DEF(ld8u_i32, 1, 1, 1, 0) DEF(ld8s_i32, 1, 1, 1, 0) DEF(ld16u_i32, 1, 1, 1, 0) DEF(ld16s_i32, 1, 1, 1, 0) ... 

في الواقع ، كل شيء بسيط للغاية - يستخدم مثل هذا:


tcg / tcg.h:


 typedef enum TCGOpcode { #define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name, #include "tcg-opc.h" #undef DEF NB_OPS, } TCGOpcode; 

أو هكذا:


tcg / tcg-common.c:


 TCGOpDef tcg_op_defs[] = { #define DEF(s, oargs, iargs, cargs, flags) \ { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, #include "tcg-opc.h" #undef DEF }; 

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


هل تعلم


  • ... أن QEMU يمكن أن تعمل ليس فقط في وضع المحاكاة لنظام كامل ، ولكن أيضًا تشغيل عملية منفصلة لبنية أخرى تتواصل مع kernel المضيف؟

Java و JVM و all-all-all


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


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


مثل تقريبا في HQ9 +

هناك مثل هذه اللغة الهزلية - HQ9 + . تم إنشاؤه كـ "لغة برمجة تعليمية ملائمة للغاية" ، أي أنه من السهل جدًا القيام بالمهام النموذجية التي يسألها الطلاب:


  • الأمر 'H' مترجم يطبع Hello، World!
  • في الأمر "Q" يطبع نص البرنامج نفسه (كيو)
  • في '9' يطبع كلمات 99 زجاجة من البيرة
  • بواسطة "i" ، فإنه يزيد المتغير i بواحد
  • لا يستطيع أن يفعل أي شيء آخر ، لكن لماذا؟

كيف تحقق JVM الهدف بتعليم واحد؟ لكن الأمر بسيط للغاية - إذا كان من الضروري التوقف ، فإنه يزيل عرض صفحة الذاكرة مع هذا المتغير - تقع الخيوط على SIGSEGV ، وتوقفهم JVM وتوقفهم مؤقتًا عند انتهاء "الصيانة". أتذكر على StackOverflow عندما سئل من مقابلة كيف تحطم JVM؟ أجاب:


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

المزاح كنكتة ، وأحيانا في JVM هو حقا.


حسنًا ، بما أنني ذكرت إنشاء الشفرة في Scala ، ونحن نتحدث فقط عن هذا النظام الإيكولوجي الآن ، فإليك حقيقة مثيرة للاهتمام بالنسبة إليك: إنشاء التعليمات البرمجية في Scala (الذي يحتوي على وحدات ماكرو) منظم مثل هذا: يمكنك كتابة التعليمات البرمجية في Scala باستخدام API مترجم ، وتجميعها. بعد ذلك ، في بداية برنامج التحويل البرمجي التالي ، يمكنك ببساطة تمرير مُنشئ الشفرة الناتج إلى classpath الخاص بالبرنامج المترجم نفسه ، ويقوم ذلك المرشد ، الذي يرى توجيهًا خاصًا ، باستدعائه ، ويمر أشجار بناء الجملة المستلمة أثناء المكالمة. رداً على ذلك ، يتلقى AST ، والذي يجب استبداله في مكان المكالمة.


ميزات أيديولوجيات الترخيص


تعجبني أيديولوجية البرمجيات الحرة ، لكن لديها أيضًا بعض الميزات الممتعة.


مرة واحدة ، قبل حوالي عشر سنوات ، قمت بتحديث مستقر ديبيان الخاص بي ، وبالتفكير في بناء جملة أمر ما ، man <> يكتب عادةً man <> ، والذي حصل على وصف شامل مثل "[اسم البرنامج] هو برنامج يحتوي على وثائق موزعة بموجب ترخيص GNU GFDL مع أقسام غير قابلة للتغيير ، وهي ليست خالية من DFSG. " يقولون أن هذا البرنامج كتبه بعض أصحاب الشر من بعض FSF ... ( المناقشة الآن هي google.)


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


أي متنوعة


ميزات بناء المترجم الدولي خلال قانون مور


حدد مطورو LLVM القاسيون المحاذاة المدعومة:


الحد الأقصى للمحاذاة هو 1 << 29.

كما يقولون ، يجعلك تضحك أولاً ، ثم فكر : الفكرة الأولى - لكن من يحتاج إلى المحاذاة بسرعة 512 ميجابايت. ثم قرأت عن تطور النواة في Rust ، وهناك يقترحون إنشاء بنية "جدول صفحة" محاذاة إلى 4096 بايت. وكيف تقرأ ويكيبيديا ، لذلك هناك عموما:


سيستغرق التسلسل الهرمي الكامل لرسم الخرائط المكون من 4 كيلوبايت لمساحة 48 بت بأكملها أكثر من 512 جيجابايت من الذاكرة (حوالي 0.195٪ من المساحة الظاهرية 256 تيرابايت).

نسخة تنسيق - كيفية تخزين؟


بمجرد أن قررت أن أعرف لماذا لا يعمل التصدير في برنامج واحد ، ولكن اتضح أنه يعمل ... أم لا؟


بعد أن بدأت تشغيل أوامر الواجهة الخلفية يدويًا ، أدركت أنه من حيث المبدأ ، كل شيء على ما يرام ، يجب إرسال الإصدار فقط كـ "2.0" ، ولكن فقط "2" يترك. أتوقع تصحيحًا تافهًا عن طريق تحرير ثابت سلسلة ، أجد الدالة double getVersion() - ولكن ما ، رئيسي ، صغير ، حتى هناك نقطة! ومع ذلك ، في النهاية ، فقد تقرر كل شيء ليس أكثر تعقيدا بكثير مما كان متوقعا ، أنا فقط تحسين دقة الإخراج إعادة توجيه نوع البيانات وإعادة توجيه السطور.


حول الفرق بين المنظرين والممارسين


في رأيي ، في مكان ما على Habré ، رأيت بالفعل ترجمة لمقال حول الحد الأدنى من التعطل عند بدء التشغيل ، ولكن لا يزال برنامج مترجم في C؟ int main; - يوجد رمز main ، ومن الناحية الفنية ، يمكنك نقل التحكم إليه. sirikid لاحظت بشكل صحيح أنه حتى بايت بايت هي زائدة هنا. بشكل عام ، حتى لو تحدثنا عن برنامج بحجم 9 بايت ، من الأفضل عدم تبديد الادعاءات بأنها الأصغر ... صحيح ، سوف يسقط البرنامج ، لكن هذا يتفق تمامًا مع القواعد.


لذلك ، نحن نعرف كيفية إسقاط ما ينبغي أن ينجح ، ولكن ماذا عن إطلاق واحد غير إطلاق؟


 $ ldd /bin/ls linux-vdso.so.1 (0x00007fff93ffa000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f0b27664000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0b2747a000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f0b27406000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0b27400000) /lib64/ld-linux-x86-64.so.2 (0x00007f0b278e9000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0b273df000) $ /lib/x86_64-linux-gnu/libc.so.6 

... و libc له صوت الانسان :


 GNU C Library (Ubuntu GLIBC 2.28-0ubuntu1) stable release version 2.28. Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 8.2.0. libc ABIs: UNIQUE IFUNC ABSOLUTE For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>. 

المبرمجين يلعبون لعبة الجولف


يوجد موقع كامل على StackExchange مخصص لـ Code Golf - مسابقات بأسلوب "حل هذه المشكلة بأقل عقوبة ، بناءً على حجم شفرة المصدر." يتضمن التنسيق نفسه حلولًا متطورة للغاية ، لكن في بعض الأحيان تصبح معقدة للغاية. لذلك ، في أحد الأسئلة ، تم جمع مجموعة من الثغرات المحظورة القياسية. أنا أحب هذا بشكل خاص:


باستخدام MetaGolfScript
MetaGolfScript هي عائلة من لغات البرمجة. على سبيل المثال ، يطبع البرنامج الفارغ في MetaGolfScript-209180605381204854470575573749277224 "Hello، World!".

في سطر واحد


  • منطقي غير مهيأ تعطل البرنامج أو حيث يؤدي سلوك غير محدد


  • ... الذي ، بالمناسبة ، هو السحر. شخص ما في LLVM مازحا في 1 أبريل ، وأصدر آخر تقريراً عن ذلك: مُحسِّني الصغير: السلوك غير المحدد هو السحر


  • تذكر النداء الغامض للاشادة مطوري البرمجيات مفتوحة المصدر في تعقب؟ في Binaryen ، تم تنفيذه ببساطة وبذوق:


    المشكلة: هذا المشروع مذهل
    القرار: wontfix ، يعمل على النحو المنشود

  • في شباط (فبراير) 2009 ، طرح شخص سؤالًا على StackOverflow: "كيفية القيام بذلك وهذا المتصفح المتقاطع؟ أو ، حسنًا ، هناك ثلاثة متصفحات عاملة رائعة ومن يستخدم Chrome على أي حال؟ "



أخيرًا ، من أين يأتي عنوان المقال؟ هذه خدعة تمت إعادة صياغتها من إخراج برنامج التحويل البرمجي emcc من Emscripten :


 $ emcc --help ... emcc: supported targets: llvm bitcode, javascript, NOT elf (autoconf likes to see elf above to enable shared object support) 

Source: https://habr.com/ru/post/ar437832/


All Articles