Optimierte Cee Funktion exec Fragment
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Folgende Funktion ist aus dem Linux Kernel. Das Original findet man in linux/fs/binfmt_script.c

Situation
Eine Datei soll ausgeführt werden. Nach dem Befragen der entsprechenden Magischen Zahlen wurde festgestellt, dass es sich bei der Datei um ein Script handelt. In der ersten Zeile eines Scriptes findet sich eine Zeichenfolge, die angibt mit welchem Interpreter das Script aufgerufen werden soll:
#! /pfad/interpreter [argument]\n

Aufgabe
Der Interpreter und das optionale Argument sollen gefunden werden.

static int load_script(struct linux_binprm *bprm, struct pt_regs *regs)
{
  char *cp, *i_name, *i_arg;
  char interp[BINPRM_BUF_SIZE];
  
  if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang))
    return -ENOEXEC;

/* SETUP SKIPPED */

  bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
  if ((cp = strchr(bprm->buf, '\n')) == NULL)
    cp = bprm->buf+BINPRM_BUF_SIZE-1;
  *cp = '\0';
  while (cp > bprm->buf) {
    cp--;
    if ((*cp == ' ') || (*cp == '\t'))
      *cp = '\0';
    else
      break;
  }
  for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
  if (*cp == '\0')
    return -ENOEXEC; /* No interpreter name found */
  i_name = cp;
  i_arg = 0;
  for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
    /* nothing */ ;
  while ((*cp == ' ') || (*cp == '\t'))
    *cp++ = '\0';
  if (*cp)
    i_arg = cp;
  strcpy (interp, i_name_start);

/* EXEC SKIPPED */

}

Es ist oben keinerlei Konzept, Schema oder System erkennbar. Es wurde einfach von oben nach unten in der Reihenfolge der Gedanken und Notwendigkeiten jeweils eine Konstruktion gewählt, die das punktuell anstehende Problem löst, ohne im voraus zu denken und auch ohne zu rekapitulieren. Als Folge der Konzeptlosigkeit werden die zu parsenden Daten mehrfach gelesen.

Folgende Variante ist eine OptimierungPerKonzeption?. Es wurde ein wiederverwendbares und skalierbares Parse-Konzept überlegt. Desweiteren wurde auf möglichst wenige Lese-, Schreib- und Test-Aktionen als zu erreichendes Ziel geachtet.

Das Konzept [lautet so ... bitte ausfüllen].

 [Zwischenraum-]Daten-Zwischenraum-Daten-Zwischenraum-...
 z= gerade      ungerade   gerade  ungerade   gerade  ...

Etwa halber Code-Umfang und wahrscheinlich doppelt so schnell:
static int load_script(struct linux_binprm *bprm, struct pt_regs *regs)
{
  int z;
  char * cp;
  char interp[BINPRM_BUF_SIZE];
  char * ocp= interp;
  char * i_arg;
  char * i_name;
  char * i_name_start;

  if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang))
    return -ENOEXEC;

/* ... */

  for (z=0,*((cp=bprm->buf+2)+127-2)='\n';  1;  ++cp)  {
    if (*cp==' '||*cp=='\t')  {
      if (z&1)  {
        if (*ocp=0,  z>=3)  break;
        if (++z==2)  i_name=ocp;
        ++ocp;
      }
      continue;
    }
    if (z==0)  i_name_start=cp, ++z;
    if (z==2)  i_arg=       cp, ++z;
    if (*cp!='\n')  { *ocp++ = *cp;  continue; }
    if (*ocp=0,  z==1)  i_name=ocp;
    break;
  }
  if (!z || *i_name_start==0)  return -ENOEXEC;
  while (--i_name>i_name_start && *i_name!='/');
  if (*i_name=='/')  ++i_name;

/* ... */

}

/*
Man achte auf die 'Zustands-Maschine z'.
z ungerade/gerade
z-Paare  0..1  2..3
switch(z) bei vielen Args; oder *Array
i_name wird als i_name_end verwendet
*/

--HelmutSchellong

Der Code soll jedoch nur zur Demonstration des Konzeptes dienen und weicht in Details von der Originalimplementierung ab.


Diskussion

Macht [...] das Programmierkonzept unerkennbar? - Nein! Eine kleine Erklärung für hilflose Nasen, wie mich, wäre aber schon fein. -- DavidSchmitt


KategorieOptimierung KategorieSchellong
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 10. September 2003 1:02 (diff))
Suchbegriff: gesucht wird
im Titel
im Text