Um in C ein externes Programm auszuführen, und dabei auf die Standardein- und Ausgabe des Programms zugreifen, muss man dies per Hand mit ein paar Syscalls machen. Es gibt zwar auch die Funktion popen, aber damit kann man nur in stdin des Programms schreiben, oder stdout lesen.
Programme werden in der Unixwelt gestartet, in dem mit fork der aktuelle Prozess kopiert wird. In dem neuen Kind-Prozess wird dann mit exec das gewünschte Programm ausgeführt.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv) {
pid_t pid = fork();
if(pid == 0) {
// child
return execl("/usr/bin/echo", "echo", "hello world");
} else if(pid > 0) {
// parent
int status = -1;
waitpid(pid, &status, 0); // wait for child termination
} else {
perror("fork");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Dies ist ein einfaches Grundgerüst, um ein Programm zu starten. Jetzt müssen wir noch stdin, stdout und stderr im Kind-Prozess umleiten. Dafür werden 3 Pipes benötigt, die vor dem Fork erstellt werden müssen.
int newin[2];
int newout[2];
int newerr[2];
if(pipe(newin) || pipe(newout) || pipe(newerr)) {
perror("pipe");
return EXIT_FAILURE;
}
Der Syscall pipe liefert uns 2 File-Deskriptoren, aus dem 1. im Array kann gelesen und in den 2. geschrieben werden. Nach dem Fork stehen die Pipes in beiden Prozessen zur Verfügung. Was jetzt noch fehlt ist, dass im Kind-Prozess die Filedeskriptoren für stdin, stdout und stderr auf die Pipe-Filedeskriptoren zeigen. Dies erledigen wir mit dup2. Dies kopiert unsere Pipe-Filedeskriptoren und ersetzt damit stdin, stdout und stderr im Kind-Prozess.
// child
// we need stdin, stdout and stderr refer to the previously
// created pipes
if(dup2(newin[0], STDIN_FILENO) == -1) {
perror("dup2");
return EXIT_FAILURE;
}
if(dup2(newout[1], STDOUT_FILENO) == -1) {
perror("dup2");
return EXIT_FAILURE;
}
if(dup2(newerr[1], STDERR_FILENO) == -1) {
perror("dup2");
return EXIT_FAILURE;
}
Danach würde im Kind-Prozess ein einfaches printf("Hello World!\n"); in unserer Pipe landen und könnte im Parent aus der Pipe gelesen werden.
Jetzt fehlt nur noch eine Kleinigkeit. Durch fork wurden alle Filedeskriptoren kopiert. Einige davon müssen geschlossen werden, weil sonst das Ende der Streams nicht erreicht werden könnte.
Im Kind-Prozess:
close(newin[1]);
Im Eltern-Prozess:
close(newout[1]);
close(newerr[1]);
Den kompletten Beispielcode gibt es hier. Es wird dort das Programm bc aufgerufen, die Standardeingabe davon befüllt und danach die die Ausgabe des Programms gelesen.
VirtualBox ist in der Lage auf am Host angeschlossene Festplatten zuzugreifen. Auf diese Weise kann man beispielsweise auf Dateisysteme zugreifen, wenn das Host-OS diese nicht unterstützt. Man braucht dann nur eine VM mit dem passendem OS und fügt zu dieser dann die physische Festplatte hinzu.
Mit einem einzigen Befehl erstellt man eine vmdk-Imagedatei, die das entsprechende Blockdevice repräsentiert.
VBoxManage internalcommands createrawvmdk -filename image.vmdk -rawdisk /dev/sda
Dann kann man in der VirtualBox-GUI eine neue Festplatte hinzufügen und wählt diese vmdk-Datei aus. Wichtig ist noch, dass der User Lese- und Schreibrechte für das Device hat.
Gnome 3 kann mehrere Hintergrundbilder als Slideshow anzeigen. Aber es wäre nicht Gnome, wenn die Einstellungsmöglichkeiten per GUI nicht völlig kastriert wären, denn im entsprechenden Dialog können nur vorgefertigte Slideshows ausgewählt werden.
Also muss man wieder einen Texteditor bemühen, glücklicherweise muss man nur 2 Dateien erstellen. Vorher erstellt man noch 2 Verzeichnisse, falls diese noch nicht existieren.
mkdir -p ~/.local/share/gnome-background-properties
mkdir -p ~/.local/share/backgrounds
Unter ~/.local/share/gnome-background-properties speichert man eine XML-Datei mit beliebigen Namen (z.B. myslideshow.xml) mit folgendem Inhalt:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE wallpapers SYSTEM "gnome-wp-list.dtd">
<wallpapers>
<wallpaper>
<name>My Slideshow</name>
<filename>.local/share/backgrounds/myslideshow.xml</filename>
<options>zoom</options>
</wallpaper>
</wallpapers>
Dann erstellt man die Datei .local/share/backgrounds/myslideshow.xml in der die eigentlichen Bilder angegeben werden. Hier ein kleines Template dafür:
<?xml version="1.0" encoding="UTF-8"?
<background>
<starttime>
<year>2012</year>
<month>01</month>
<day>01</day>
<hour>00</hour>
<minute>00</minute>
<second>00</second>
</starttime>
<static>
<duration>1800.0</duration>
<file>.local/share/backgrounds/image1.png</file>
</static>
<transition>
<duration>5.0</duration>
<from>.local/share/backgrounds/image1.png</from>
<to>.local/share/backgrounds/image2.png</to>
</transition>
<static>
<duration>1800.0</duration>
<file>.local/share/backgrounds/image2.png</file>
</static>
<transition>
<duration>5.0</duration>
<from>.local/share/backgrounds/image2.png</from>
<to>.local/share/backgrounds/image3.png</to>
</transition>
<static>
<duration>1800.0</duration>
<file>.local/share/backgrounds/image3.png</file>
</static>
<transition>
<duration>5.0</duration>
<from>.local/share/backgrounds/image3.png</from>
<to>.local/share/backgrounds/image1.png</to>
</transition>
</background>
Dürfte relativ selbsterklärend sein. Die Bilder werden in der Reihenfolge angezeigt, in der sie in der Datei gelistet sind. Die Pfade zu den einzelnen Bilddateien können beliebig gewählt werden. Mit einem static-Element gibt man ein Bild an, dass dann für die gewünschte Dauer angezeigt wird. Übergänge zwischen Bildern können mit den transition-Elementen gemacht werden.
Hat man alle Dateien wie gewünscht erstellt, kann die eigene Slideshow dann in den Einstellungen für Hintergrundbilder ausgewählt werden.
Vor kurzem hab ich versucht ein kleines Stück Software auf einer exotischen RISC-Plattform zum Laufen zu bringen, doch bei der Ausführung crashte das Programm. Der Grund war Code der in etwa das machte:
int *intptr = (int*)(str + 15);
Um von einer bestimmten Stelle aus einem Speicherbereich ein int zu lesen wurde ein char* verschoben und zu einem Integer-Pointer gecasted. Beim anschließenden Zugriff auf diesen Pointer stürzte das Programm ab. Der Grund ist, dass nicht alle CPU-Architekturen beliebig wahllose Speicherzugriffe erlauben, sondern nur auf richtig ausgerichtete Adressen, die ein Vielfaches von n (meistens 4) sind. Siehe Data structure alignment
Jetzt sind allerdings die verbreitetsten CPU-Architekturen x86 und ARM, und die kommen auch mit misaligned Memory klar. Warum sollte man das dann überhaupt beachten? Weil auch wenn es auf diesen CPUs fehlerfrei funktioniert, hat es zumindestens Performance-Auswirkungen. Es werden dann nämlich einfach 2 Speicherzugriffe gemacht. Ich habe ein interessanten Blogpost zu dem Thema gefunden, in dem jemand ein Performance-Test gemacht hat. Das Ergebnis ist, dass im schlimmsten Fall die Speicherzugriffe doppelt so lange dauern.
Wenn man jetzt aber doch auf nicht-ausgerichteten Speicher zugreifen will, kann man immer noch memcpy nutzen, denn das kann die Adresse berichtigen und dann größtenteils optimierte Speicherzugriffe machen.
Kommentare
dev | Artikel: Datei ver- und entschlüsseln mit openssl - kompatibel mit dav
Andreas | Artikel: Datenanalyse in der Shell Teil 1: Basis-Tools
Einfach und cool!
Danke Andreas
Rudi | Artikel: Raspberry Pi1 vs Raspberry Pi4 vs Fujitsu s920 vs Sun Ultra 45
Peter | Artikel: XNEdit - Mein NEdit-Fork mit Unicode-Support
Damit wird Nedit durch XNedit ersetzt.
Danke!
Olaf | Artikel: XNEdit - Mein NEdit-Fork mit Unicode-Support
Anti-Aliasing hängt von der Schriftart ab. Mit einem bitmap font sollte die Schrift klassisch wie in nedit aussehen.
Einfach unter Preferences -> Default Settings -> Text Fonts nach einer passenden Schriftart suchen.
Peter | Artikel: XNEdit - Mein NEdit-Fork mit Unicode-Support
Mettigel | Artikel: Raspberry Pi1 vs Raspberry Pi4 vs Fujitsu s920 vs Sun Ultra 45
Ich hatte gedacht, dass der GX-415 im s920 deutlich mehr Dampf hat als der Raspi4.
Mein Thinclient verbraucht mit 16 GB RAM ~11 W idle, das ist das Dreifache vom RP4. Das muss man dem kleinen echt lassen... Sparsam ist er.
Olaf | Artikel: Raspberry Pi1 vs Raspberry Pi4 vs Fujitsu s920 vs Sun Ultra 45
Ergebnisse von der Ultra 80 wären natürlich interessant, insbesondere im Vergleich mit dem rpi1.