UNIXwork

stat Benchmark

09. Februar 2016

Der Syscall stat wird benutzt um an Informationen wie Dateigröße oder Änderungsdatum einer Datei zu gelangen. Die Funktion erwartet als Argumente nur einen Dateipfad und einen Buffer. Daneben gibt es noch die Variante fstat, die statt eines Dateipfades einen Filedescriptor erwartet, und fstatat, die den Filedescriptor eines geöffneten Verzeichnisses und einen Pfad relativ zu dem Verzeichnis erwartet.

int stat(const char *restrict path, struct stat *restrict buf);
int fstat(int fildes, struct stat *buf);
int fstatat(int fd, const char *restrict path,
    struct stat *restrict buf, int flag);

Mich hat jetzt ein Performancevergleich zwischen den Funktionen interessiert. Zum einen für den Fall, dass man für jede Datei in einem Verzeichnis stat aufrufen will. Hier würde sich der Einsatz von fstatat anbieten. Der andere Fall wäre, wenn man eine Datei öffnen und stat-en will. Um dies zu testen hab ich ein primitives Programm geschrieben, dass man hier findet. Das Programm erwartet als Argument einen Pfad zu einem Verzeichnis, welches es zunächst ließt. Danach führt es 4 Tests durch und misst für jeden die Zeit:

Ein kleiner Test unter Linux ergab:

test 195 files:

test_stat
time: 496386 ns

test_fstatat
time: 246039 ns

----------------------------------------

test_open_stat
time: 1106593 ns

test_open_fstat
time: 885549 ns

Ähnliche Ergebnisse konnte ich auch unter FreeBSD und Solaris, mit Festplatten und SSDs, reproduzieren. Der Vergleich zwischen test_stat und test_fstatat zeigt, dass fstatat deutlich schneller ist. In beiden Tests wird auch nur pro Datei jeweils ein Syscall aufgerufen. Bei test_open_stat und test_open_fstat wird in beiden Fällen zunächst open benutzt um die Datei zu öffnen und es zeigt sich, dass in diesem Fall fstat auch schneller ist als stat, allerdings fällt der Unterschied hier nicht so sehr ins Gewicht.

Autor: Olaf | 0 Kommentare | Tags: c, unix, linux, benchmark

Shell-Session im Hintergrund mit GNU Screen

07. Oktober 2015

GNU Screen ist eine Art Fenstermanager für die Konsole, der es erlaubt, mehrere getrennte Sitzungen innerhalb eines Terminals zu benutzen. In Zeiten grafischer Terminal-Emulatoren wird dies vielleicht nicht so oft gebraucht, ein weiteres sehr nützliches Feature ist jedoch, dass man eine Screen-Session unterbrechen, und später wieder fortsetzen kann. Die unterbrochenen Sessions laufen im Hintergrund weiter, auch wenn die Shell, von der aus man ursprünglich screen gestartet hat, beendet wird. Dies ist sehr praktisch, wenn man z.B. per ssh auf einem entfernten Rechner ein Programm längere Zeit laufen lassen will.

Nach dem Start von screen erhält man eine Shell die in einer Screen-Session läuft. Diese kann mit Strg+A gefolgt von D getrennt werden und später mit screen -r wieder hergestellt werden.

Autor: Olaf | 0 Kommentare | Tags: shell

Large File IO

28. Mai 2015

Betrachten wir zunächst folgendes Beispielprogramm:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
	printf("sizeof(void*) = %d\n", sizeof(void*));
	printf("sizeof(off_t) = %d\n", sizeof(off_t));
	
	FILE *file = fopen("testfile", "w");
	if(!file) return -1;
	
	size_t len = 1024*1024*256;
	char *buf = malloc(len);
	
	int count = 0;
	while(fwrite(buf, 1, len, file) == len) {
		count++;
		if(count >= 10)
			break;
	}
	printf("count: %d\n", count);
	
	fclose(file);
	return 0;
}

Das Programm öffnet eine Datei und schreibt dann 10 mal einen 256MB großen Block. Insgesammt sollte eine 2,5GB große Datei rauskommen. Kompilieren wir das Programm nun im 32bit Modus mit cc -m32 -o test test.c wird die Schleife nicht 10 mal ausgeführt, denn vorher überschreitet die Datei eine Größe von 2GB. Die APIs können auf Grund des 32bit Limits nicht mit größeren Dateien umgehen.

Es gibt jedoch ein Large File Interface für 32bit Anwendungen, damit diese auch mit größeren Dateien umgehen können. Dazu stehen neben den typischen Funktionen, wie z.B. open, fopen, stat, lseek, fseek, ftell, usw., 64bit fähige Funktionen zur Verfügung, deren Name einfach nur um ein 64 erweitert wurde (open64, fopen64, ...). Außerdem gibt es zusätzliche Typen wie off64_t.

Jetzt wäre es etwas unschön, müsste man immer diese 64 bit fähigen Funktionen direkt verwenden, und daher seinen ganzen Code anpassen. Doch definiert man _FILE_OFFSET_BITS=64 stehen unter den alten Namen die 64bit fähigen Funktionen bzw. Typen zur Verfügung. Damit ist off_t nun in 32bit Anwendungen 64bit groß und fopen wird transparent durch fopen64 ersetzt. Wir können also das obere Beispiel einfach mit cc -D_FILE_OFFSET_BITS=64 -o test test.c kompilieren und es verhält sich dann wie sein 64bit Pendant.

Das ganze sollte unter jedem unixoiden Betriebsystem funktionieren. Unter OS X sind die IO-Funktionen allerdings standardmäßig schon im 64bit-Modus und die *64-Funktionen existieren dort nicht.

Siehe auch: lf64(5)

Autor: Olaf | 0 Kommentare | Tags: unix, c, io

SSHA-Hashes

17. Mai 2015

SSHA ist ein Format für SHA-1 Hashes mit Salt und wird von manchen Programmen genutzt um Passwort-Hashes zu speichern. Hierfür wird zunächst ein Salt an das Passwort angehängt und davon ein SHA-1-Hash gebildet. Danach wird an den Hash nochmal das Salt angehängt und das ganze mit base64 kodiert.

Hier ein kleines Script, das ein Passwort als Parameter erwartet und daraus ein SSHA-Hash generiert.

#!/bin/bash

saltlen=8

salt="$(cat /dev/urandom | head -c $saltlen)"
pwsalt=$1$salt

pwhash="$(head -c -1 << EOF | openssl dgst -sha1 -binary
$pwsalt
EOF
)"

ssha="$(head -c -1 << EOF | base64
$pwhash$salt
EOF
)"

ssha="{SSHA}$ssha"
echo $ssha
Autor: Olaf | 0 Kommentare | Tags: shell

Linkdump

14. Mai 2015
Autor: Olaf | 0 Kommentare | Tags: links, c, dtrace
Zurück Weiter