ein Kapitel zurück                                           ein Kapitel weiter

Nun wird es mal Zeit das wir unser Know-how mal in die Praxis umsetzen. Wir wollen in diesem Kapitel, was immer noch noch Terminal I/O zählt, eine virtuelle Konsole unter Linux erzeugen.

Für Anfänger und Umsteiger von Windows auf Linux will ich noch schnell erklären was eine virtuelle Konsole überhaupt ist. Ein virtuelle Konsole ist eigentlich nichts anderes als mehrere Terminalsitzungen an einem Bildschirm zu betreiben. Wenn sie Beispielsweise unter Linux (nicht unter X-Window) die Taste von ALT+F1 bis ALT+F6 und unter X-Window die Tastenkombination STRG+ALT+F1 bis STRG+ALT+F6 drücken können sie zwischen einzelnen virtuellen Konsolen hin-und-herschalten. Zum X-Window kommen sie übrigens mit der Tastenkombination ALT+F7 bzw. STRG+ALT+F7. Der Clou daran ist das jede einzelne virtuelle Konsole davon Ihre eigene Einstellungen haben darf unabhängig von den anderen Konsolen. Soviel in kürze dazu.

Wenn man eine virtuelle Konsole programmiert benötigt man auf alle Fälle die Funktion....

int ioctl(int fd, int operation,...);  

...die in der Headerdatei <sys/ioctl.h> definiert ist. Bei Fehler liefert diese Funktion den Wert -1 ansonsten 0.
Die Angabe für die 'operation' der Funktion stehen in den Headerdateien <sys/vt.h> und <sys/kd.h>
Am besten binden sie gleich von Anfang an beide mit in das Programm ein. Hierzu nun ein paar Konstanten der Headerdatei <sys/vt.h> die wir für die Programmierung von virtuelle Konsolen mit der Funktion ioctl() benötigen....

Konstante Bedeutung

#define VT_AUTO 0x00 
/*Damit ist es möglich zwischen den einzelnen Terminals mit entsprechender
Tastenkombination Hin-und-Herzuschalten oder reagiert darauf wenn ein
Programm eine entsprechende Aufforderung an den Kern schickt */
#define VT_PROCESS 0x01 /*Abfrage vom Systemkern ob sie wirklich die Konsole wechseln wollen, falls sie es vorhaben */
VT_OPENQRY  /*Sucht nach einer freien virtuellen Konsole :
if(ioctl(fd, VT_OPENQRY, &vtty_nummer) <0 || vtty_nummer == -1)
//Fehler
Vorraussetzung das sie eine freie virtuelle Konsole suchen ist das sie zuvor die Gerätedatei /dev/tty mit open() für das Terminal geöffnet haben*/
VT_GETMODE  /*Mit dieser Konstante könne wir abfragen ob das aktuelle Terminal eine virtuelle Konsole ist */
VT_GETSTATE  /*Damit ermitteln wir die Nummer der aktiven virtuellen Konsole*/
VT_ACTIVATE  /*Um auf eine andere virtuelle Konsole umzuschalten. Kann im Grafikmodus etwas
dauern */
VT_WAITACTIVE  /*Wartet bis die virtuelle Konsole wirklich akitv (VT_ACTIVATE) ist, dann kann ein
Prozess starten */
VT_DISALLOCATE  /*Den für die virtuelle Konsole reservierten Speicher wieder freigeben.*/
VT_SETMODE  damit setzen sie den Modus der aktuellen Konsole
VT_RELDISP  damit geben sie eine virtuelle Konsole frei
VT_ACKAQK  übernimmt die Virtuelle Konsole so damit diese aktiv wird
KIOCSOUND  Damit schalten sie den Terminalton ein. Als 3.Parameter benötigen sie dabei Frequenzzahl -> ioctl(vter_fd, KIOCSOUND, 20);
VT_LOCKSWITCH  Damit können die Umschaltung der virtuellen Terminals auschalten
VT_UNLOCKSWITCH  Damit schalten sie die Umschaltung der virtuellen Terminals wieder ein.

Bevor wir uns das in der Praxis ansehen muss ich Ihnen noch 2 Strukturen erklären die ebenfalls in der Headerdatei <sys/vt.h> definiert sind.....

struct vt_mode {
                char mode;      /*Ist mit VT_AUTO(0x00) oder VT_PROCESS(0x01) gesetzt*/
                char waitv;     /*wenn gesetzt wird schreiben auf eine virtuelle Konsole
                /*blockiert die z.Z. nicht aktiv ist bis die aktiviert ist */
                short relsig;  /*Signal vom Systemkern das er sendet zur Freigabe*/
                               /*der virtuellen Konsole*/
                short acqsig;  /*Signal vom Systemkern das er sendet wen er */
                /*den Prozess warnen will daß er sich diese virtuelle Konsole*/
                /*angeeignet hat */
                short frsig;   /*unbenutzt*/
                };

struct vt_stat {/*enthält die Nummer der gerade aktiven virt. Konsole*/
                unsigned short v_active;
                unsigned short v_signal; /*noch nicht benutzt*/
                /*Bitmaske die die ersten 16 virtuellen Konsolen
                /*anzeigt die offen sind von maximal 63 offenen */
                unsigned short v_state;
               };  

Zum besseren Verständnis wollen wir dies jetzt in ein kleines Beispiel verwenden......

/*Download:vt1.c*/
#include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/vt.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <stdarg.h> #include <fcntl.h> enum{ERROR=-1,OK}; void fehler_exit(char *error_msg,...) { va_list az; va_start(az,error_msg); vprintf(error_msg,az); va_end(az); exit(0); } int main() { int vterm_nr, vterm_fd; int status; struct vt_stat vterm_stat; char terminal[100]; pid_t kindprozess; /*Zuerst öffnen wir die Gerätedatei /dev/tty da wir für ioctl ein Filedeskriptor benötigen */ if((vterm_fd = open("/dev/tty", O_RDWR, 0)) == ERROR) fehler_exit("Kann /dev/tty nicht öffnen.....\n"); /*Jetzt prüfen wir ob tty eine virtuelle Konsole ist*/ if(ioctl(vterm_fd, VT_GETSTATE, &vterm_stat) == ERROR) fehler_exit("tty ist keine virtuelle Konsole..\n"); /*Jetzt suchen wir uns eine freie virtuelle Konsole*/ if(ioctl(vterm_fd, VT_OPENQRY, &vterm_nr) == ERROR || vterm_nr == ERROR) fehler_exit("Keine freie konsole vorhanden...\n"); sprintf(terminal,"/dev/tty%d",vterm_nr); printf("Versuche neues Terminal %s zu öffnen........\n",terminal); /*Jetzt wollen wir überprüfen ob wir auf unserem neuen virt. */ /*Term Lesen und Schreiben dürfen*/ if(access(terminal, (W_OK|R_OK)) == ERROR) fehler_exit("Unzureichend Rechte auf das Terminal......\n"); /*Jetzt erzeugen wir einen neuen Prozess für unser neues Terminal*/ if((kindprozess=fork()) == OK) { /*Wir aktivieren die neuen Konsole warten bis sie wirklich aktiviert wird*/ ioctl(vterm_fd, VT_ACTIVATE, vterm_nr); ioctl(vterm_fd, VT_WAITACTIVE, vterm_nr); /*Wir richten eine neue Session ein*/ setsid(); /*Wir schließen stdin,stdout und stderr und vterm_fd da wir ja eine neuen virtuelle*/ /*Konsole starten wollen und nicht mit dem ganzprintf("%s\n",terminal);en vererbten*/ /*Eigenschaften des Elternprozesses*/ close(0); close(1); close(2); close(vterm_fd); /*Jetzt können wir in unserem Kindprozess die Kprintf("%s\n",terminal);konsole öffen*/ vterm_fd = open(terminal, O_RDWR,0); printf("%s\n",terminal); dup(vterm_fd); dup(vterm_fd); /*Ausführen von unserer neuen virtuellen Konsole*/ printf("...........................Virtuelle Konsolle" "(tty%d)..................\n\n\n",vterm_nr); execlp("/bin/bash", "bash", NULL); printf("%s\n",terminal); } /*Ende Kindprozess*/ wait(NULL); /*Elternprozess wartet auf den Kindprozess*/ /*Alte Konsole wieder aktivieren und Speicher der virtuellen Konsole wieder freigeben*/ ioctl(vterm_fd, VT_ACTIVATE, vterm_stat.v_active); ioctl(vterm_fd, VT_WAITACTIVE, vterm_stat.v_active); ioctl(vterm_fd, VT_DISALLOCATE, vterm_nr); return 0; }

Zum Ausführen diese Beispiels öffnen sie bitte ein echtes Terminal mit STRG+ALT+F1 Wenn sie das Programm jetzt compiliert haben und ausführen öffnen sie ein neues virtuelles Terminal. Bei den meisten dürfte dies /dev/tty8 sein. Unser Terminal das das neue Terminal aufgerufen hat wartet solange (wait(NULL)) bis sein Kindprozess (dev/tty8) fertig ist. Dies können sie sich mit STRG+ALT+F1 ansehen. Zu Ihrer neuen virtuellen Konsole kommen sie zurück mit STRG+ALT+F8
Wenn sie jetzt die neue virtuelle Konsole beenden (exit) kommen wir wieder zu unseren alten Konsole zurück die die neue Aufgerufen hat. Falls sie folgende Fehlermeldung erhalten.........

Unzureichend Rechte auf das Terminal......  

...machen sie mal kurz den Superuser (su) und verändern die Rechte auf das neue virtuelle Terminal. In unserem Beispiel war es /dev/tty8 mit.....

chmod a+rw /dev/tty8  

...damit haben Alle Lese und Schreibrecht auf diesem Terminal.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf