ist die funktion "open" eine Kernelfunktion, oder die einer lib?
> ist die funktion "open" eine Kernelfunktion, oder die einer lib?
man man
man open
Michael
--
$|++;$_=reverse',rekcaH lreP rehtonA tsuJ';$u=undef;$u=$u;$d='
select($u,$u,$u,0.01)';$l=length()-1;for$i(0..$l){$s=$l-$i;for$
j(0..$s){print' 'x$j;if($j==$s){for$c('a'..'z'){eval($d);print"$
c\b";}}print substr($_,$s,1);print"\b"x$l;eval($d);}}print"\n";
Danke! "man 2 open" :-)
>>>ist die funktion "open" eine Kernelfunktion, oder die einer lib?
>>
>>
>> man man
>> man open
>>
>> Michael
>
> Danke! "man 2 open" :-)
Wobei die 2 übrigens schon die Antwort auf die Frage enthält.
schon klar, die "2" habe ich mit "man man" herausgefunden
Im Kernel finde ich nur die Funktion "sys_open", wo wird die auf "open"
"gemappt"?
Sind die Kernelfunktionen thread-safe? die funktionen der libc sind es.
>Im Kernel finde ich nur die Funktion "sys_open", wo wird die auf "open"=20
>"gemappt"?
Wenn Du vom Userlevel aus, in C, die Funktion open() aufrufst, dann
landest Du in der C-Library. Diese macht dann fuer Dich einen Syscall,
wie auch immer das auf der entsprechenden Architektur gemacht wird.
Die Syscalls werden dabei in der Regel durch eine Nummer in einem
Register unterschieden. Der Kernel hat ein Array, was dann auf die
Funktionsnamen der In-Kernel-Implementation verweist.
Ein grep nach sys_open in _allen_ Kernel-Quellen (.c, .h., .s, .S)
wird Dir die richtigen Stellen sicher zeigen.
>Sind die Kernelfunktionen thread-safe?
Fuer geeignete Definitionen von thread-safe sicher. Was genau interessiert
Dich denn da im Zusammenhang mit "open"?
>die funktionen der libc sind es.
Da sollte man immer vorsichtig sein.
Gruss
Patrick
>> Danke! "man 2 open" :-)
>
> Wobei die 2 übrigens schon die Antwort auf die Frage enthält.
Ist es nicht eher so, dass man in seinem C Programm die Libc Funktion open
aufruft und diese dann den systemcall open durchführt?
Christoph
$ gdb /lib/libc.so.6
[...]
This GDB was configured as "i386-redhat-linux"...
(no debugging symbols found)...
(gdb) disassemble open
Dump of assembler code for function open:
0xcf620 <open>: push %ebx
0xcf621 <open+1>: mov 0x10(%esp,1),%edx
0xcf625 <open+5>: mov 0xc(%esp,1),%ecx
0xcf629 <open+9>: mov 0x8(%esp,1),%ebx
0xcf62d <open+13>: mov $0x5,%eax
0xcf632 <open+18>: int $0x80
0xcf634 <open+20>: pop %ebx
0xcf635 <open+21>: cmp $0xfffff001,%eax
0xcf63a <open+26>: jae 0xcf63d <open+29>
0xcf63c <open+28>: ret
[...]
open(3) füllt nur die Register mit den Funktionsparametern
und führt danach open(2) aus. Anschließend wird der
Rückgabewert überprüft, und eventuell errno gesetzt.
Ist man an errno nicht interessiert, kann man die Sequenz
auch mit Inline-Assembler selber bauen.
Ist natürlich extrem plattformspezifisch.
man 2 intro
man 2 syscalls
http://en.tldp.org/LDP/lki/lki-2.html#ss2.11
--
post tenebras lux. post fenestras tux.
> open(3) füllt nur die Register mit den Funktionsparametern
> und führt danach open(2) aus. Anschließend wird der
> Rückgabewert überprüft, und eventuell errno gesetzt.
>
> Ist man an errno nicht interessiert, kann man die Sequenz
> auch mit Inline-Assembler selber bauen.
> Ist natürlich extrem plattformspezifisch.
>
> man 2 intro
> man 2 syscalls
> http://en.tldp.org/LDP/lki/lki-2.html#ss2.11
>
Ist schon klar, ich frage mich aber nun, ob es nicht einen gewissen overhead
nach sich zieht erst open(3) aufzurufen?
Christoph
> Ist schon klar, ich frage mich aber nun, ob es nicht einen gewissen
> overhead nach sich zieht erst open(3) aufzurufen?
Ich weiß ja nicht, wie viele Millionen Dateien du pro Sekunde öffnen willst,
aber ich denke, der Overhead wird sich nicht so arg bemerkbar machen. Vor
allem, weil Syscalls an anderer Stelle (Kontextwechsel) um vielfaches
größere Overheads haben.
So etwas gehört gemessen, nicht geraten. ;=)
Grundsätzlich sind Systemaufrufe viel, viel zeitaufwändiger
als Funktionsaufrufe. Dramatische Performancegewinne lassen
sich durch eine Reduktion der Anzahl der Systemaufrufe erzielen.
In der Regel ist der Overhead von fopen(3) vernachlässigbar
gegenüber den eingesparten read(2) durch getc(3) bzw. fread(3).
Wie "eingespart"? fread wird intern auch nur read benutzen. getc genauso.
Man darf eben nur nicht auf die Idee kommen, mit read zeichenweise zu
lesen.
Wie oft machst Du open? Wie groß ist der Overhead eines
Funktionsaufrufs? Wieviel Zeit wird im Rest des Programms verbracht?
Ich vermute stark, daß Die Überlegungen zu diesem "Overhead"
verschwendete Zeit sind. Wenn Dein Programm zu langsam ist, dann
instrumentiere, messe, und identifiziere die hot spots. Alles andere ist
Unsinn.
Regards,
Jens
--
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
Ja.
Prog 1:
int
main (void)
{
long i;
for ( i = 0; i < 10000000; i++ )
getchar ();
return 0;
}
Prog 2:
int
main (void)
{
long i;
char c;
for ( i = 0; i < 10000000; i++ )
read (0, &c, 1); // der Standardfetishist würde hier keine 0 verwenden, sondern eine portable Lösung, die häufig nicht compilierbar ist
return 0;
}
oder
int
main (void)
{
long i;
char c;
for ( i = 0; i < 10000000; i++ )
_read (0, &c, 1); // der Standardfetishist würde hier keine 0 verwenden, sondern eine portable Lösung, die häufig nicht compilierbar ist
return 0;
}
Compilieren, ausführen mit stdin-redirekt auf eine >10 MByte große Datei.
--
Frank Klemm
> Hinweis:
> Denken, ausprobieren und messen.
Gegenhinweis:
Lesen, antworten, nochmal lesen und erst dann posten.
Ich schrieb:
>>Man darf eben nur nicht auf die Idee kommen, mit read zeichenweise zu
>>lesen.
> read (0, &c, 1); // der Standardfetishist würde
> hier keine 0 verwenden, sondern eine portable Lösung, die häufig
> nicht compilierbar ist
Hmm, impliziert portabel nicht, daß es so gut wie überall compilierbar ist?
Übrigens, gibt es ein "real-life examle", wo die id von stdin nicht 0 ist?
> read (0, &c, 1); // der Standardfetishist würde
// hier keine 0 verwenden,
// sondern eine portable Lösung,
// die häufig nicht compilierbar ist
Nein, wieso? STDIN_FILENO ist laut ISO/IEC 9945-1:1996,
8.2.1.2, p. 210 immer 0, ebenso laut IEEE Std 1003.1-2001.
Hingegen wird derjenige, der auf Portabilität ernsthaft
Wert legt, keine C++/C99-Kommentare verwenden, weil die
nämlich nicht überall compilierbar sind.
Gunnar
> Ich weiß ja nicht, wie viele Millionen Dateien du pro Sekunde öffnen willst,
> aber ich denke, der Overhead wird sich nicht so arg bemerkbar machen. Vor
> allem, weil Syscalls an anderer Stelle (Kontextwechsel) um vielfaches
> größere Overheads haben.
Der Kontextwechsel liegt bei ein paar hundert Zyklen höchstens.
Dateisystem-Lookups auf Millionen verschiedener Dateien sind wegen
Cache Misses etc. erheblich teurer.
Wer so etwas braucht, macht also etwas falsch. :-/
Aber ich habe hier mindestens 3 C-ähnliche Compiler, die
"//" kennen, aber mit STDIN_FILENO nichts anfangen können.
STDIN_FILENO verwende ich daher nicht, weil ich damit häufig Ärger hatte.
Auch fileno(stdin) oder _fileno(stdin) macht genug Probleme.
>Hingegen wird derjenige, der auf Portabilität ernsthaft
>Wert legt, keine C++/C99-Kommentare verwenden, weil die
>nämlich nicht überall compilierbar sind.
>
Wer auf Portabilität Wert legt, liefert im Makefile ein Target KandR mit,
welches die Quelle von C89 + // nach K&R-C konvertiert.
Bei mppdec hatte ich eine Basisversion C89+// und eine K&R-C ca. 14 Monate
auf der Webseite. Sie ist in dieser Zeit einmal runtergeladen worden.
Allerdings habe ich kein Testsystem gefunden, den einigsten K&R-C Compiler,
den ich auftreiben konnte, kam mit den Datenmengen nicht zurecht (war nur 16
bit).
--
Frank Klemm
typedef struct {
int fd;
int readable;
int writeable;
CFileIO OpenFile (const char* filename);
CFileIO OpenStdin (void);
CFileIO OpenStdout (void);
CFileIO OpenStderr (void);
ssize_t Read (void* dst, ssize_t len);
ssize_t Write (const void* src, ssize_t len);
int Close (void);
...
} CFileIO;
--
Frank Klemm
>>Nein, wieso? STDIN_FILENO ist laut ISO/IEC 9945-1:1996,
>>8.2.1.2, p. 210 immer 0, ebenso laut IEEE Std 1003.1-2001.
> Hier behauptete gerade jemand, daß das nicht der Fall sei.
Überprüfe den Beleg, wenn Du es nicht glaubst. Dafür ist er
ja da.
> Aber ich habe hier mindestens 3 C-ähnliche Compiler, die
> "//" kennen, aber mit STDIN_FILENO nichts anfangen können.
Und? Ich habe Compiler, auf deren Systemen STDIN_FILENO definiert
ist, die aber mit «//» nichts anfangen können. UnixWare 2.1 z. B.
> STDIN_FILENO verwende ich daher nicht, weil ich damit häufig Ärger hatte.
Ein #ifndef würde genügen, wenn Du es wolltest. Ich verwende es
einfach deshalb nicht, weil es überflüssig ist.
> Auch fileno(stdin) oder _fileno(stdin) macht genug Probleme.
Auf Unix? Kaum zu glauben. Wo?
> Bei mppdec hatte ich eine Basisversion C89+// und eine K&R-C ca. 14 Monate
> auf der Webseite. Sie ist in dieser Zeit einmal runtergeladen worden.
Es hat ja auch kein Mensch von K&R-C gesprochen.
Gunnar
> Das beste ist sowieso, für Funktionalität, die sich auf Interfaces zum OS
> bezieht, erst mal eine Interfaceklasse zu schreiben und im eigentlichen
> Programm nur noch diese zu verwenden.
Frank, wir sind hier in de.comp.os.UNIX.programming. Alle Systeme
kennen hier open() und haben standard input auf fd 0. Unter diesen
Umständen ist das nutzloser Bloat, was Du da vorschlägst.
Gunnar
>> Auch fileno(stdin) oder _fileno(stdin) macht genug Probleme.
>
> Auf Unix? Kaum zu glauben. Wo?
>
Wer will schon Programme, die nur unter Unix laufen.
>> Bei mppdec hatte ich eine Basisversion C89+// und eine K&R-C ca. 14 Monate
>> auf der Webseite. Sie ist in dieser Zeit einmal runtergeladen worden.
>
>Es hat ja auch kein Mensch von K&R-C gesprochen.
>
Es gab eine Version für C89 mit "//"-Kommentaren und eine K&R-Version.
Wenn erste Version Probleme macht, sollte die zweite Version übersetzbar
sein. Weiterhin war zweite Version mit compress statt mit gzip gepackt.
Verständlich?
--
Frank Klemm
Gegenargumente:
- Man könnte irgendwann mal das Programm portieren müssen oder wollen.
Auch wenn man am Anfang der Meinung war, daß das nie passieren dürfe.
- Programme mit Abtrennung von Interface-Stuff und eigentlicher
Funktionalität sind leichter lesbar.
- Es gibt nicht das "Unix", Unix ist eine Sammlung von Betriebssystemen mit
gewissen Ähnlichkeiten. Es gibt zwei Hauptgeschmacksrichtungen mit vielen
Geschmacksnuancen. Vielleicht will ich Funktionen nutzen, die es nur in
neueren Unices gibt (sigaction), und die man bei älteren Unices aber nicht
findet und daher nachbilden muß (signal), auch wenn diese Funktionen durch
Konzeptfehler kein fehlerfreies Programm zulassen.
--
Frank Klemm
> Was, wenn STDIN_FILENO kein Makro, sondern eine Variable ist?
Dann ist das System so kaputt, daß es nicht mehr zu retten ist.
> Wer will schon Programme, die nur unter Unix laufen.
Ich. Aber das ist nicht der Punkt. Der Punkt ist, daß alles
andere hier off-topic ist.
Gunnar
> - Es gibt nicht das "Unix", Unix ist eine Sammlung von Betriebssystemen mit
> gewissen Ähnlichkeiten. Es gibt zwei Hauptgeschmacksrichtungen mit vielen
> Geschmacksnuancen. Vielleicht will ich Funktionen nutzen, die es nur in
> neueren Unices gibt (sigaction), und die man bei älteren Unices aber nicht
> findet und daher nachbilden muß (signal), auch wenn diese Funktionen durch
> Konzeptfehler kein fehlerfreies Programm zulassen.
Hier ging es aber um open()/read() und STDIN_FILENO / 0. Das ist
auf jedem Unix-System vorhanden und wird da auch immer vorhanden
sein. Da mußt Du nicht ablenken, indem Du auf ganz andere Fälle
verweist.
Gunnar
Das wird wohl eine Floating Point Exception, womit wir doch wieder bei
Signalen waeren <g,d&rvvf>.
SCNR
Gruesse,
awiese
--
--- \|/ ______ \|/
Andreas Wiese "@' / , . \ `@"
awiese....@t-online.de /__| \____/ |__\
http://www.root-for-everybody.de.vu \___U__/
Welche?
> > Auf Unix? Kaum zu glauben. Wo?
>
> Wer will schon Programme, die nur unter Unix laufen.
Portable Programme, die nur unter Unix laufen, laufen automatisch auch
unter Windows (in den meisten Fällen, Ausnahmen fallen mir gerade keine
ein). Dank cygwin. Das erhöht die potentielle Zielgruppe enorm.
Und auf POSIX sollte man sich schon verlassen können (von den Widersprüchen
einmal abgesehen). Ebenso wie auf ANSI C - allerdings ist eine
Beschränkung auf ANSI C nicht unbedingt immer machbar und sinnvoll,
zumal wir uns hier in dco.*unix*.p befinden.
--
[EP 14]
Misato: It's Shinji.
Asuka: I know it and that's why he's stupid.
[just another Neon Genesis Evangelion scene]
So ein Unfug. Vielleicht willst Du uns erklären, warum Extratools (make
zusammen mit einem //-Wandler) mehr Portabilität bringen, als gleich auf
// zu verzichten. So ein //-Wandler ist übrigens auch nicht leicht zu
schreiben, wenn er "foo//bar" und '//' korrekt behandeln soll.
Das ist der Stoff, aus dem Bloat ist!
Und es ist der Stoff, dessen Abwesenheit zu den immensen
Schmerzensgel^WGehältern von Portierungs-Spezialisten führt.
printf ("/*\n");
....
printf ("*/\n");
den vermeintlichen Kommentar rausgeworfen hat!
Andreas
#include <stdio.h>
int
main ( void )
{
printf ("Was soll denn das :-??!\n");
return 0;
}
--
Frank Klemm
> In der Tat. Ich hatte mal ein seeehr seltsames Programmverhalten, das
> ich erst erklären konnte, als ich feststellte, das der Compiler aus
>
> printf ("/*\n");
> ....
> printf ("*/\n");
>
> den vermeintlichen Kommentar rausgeworfen hat!
Schmeiss den Compiler (genauer: Praeprozessor) weg. Innerhalb eines
Strings darf er nicht fälschlicherweise einen Kommentar entdecken.