2009-07-15 12 views
2

Following my previous question in Bezug auf die Begründung hinter extrem langen Funktionen, würde ich gerne eine spezifische Frage zu einem piece of code Ich studiere für meine Forschung. Es ist eine Funktion des Linux-Kernels, der ziemlich lang (412 Zeilen) und kompliziert ist (ein MCC index von 133). Grundsätzlich ist es eine lange und verschachtelte Switch-AnweisungKann diese Kernel-Funktion besser lesbar sein? (Ideen für eine akademische Forschung benötigt!)

Ehrlich gesagt, ich kann mir keine Möglichkeit vorstellen, dieses Durcheinander zu verbessern. Eine Dispatchtabelle scheint sowohl riesig als auch ineffizient zu sein, und jeder Unterprogrammaufruf würde eine unvorstellbare Anzahl von Argumenten erfordern, um ein großes Code-Segment abzudecken.

Denken Sie an irgendeine Art, wie diese Funktion besser lesbar umgeschrieben werden kann, ohne an Effizienz zu verlieren? Wenn nicht, scheint der Code für Sie lesbar?

Es erübrigt sich zu sagen, dass jede Antwort, die in meiner Forschung erscheinen wird, volle Anerkennung bekommen wird - sowohl hier als auch in der eingereichten Arbeit.

Link to the function in an online source browser

+0

Sie haben sehr interessante Forschung im Gange ... –

+1

Dies und alle weiteren Beiträge, die Sie zu diesem Thema machen, sollten Community Wiki sein, IMHO. –

+1

Ich würde Kernel-Code sehr sehr anders als normaler Anwendungscode behandeln. Und vor allem Code, der ein sehr gut definiertes und verständliches Konzept implementiert, das nicht geändert oder weiterentwickelt werden muss. – nos

Antwort

1

Äußerst schrecklich, IMHO. Die naheliegende erste Ordnung besteht darin, jeden Fall im Switch zu einem Aufruf einer Funktion zu machen. Und bevor jemand anfängt über Effizienz zu murmeln, lass mich nur ein Wort sagen - "Inlining".

Edit: Ist dieser Code Teil des Linux FPU-Emulators durch Zufall? Wenn das so ist, dann ist das ein sehr alter Code, der ein Hack war, um Linux auf Intel-Chips wie dem 386 zu bekommen, der keine FPU hatte. Wenn es so ist, ist es wahrscheinlich keine geeignete Studie für Akademiker, außer für Historiker!

+0

Die einzige Konsequenz, an die ich denken kann, ist die unangemessen lange Anzahl von Argumenten, die man braucht, um bestanden zu werden. –

+0

Neil: mehr Wörter: es ist Linux. Es muss wahrscheinlich auf einer Vielzahl von Compilern aufbauen. Es ist auch sehr wahrscheinlich, dass niemand diesen Code betrachtet, außer für Leute, die forschen. –

+0

@Udi Wie es scheint, etwas mit der FPU zu tun, scheint eine Art FPU-Struktur herumzugehen. –

0

Ich weiß nicht viel über Kernel oder darüber, wie Refactoring sie funktionieren könnte.

Die Hauptsache, die mir in den Sinn kommt, ist, diese switch-Anweisung zu übernehmen und jeden Teilschritt in eine separate Funktion mit einem Namen zu zerlegen, der beschreibt, was der Teil tut. Im Grunde, mehr beschreibende Namen.

Aber ich glaube nicht, dass dies optimiert die Funktion nicht mehr. Es wird nur in kleinere Funktionen aufgeteilt, von denen einige hilfreich sein könnten ... Ich weiß es nicht.

Das sind meine 2 Cent.

+0

Der Funktionsaufruf-Overhead wäre prohibitiv. Das sieht wie ein Teil eines Interrupt-Handlers aus - muss ein- und aussteigen. –

4

Ich glaube nicht, dass diese Funktion ein Durcheinander ist. Ich musste schon so ein Durcheinander schreiben.

Diese Funktion ist die Übersetzung in den Code einer Tabelle von einem Mikroprozessorhersteller. Es ist ein sehr low-level Zeug, das die entsprechenden Hardware-Register für den jeweiligen Interrupt oder Fehlergrund kopiert. In dieser Art von Code können Sie oft Register nicht berühren, die nicht von der Hardware ausgefüllt wurden - das kann Busfehler verursachen. Dies verhindert die Verwendung von Code, der allgemeiner ist (wie das Kopieren aller Register).

Ich habe gesehen, was etwas Code Duplikation schien. Auf dieser Ebene (auf Unterbrechungsebene) ist jedoch die Geschwindigkeit wichtiger. Ich würde die Extraktionsmethode nicht für den gemeinsamen Code verwenden, wenn ich nicht wüsste, dass die extrahierte Methode inline ist.

BTW, während Sie sich dort (der Kernel) befinden, achten Sie darauf, die Änderungshistorie dieses Codes zu erfassen. Ich habe den Verdacht, dass es hier nicht viele Änderungen geben wird, da es an die Hardware gebunden ist. Die Art der Änderungen dieser Art von Code im Laufe der Zeit unterscheidet sich erheblich von der Art der Änderungen, die von den meisten Benutzermoduscodes erfahren werden.

Dies wird sich zum Beispiel ändern, wenn ein neuer konsolidierter IO-Chip implementiert wird. In diesem Fall ist die Änderung wahrscheinlich Kopieren und Einfügen und Ändern der neuen Kopie, anstatt den vorhandenen Code zu modifizieren, um die geänderten Register aufzunehmen.

+0

Danke, das war informativ und nützlich. –

1

Ich würde damit beginnen, Konstanten für die verschiedenen Klassen zu definieren. Wenn man in diesen Code kalt kommt, ist es ein Rätsel, wofür das Schalten ist; Wenn das Umschalten gegen benannte Konstanten wäre, hätte ich einen Startpunkt.

Update: Sie können ungefähr 70 Zeilen loswerden, wo die Fälle MAJOR_0C_EXCP zurückgeben; lassen Sie sie einfach bis zum Ende der Routine durchfallen. Da dies der Kernel-Code ist, werde ich erwähnen, dass es einige Performance-Probleme geben könnte, insbesondere wenn die Case-Reihenfolge bereits optimiert wurde, aber es würde zumindest die Menge an Code reduzieren, mit der Sie umgehen müssen.

1

Es gibt hier eine gewisse Regelmäßigkeit, ich vermute, dass sich das für einen Domänenexperten sehr kohärent anfühlt.

Auch die Variationen in der Nähe erlauben eine sofortige visuelle Inspektion.

Ich sehe keine Notwendigkeit, diesen Code zu refaktorieren.