C-Programm – Dateien kopieren unter Linux
Dieser Beitrag wurde vor mehr als drei Monaten veröffentlicht. Bedenke bitte, dass die hier angebotene Information nicht mehr aktuell und gültig sein könnte. Informiere dich daher bitte auch an anderer Stelle über dieses Thema. Sollten sich neue Informationen ergeben haben, so kannst du mich auch gerne auf diese über einen Kommentar hinweisen. Vielen Dank!
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main() {
char c;
int in, out;
// open - mit dem Systemaufruf open kann ein neuer Dateideskriptor erstellt werden
// ---------------------
// Modus -> Beschreibung
// ---------------------
// O_RDONLY -> nur zum lesen oeffnen
// O_WONLY -> nur zum schreiben oeffnen
// O_RDWR -> zum lesen und schreiben oeffnen
// ---------------------
// optionaler Modus -> Beschreibung
// ---------------------
// O_APPEND -> am Ende der Datei schreiben
// O_TRUNC -> Inhalt der vorhandenen Datei wird geloescht
// O_CREAT -> erstellt die Datei mit Berechtigungen
// O_EXCL -> stellt sicher, dass nicht zwei Programme
// die selbe Datei, zur gleichen Zeit erstellen
// ---------------------
// Berechtigung -> Beschreibung
// ---------------------
// S_IRUSR -> Lesen, Eigentuemer (owner)
// S_IWUSR -> Schreiben, Eigentuemer (owner)
// S_IXUSR -> Ausfuehren, Eigentuemer (owner)
// S_IRGRP -> Lesen, Gruppe (group)
// S_IWGRP -> Schreiben, Gruppe (group)
// S_IXGRP -> Ausfuehren, Gruppe (group)
// S_IROTH -> Lesen, Andere (others)
// S_IWOTH -> Schreiben, Andere (others)
// S_IXOTH -> Ausfuehren, Andere (others)
//
// weitere Infos unter: man 2 open
//
// 1 MB Datei erstellen -> dd if=/dev/zero of=file.in bs=1024 count=10240
//
// Datei "file.in" zum lesen oeffnen
in = open("file.in", O_RDONLY);
// Datei "file.out" erstellen (Eigentuemer -> Lesen + Schreiben)
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
// Zeichen fuer Zeichen einlesen ...
while(read(in,&c,1) == 1) {
// ... und jedes Zeichen in die neue Datei schreiben
write(out,&c,1);
}
exit(0);
}
Wir gehen in diesem Beispiel davon aus, dass die Datei "file.in" (10 MB) bereits vorhanden ist.
Test:
dd if=/dev/zero of=file.in bs=1024 count=10240
time ./copy_system
Ausgabe:
./copy_system 7,54s user 88,56s system 99% cpu 1:36,23 total
Wie wir sehen, dauerte der Kopiervorgang insgesamt ~ 1 1/2 Minuten, da wir die Datei Zeichen für Zeichen kopiert haben, im nächsten Beispiel werden jeweills 1024 Byte eingelesen und in die neue Datei geschrieben.
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main() {
char block[1024];
int in, out, nread;
// open - mit dem Systemaufruf open kann ein neuer Dateideskriptor erstellt werden
// ---------------------
// Modus -> Beschreibung
// ---------------------
// O_RDONLY -> nur zum lesen oeffnen
// O_WONLY -> nur zum schreiben oeffnen
// O_RDWR -> zum lesen und schreiben oeffnen
// ---------------------
// optionaler Modus -> Beschreibung
// ---------------------
// O_APPEND -> am Ende der Datei schreiben
// O_TRUNC -> Inhalt der vorhandenen Datei wird geloescht
// O_CREAT -> erstellt die Datei mit Berechtigungen
// O_EXCL -> stellt sicher, dass nicht zwei Programme
// die selbe Datei, zur gleichen Zeit erstellen
// ---------------------
// Berechtigung -> Beschreibung
// ---------------------
// S_IRUSR -> Lesen, Eigentuemer (owner)
// S_IWUSR -> Schreiben, Eigentuemer (owner)
// S_IXUSR -> Ausfuehren, Eigentuemer (owner)
// S_IRGRP -> Lesen, Gruppe (group)
// S_IWGRP -> Schreiben, Gruppe (group)
// S_IXGRP -> Ausfuehren, Gruppe (group)
// S_IROTH -> Lesen, Andere (others)
// S_IWOTH -> Schreiben, Andere (others)
// S_IXOTH -> Ausfuehren, Andere (others)
//
// weitere Infos unter: man 2 open
//
// 1 MB Datei erstellen -> dd if=/dev/zero of=file.in bs=1024 count=10240
//
// Datei "file.in" zum lesen oeffnen
in = open("file.in", O_RDONLY);
// Datei "file.out" erstellen (Eigentuemer -> Lesen + Schreiben)
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
// 1024 Byte werden eingelesen ...
while((nread = read(in,block,sizeof(block))) > 0) {
// ... und in die neue Datei geschrieben
write(out,block,nread);
}
exit(0);
}
Test:
rm file.out
time ./copy_block
Ausgabe:
./copy_block 0,01s user 0,15s system 98% cpu 0,158 total
Hier dauerte der gleiche Vorgang nur noch ~ 0,16 Sekunden. Daher nutzt man zum kopieren von ganzen Festplatten auch gerne "dd"!
#include <stdio.h>
#include <stdlib.h>
int main() {
char c;
FILE *in, *out;
// fopen - oeffnet eine Datei
// ---------------------
// Modus -> Beschreibung
// ---------------------
// r -> nur zum lesen oeffnen
// w -> nur zum schreiben oeffnen
// a -> am Ende der Datei anhaengen
// r+ -> zum Aktualisieren oeffnen (schreiben + lesen)
// w+ -> zum Aktualisieren oeffnen, auf Null-Laenge abschneiden
// a+ -> zum Aktualisieren oeffnen, am Ende der Datei anhaengen
//
// weitere Infos unter: man fopen
//
// fgetc - liefert das naechste Byte als Zeichen aus einem Datei-Stream zurueck,
// die Funktion liefert EOF (End of File) beim Ende der Datei bzw.
// bei einem Fehler zurück
//
// weitere Infos unter: man fgetc
//
// fputc - schreibt ein Zeichen in einen Ausgabe-Datei-Stream
//
// weitere Infos unter: man fputc
//
// 1 MB Datei erstellen -> dd if=/dev/zero of=file.in bs=1024 count=10240
//
// Datei "file.in" zum lesen oeffnen
in = fopen("file.in", "r");
// Datei "file.out" erstellen (Eigentuemer -> Lesen + Schreiben)
out = fopen("file.out", "w");
// Zeichen fuer Zeichen einlesen (+ interner Puffer in der Struktur FILE) ...
while((c = fgetc(in)) != EOF) {
// ... und jedes Zeichen in die neue Datei schreiben
fputc(c,out);
}
exit(0);
}
Test:
rm file.out
time ./copy_system_2
Ausgabe:
./copy_system_2 1,10s user 0,09s system 99% cpu 1,196 total
Hier brauchen wir für 10 MB zirka 1,2 Sekunden, was um einiges schneller ist als das erste Beispiel, wo die Zeichen einzeln kopiert wurden.
Bewertung:
Ähnliche Blog-Einträge:
C-Programm - Schaltjahr Berechnung
C-Programm – Umrechnung von Zahlensystemen
C-Programm – check_mem für Nagios
C-Programm & Cflags

Du solltest, wenn du die Filestreams benutzt, die "b"-Flagge benutzen, welche bei binären Dateien benutzt wird. Um mit den Filestreams ein, zu deinem obrigen Beispiel äquivalentes Programm zu implementieren, solltest du die Funktionen fread und fwrite benutzen. Filestreams sollten auch mit fclose geschlossen werden. Deine Algorithmen sind nicht zu empfehlen, weil die DMA-Unterstützung (Festspeicherbereiche werden in den Arbeitsspeicher kopiert, ohne das die CPU arbeiten muss) nicht verwendet wird.