Open Source: Kodoyumor, Kodotryuki, NICHT Codebred

    Alte GLib gegen New Clang


    Ich arbeite an einer Vielzahl von Open-Source-Software und finde gelegentlich alle möglichen interessanten Dinge: Manchmal handelt es sich um einen lächerlichen Kommentar, manchmal um etwas Witziges im weiteren Sinne. Ähnliche Sammlungen erscheinen regelmäßig im "globalen Internet" und auf Habré - etwa eine bekannte Frage zu StackOverflow über Kommentare im Code, und hier wurde kürzlich eine Sammlung witziger Namen von juristischen Personen und Toponymen veröffentlicht . Ich werde versuchen und strukturieren und auslegen, was ich allmählich angesammelt habe. Unter dem Schnitt warten Sie auf Zitate von QEMU, dem Linux-Kernel, und nicht nur.


    Linux Kernel


    Ich denke, für viele ist es kein Geheimnis, dass Briefe aus der Linux-Kernel-Mailing-Liste in Bezug auf Zitate nicht immer übereinstimmen. Schauen wir uns also den Code an. Sofort begrüßt uns das Kernel-Build-System mit einer Überraschung: Wie Sie wissen, haben von Autoconf erstellte Projekte ein Makefile mit zwei Standard-Bereinigungszielen: cleanund distclean. Natürlich ist der Kern nicht mit Hilfe von Autoconf gehen, und auch nur dann gibt es nur ein menuconfig, so mehr Tore hier: clean, distcleanund mrproper- ja, „Mr. Proper“Kernreiniger doppelt so schnell.


    Apropos Konfiguration des Systems: Es ist einmal eine Zeit, ich war überrascht , als ich über sie zusätzlich zu den klaren Befehlen kam wie allnoconfig, allyesconfig(ich vermute , dass etwas kompilieren kann viel Debugging , so dass jetzt hatte ich eine Last auf echte Hardware würde ... nicht wagen) und allmodconfigdas geheimnisvolle Ziel allrandconfig. „Sie machen sich über mich lustig“, dachte ich und erzählte meinem Bekannten von dieser Bemerkung, auf die er antwortete, dass es wahrscheinlich ein ziemlich bedeutungsvoller Befehl sei, aber nicht für die tatsächliche Montage, sondern um die Richtigkeit der Abhängigkeiten zwischen den Optionen zu testen - wie gesagt jetzt eine umwerfende Konfigurationsparameter.


    Es gibt jedoch Leben im Kern außerhalb des Montagesystems: Dokumentation ist manchmal nicht nur technischer, sondern auch ein künstlerischer Wert. Angenommen, Sie möchten die Benutzer vor dem Ruhezustand über die Fragilität und das Risiko eines Datenverlusts warnen, wenn bestimmte Regeln nicht befolgt werden. Ich würde traurig schreiben, sagen sie. ACHTUNG: <ersetze ein paar der langweiligsten Zeilen> . Der Entwickler, der dies geschrieben hat, hat sich jedoch anders verhalten:


    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]
     *
     * ...

    Kleine Tricks


    Es ist nicht überraschend, dass nicht jeder Code mit Optimierungen kompiliert werden kann: Als ich versuchte, sie für alle Objektdateien zu erzwingen, stieß ich natürlich auf eine Entropiequelle oder etwas Ähnliches, das ich herausgab #error, wenn die Optimierung aktiviert war. Nun, Kryptographie ist so. Und möchten Sie Code wie die nicht sammeln sich, wenn Sie deaktivieren alle Optimierung, inlining usw.? Wie ist das möglich? Und das ist eine solche statische Behauptung:


    /* 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;
            }
    }

    Es wird anscheinend angenommen, dass sich diese Funktion bei jeder Verwendung mit einem konstanten Argument in nur einem Zweig entfaltet switch, und bei Verwendung mit einem gültigen Argument nicht default:.
    In einer nicht optimierten Form verursacht diese Funktion einen Verknüpfungsfehler, der ...


    Wissen Sie


    • ... dass der Kernel einen Bytecode-JIT-Compiler aus dem Benutzermodus hat? Diese Technologie wird eBPF genannt und wird für Routing, Tracing und mehr verwendet. Übrigens, wenn Sie keine Angst vor experimentellen "nuklearen" Werkzeugen haben, schauen Sie sich das Paket von bpftools an.
    • ... dass der Core fünf Minuten CPU-Zeit beanspruchen kann? Es gibt einen solchen Systemaufruf sendfile, der Bytes von einem Dateideskriptor in einen anderen kopiert. Wenn Sie dieselbe Beschreibung eingeben und den korrekten Versatz in der Datei festlegen, werden dieselben Daten zurückgespult, bis sie 2 GB kopieren.
    • ... dass es eine Variante der Arbeit des Ruhezustands gibt, die der Benutzerprozess durchführt - es würde mich nicht wundern, wenn er auch auf dem Netzwerkspeicher gespeichert werden kann.

    QEMU


    Wenn ich Robert Love über das Linux-Kernelgerät las und dann in den QEMU-Quellcode kam, hatte ich im Allgemeinen ein gewisses Gefühl von Deja Vu. Es gab Listen, die nach Wert in Strukturen eingebaut wurden (und nicht von Zeigern im ursprünglichen Programmierkurs unterrichtet wurden), und ein bestimmtes RCU-Subsystem (was ich meine, ich habe es nicht vollständig verstanden, aber es existiert auch im Kernel) und wahrscheinlich viel ähnlicher.


    Was ist das Erste, an dem eine nette Person an einem Projekt arbeiten möchte? Wahrscheinlich mit einem Codierstil. Und schon könnte man sagen, zeremoniell, dokumentieren wir:


    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.

    Hier geht es auch um die mehrjährige Frage nach der maximalen Zeilenlänge:


    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.
    ...

    (Hmm ... Es ist doppelt so viel auf jeder Achse, als ich manchmal verwende. Ist es so eine Linux-HD?)


    Es gibt noch viele interessante Dinge - lesen Sie .


    Und wieder Tricks


    Sie sagen, dass C eine Muttersprache ist. Wenn es jedoch gut ist, zu pervertieren, können die Wunder der Codegenerierung während der Kompilierung ohne Scala oder sogar C ++ manifestiert werden.


    Beispielsweise ist die Datei in der QEMU-Codebasis verborgen softmmu_template.h. Als ich diesen Namen sah, dachte ich, dass er in meine Implementierung des TCG-Backends kopiert und korrigiert werden sollte, bis die korrekte Implementierung des TLB erreicht wurde. Egal wie falsch! So verwenden Sie es richtig :


    accel / 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"

    Wie Sie sehen können, Handarbeit und kein C ++. Dies ist jedoch ein ziemlich einfaches Beispiel. Wie wäre es mit etwas komplizierter?


    Es gibt eine solche Datei: tcg / tcg-opc.h . Ihr Inhalt ist eher geheimnisvoll und sieht ungefähr so ​​aus:


    ...
    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)
    ...

    In der Tat ist alles sehr einfach - es wird so verwendet:


    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;

    Oder so:


    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
    };

    Es ist sogar merkwürdig, dass es keine anderen Anwendungsfälle gab. In diesem Fall gibt es keine kniffligen Skripte für die Codegenerierung - nur C, nur Hardcore.


    Wissen Sie


    • ... dass QEMU nicht nur im vollständigen Systememulationsmodus arbeiten kann, sondern auch einen separaten Prozess für eine andere Architektur ausführen kann, die mit dem Host-Kern kommuniziert?

    Java, JVM und alles andere


    Was mache ich nur mit Linux? Reden wir über etwas plattformübergreifend. Über die JVM zum Beispiel. Nun, über GraalVM haben wahrscheinlich viele Entwickler in diesem Ökosystem bereits gehört. Wenn nicht in zwei Worten gehört: Es ist episch. Gehen wir also nach der Geschichte von Graal zur guten alten JVM über.


    Manchmal muss die JVM alle verwalteten Flüsse stoppen - die Müllsammelphase ist so kompliziert oder etwas anderes -, aber zum Glück stoppen Sie die Flüsse nur an sogenannten Sicherungspunkten. Wie hier erläutert , dauert eine normale Überprüfung globaler Variablen sehr lange, einschließlich einiger Schamanismen mit Gedächtnisbarrieren. Was haben die Entwickler gemacht? Sie beschränkten sich auf eine Lesung der Variablen.


    Fast wie in HQ9 +

    Есть такой шуточный язык — HQ9+. Он создавался как "очень удобный учебный язык программирования", а именно, на нём очень просто выполнять типичные задачи, которые задают ученикам:


    • по команде 'H' интерпретатор печатает Hello, World!
    • по команде 'Q' печатает сам текст программы (квайн)
    • на '9' он печатает текст песенки про 99 bottles of the beer
    • по 'i' он увеличивает переменную i на единицу
    • больше он ничего делать не умеет, а зачем?..

    Wie erreicht die JVM mit einer Anweisung das Ziel? Und es ist sehr einfach - wenn Sie es anhalten, wird die Anzeige der Speicherseite mit dieser Variablen entfernt. Die Streams fallen entlang SIGSEGV, und die JVM parkt sie und entfernt sie aus einer Pause, wenn die "Wartung" endet. Ich erinnere mich an StackOverflow an die Frage aus dem Interview. Wie stürzt eine JVM ab? antwortete:


    JNI. Mit JNI ist Absturz tatsächlich die Standardbetriebsart. Du musst arbeiten.

    Witze Witze, und manchmal ist es in der JVM wirklich so.


    Nun, da ich die Codegenerierung in Scala erwähnt habe, und jetzt sprechen wir über dieses Ökosystem, ist hier eine interessante Tatsache: Die Codegenerierung in Scala (die Makros) sieht ungefähr so ​​aus: Sie schreiben Code mit der API in Scala kompilieren und kompilieren. Wenn Sie dann den Compiler das nächste Mal starten, übergeben Sie einfach den resultierenden Codegenerator an den Compiler-Klassenpfad selbst. Wenn er eine spezielle Direktive sieht, ruft sie diese auf und übergibt die während des Aufrufs erhaltenen Syntaxbäume. Als Antwort erhält er eine AST, die an der Anrufstelle ersetzt werden muss.


    Merkmale von Lizenzideologien


    Ich mag die Ideologie der freien Software, aber sie enthält einige witzige Funktionen.


    Vor etwa zehn Jahren habe ich meinen Debian-Stable aktualisiert und, als ich über die Syntax eines Befehls nachgedacht hatte, habe ich getippt man <команда>. Ich erhielt eine umfassende Beschreibung wie "[Programmname] ist ein Programm, dessen Dokumentation unter der GNU GFDL-Lizenz mit unveränderlicher Datei verteilt ist Abschnitte, die nicht DFSG-frei sind. “ Sie sagen , dass das Programm etwas Böses proprietarschiki von einigen geschrieben ... die FSF (jetzt Google Diskussion .)


    Einige kleine, aber wichtige Bibliotheken werden von einigen Distributionen als nicht-freie Software betrachtet, da der Autor der Standardlizenz hinzugefügt hat, dass dieses Programm zum Guten und nicht zum Bösen verwendet werden sollte . Lachen vor Lachen, und auch ich hätte wahrscheinlich Angst vor so etwas in der Produktion - reicht es nicht aus, welche Vorstellungen von Gut und Böse der Autor hat.


    Irgendein anderes


    Merkmale des internationalen Compilers in der Zeit von Moores Gesetz


    Schwere LLVM-Entwickler haben eine begrenzte unterstützte Ausrichtung:


    Die maximale Ausrichtung beträgt 1 << 29.

    Wie sie sagen, bringt es Sie zuerst zum Lachen und dann zum Nachdenken : Der erste Gedanke ist der, der sich auf 512 MiB ausrichten muss. Dann las er über die Entwicklung des Kernels auf Rust , und dort schlagen sie vor, die Struktur "Seitentabelle" an 4096 Bytes anzupassen. Und wie Sie Wikipedia lesen , so allgemein:


    48-Bit-Speicherplatz für mehr als 512 GB Arbeitsspeicher (für etwa 0,195% des virtuellen 256-TB-Speicherplatzes).

    Formatversion - Wie lagern?


    Einmal entschied ich mich herauszufinden, warum der Export in einem Programm nicht funktioniert, aber es stellt sich heraus, dass es funktioniert ... oder nicht?


    Nachdem ich den Backend-Befehl manuell gestartet hatte, wurde mir klar, dass im Prinzip alles in Ordnung ist, nur die Version sollte als "2.0" übertragen werden und es verlässt einfach "2". Ich erwarte eine triviale Korrektur durch Editieren der String-Konstante und entdecke eine Funktion double getVersion()- aber was ist ein Major, es gibt ein Moll, es gibt sogar einen Punkt! Am Ende war alles entschieden, nicht viel schwieriger als erwartet, ichgerade die Genauigkeit der Ausgabe erhöht Der Datentyp wurde weitergeleitet und die Zeilen weitergeleitet.


    Über den Unterschied zwischen Theoretikern und Praktizierenden


    Meiner Meinung nach habe ich irgendwo auf Habré bereits die Übersetzung eines Artikels über das minimale C-Programm gesehen, das beim Start fällt, aber immer noch? int main;- das Symbol mainist und technisch können Sie die Kontrolle darauf übertragen. sirikid hat richtig bemerkt, dass auch die Bytes hier intüberflüssig sind. Im Allgemeinen, selbst wenn von einem Programm mit 9 Bytes Größe gesprochen wird, ist es besser, nicht mit den Anweisungen zu streuen, dass es die kleinste ist ... Das Programm wird zwar fallen, aber die Regeln sind vollständig konsistent.


    Wir wissen also, wie man das ablegt, was funktionieren sollte, aber wie sieht es mit der Ausführung des nicht startenden aus?


    $ 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

    ... und libc zu ihm in einer menschlichen Stimme:


    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>.

    Programmierer spielen Golf


    Es gibt eine ganze Site auf StackExchange, die Code-Golf-Wettbewerben gewidmet ist und den Stil "Lösen Sie dieses Problem mit einer Mindeststrafe, abhängig von der Größe des Quellcodes". Das Format selbst beinhaltet sehr ausgeklügelte Lösungen, die jedoch manchmal sehr ausgereift sind. Daher war eine der Fragen eine Sammlung von standardmäßig verbotenen Lücken. Ich mag dieses besonders:


    Verwenden von MetaGolfScript
    MetaGolfScript ist eine Familie von Programmiersprachen. Das Programm in MetaGolfScript-209180605381204854470575573749277224 druckt beispielsweise "Hallo, Welt!".

    Einzeilig



    Woher kommt schließlich der Titel des Artikels? Dies ist ein umformulierter Trick aus der Ausgabe emccdes Emscripten- Compilers :


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

    Jetzt auch beliebt: