Unix I/O and C library I/O, why there are two sets of I/O functions?

  • Thread starter lovecreatesbeauty
  • Start date
L

lovecreatesbeauty

In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?

Thank you

lovecreatesbeauty
 
R

richselby

You're talking about the difference between library calls and system
calls. The ones in stdio (e.g. printf, fopen) are C library functions.
The others (e.g. read, write) are lower level than that, and are known
as system calls (meaning functions provided by the kernel to all other
libraries). The C library functions actually call the system calls to
do their job. But one stdio call may result in several system calls.
(Try using the command line strace utility to see which system calls a
stdio function actually boils down to)

The stdio calls, believe it or not, provide easier interfaces to the
system calls. If you do want to use the system calls directly, you have
to fiddle around with the exact number of bytes in and out each time,
which is a pain.

If you want to use system calls, go ahead. When you are writing a
program, they're pretty much the same thing, although at a kernel
level, there are differences.

Whatever you do, don't mix stdio and system calls. Ther results can be
a little strange to say the least.
 
V

Vladimir S. Oka

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek()
...

But another set of I/O functions are also defined in Unix, for
example, open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library
version or Unix version?

If you are only ever going to use your program on Unix, whichever better
fits your needs. However, if you go the Unix I/O way, you're most
likely in for a nasty experience if ever you're required to port to
some other OS. Pick your poison...

Cheers

Vladimir
 
L

loufoque

Vladimir S. Oka a écrit :
if you go the Unix I/O way, you're most
likely in for a nasty experience if ever you're required to port to
some other OS. Pick your poison...

an OS that isn't POSIX isn't a good one anyway.
 
L

Lucien Kennedy-Lamb

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?

You must realise that the low level functions (open(), close(), read(),
write(), ...) use unbuffered I/O and may therefore slow down your
program read/write operations.

I recommend only to use the standard I/O functions for portability,
speed and ease of use. You can configure the buffering used by the
standard I/O functions by calling setvbuf().

Lucien Kennedy-Lamb
 
R

Robin Haigh

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?


One of the original motivations for the stdio library was to provide a layer
of buffering so that character-based calls like getc(), fgets() and printf()
could be implemented without the overhead of doing system I/O one byte at a
time (if the o.s. and the device support such a thing at all).

Bear in mind also that fread() returns the amount of data requested, if
possible, whereas read() gives you no such guarantee. A lot of the time,
you have to write more code to use the low-level calls.
 
E

Eric Sosman

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?

To the question in your subject line: C's I/O and Unix'
I/O are different because C can operate on systems that are
not Unix.

To the question in your message: Neither set of functions
is always "more suitable." Which is more suitable: a hammer
or a saw? A hand-operated drill, a battery-powered drill, a
portable drill powered by house current, or a fixed-position
drill press? It all depends on the task at hand and on where
you want to be able to do it.

Various responders have offered information that's either
incorrect, incomplete, or misleading. Rather than post a
whole flurry of rebuttals, I'll package them all here:

richselby says fopen() and friends are library functions
while open() and the like are system calls. That's a detail
of the implementation, true on many systems but certainly
not on all. On some systems, both fopen() and open() are
library functions.

loufoque opines that only POSIX-compliant systems are any
good. It's pointless to dispute his (?) opinion, but the
implication that open() and friends on POSIX systems share
all the characteristics found in Unix implementations.

Lucien Kennedy-Lamb explains that fopen() and friends are
higher-level functions that rest upon lower-level system calls
like open(). This is really just richselby's mistake all over
again: It's often true, but not universally true.

Summary: fopen() and friends are part of the C Standard
library, found in all hosted C implementations, even those
that do not run under Unix or under POSIX. open() and the
like are specified by POSIX, but only in terms of what they
do, not how they do it. They may or may not be "system calls,"
and they may or may not be "lower level" calls.
 
L

loufoque

Lucien Kennedy-Lamb a écrit :
You must realise that the low level functions (open(), close(), read(),
write(), ...) use unbuffered I/O and may therefore slow down your
program read/write operations.

That's not true.
 
K

Keith Thompson

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?

If you want maximum portability, you should obviously use only the
functions defined by the C standard.

The Unix-specific (or POSIX-specific) functions may provide some
features that the standard C functions don't. <OT>For example,
open()'s flags parameter gives you more control over how the file is
opened than fopen()'s mode parameter.</OT> If you really need that
extra functionality, you'll need to use the POSIX functions -- but
there's a good chance you don't really need it.

It's quite possible that you'll never need to port your program to a
system that doesn't support POSIX (though you can't really be sure of
that). Even in that case, I recommend using the C standard functions
rather than the POSIX-specific functions. They're easier to use, and
they typically provide buffering that can make your program more
efficient.

Somebody elsethread said something about function calls vs. system
calls. That's a system-specific distinction that you shouldn't have
to worry about even if you're writing system-specific code. The C
language has no concept of "system calls"; they're all just functions.
<OT>I don't think POSIX refers to system calls either, but I could be
mistaken; the POSIX interface can be implemented on top of lower-level
calls, just as the <stdio.h> interface can be.</OT> In Unix, a
system call might be implemented differently than a call to a library
function, but as far as your program is concerned it's just another
function call.

If you have more questions in this area, comp.unix.programmer would
probably be a better place to ask.
 
I

Ian Collins

Eric said:
Summary: fopen() and friends are part of the C Standard
library, found in all hosted C implementations, even those
that do not run under Unix or under POSIX. open() and the
like are specified by POSIX, but only in terms of what they
do, not how they do it. They may or may not be "system calls,"
and they may or may not be "lower level" calls.
Well put.
 
?

=?iso-8859-1?q?Dag-Erling_Sm=F8rgrav?=

richselby said:
You're talking about the difference between library calls and system
calls. The ones in stdio (e.g. printf, fopen) are C library functions.
The others (e.g. read, write) are lower level than that, and are known
as system calls (meaning functions provided by the kernel to all other
libraries). The C library functions actually call the system calls to
do their job. But one stdio call may result in several system calls.
(Try using the command line strace utility to see which system calls a
stdio function actually boils down to)

You are making several incorrect assumptions here.

open(), read(), write(), close() etc. are part of the POSIX standard.
POSIX does not differentiate between library functions and system
calls; I do not believe it even uses the term "system call".

Although POSIX has been merged into the Single Unix Specification, is
not synonymous with what we commonly regard as Unix. In fact, most
operating systems which are grouped under the term Unix in common
parlance are not Unix; they are derivatives or clones. Only a very
few Unix-like operating systems are actually certified as Unix.

POSIX can be (and has been) implemented on e.g. Microsoft Windows. In
fact, there are several partial or complete implementations of POSIX
for Windows; at least one of them (Interix / SFU) is implemented as a
separate kernel personality, but others (like Cygwin) are implemented
on top of the Windows API, and most of what you think of as system
calls are in fact library functions which invoke Windows system
library or kernel calls behind the scenes. In an environment like
this, it is not unlikely that both open() and fopen() are layered
directly on top of the underlying system API, instead of one being
implemented in terms of the other.
The stdio calls, believe it or not, provide easier interfaces to the
system calls. If you do want to use the system calls directly, you have
to fiddle around with the exact number of bytes in and out each time,
which is a pain.

There is no conceptual difference between fwrite() and write(),
although fwrite() is usually buffered and write() usually is not (and
if it is, there is no standardized API to manipulate the buffer). The
only stream-based functions which have no equivalent that operate on
file descriptors are the printf() / scanf() family (because they
cannot be implemented efficiently without a buffer).

DES
 
I

Ian Collins

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?
One issue that hasn't been addressed so far (maybe because it's off
topic?) is that the posix functions operate with a file descriptor,
which can refer to things other than files.

For more information, go to comp.unix.programmer.
 
R

Rod Pemberton

lovecreatesbeauty said:
In the C programming language, I/O operation functions are declared in
stdio.h, for example, fopen(), fclose(), fwrite(), fread(), fseek() ...

But another set of I/O functions are also defined in Unix, for example,
open(), close(), read(), write(), lseek() ...

Which set of functions is more suitable for I/O task, C library version
or Unix version?

You need to find answers to other questions:

1) Do you need ANSI/ISO C compliance or portability?
2) Do you want IO buffering?
3) Which is more important speed or ease of programming?

Most language compilers (except PL/1, FORTH) were written after the
operating system was implemented and are dependent on a small set of
operating system specific functions. P.J. Plauger layers 'fopen(),
fclose(), fwrite(), fread(), fseek()' on top of 'open(), close(), read(),
write(), lseek()' in his classic book (pg 447) "The Standard C Library."
The ANSI/ISO C functions of GLIBC are also layered on top of POSIX operating
system functions. In fact, just about anywhere you find a C compiler (VAX
VMS, Stratus VOS, Windows, MS-DOS, Linux), the ANSI/ISO C functions will
layered onto the OS's low level functions.


Rod Pemberton
 
J

Jordan Abel

To the question in your subject line: C's I/O and Unix'
I/O are different because C can operate on systems that are
not Unix.

Though I suspect that the Unix I/O functions can be faked to some degree
in standard C.

say,

#define OPEN_MAX 20

static FILE *_files[OPEN_MAX] = { stdin, stdout, stderr };

int fileno(FILE *x) {
for(int i=0;i<OPEN_MAX;i++) if(_files == x) return i;
return -1;
}

#define O_RDONLY 0 #define O_WRONLY 1 #define O_RDWR 2 ...
static char **flags = {
"rb", "wb", "wb+", NULL, ...
}

int open(char *fn, int flag, ...) {
return fileno(fopen(fn,flags[flag]));
}

and so forth.

Something analogous to O_EXCL and O_CREAT might have been nice to have
in standard C [O_CREAT: create the file if it doesn't exist - if flag is
not set, fail if the file does not exist. O_EXCL: fail if the file
exists] I don't see any reason why such a thing couldn't exist - anyone
have any ida why it doesn't?
 
J

Jordan Abel

True or not (I honestly don't know), it's a question for
comp.unix.programmer.

There may be kernel buffers involved, but there's no
buffering at the user level [which means that it requires a
trip to the system and back (two context switches) per call]
 
J

Jordan Abel

open(), read(), write(), close() etc. are part of the POSIX standard.
POSIX does not differentiate between library functions and system
calls; I do not believe it even uses the term "system call".

True. what are "system calls" is a matter of tradition, rather than
standardized fact. And there are variations between systems [on
traditional unix systems, all four you listed are system calls, or, more
precisely, very thin wrappers. around system calls.]
POSIX can be (and has been) implemented on e.g. Microsoft Windows. In
fact, there are several partial or complete implementations of POSIX
for Windows; at least one of them (Interix / SFU) is implemented as a
separate kernel personality, but others (like Cygwin) are implemented
on top of the Windows API, and most of what you think of as system
calls are in fact library functions which invoke Windows system
library or kernel calls behind the scenes. In an environment like
this, it is not unlikely that both open() and fopen() are layered
directly on top of the underlying system API, instead of one being
implemented in terms of the other.

Except that each FILE * is required to have a file number for fileno(),
so i suspect fopen is _still_ layered on top of open() in that case.
[doesn't windows come with an _open() call that more or less fakes posix
open()?]

Though I suppose that open() could be layered on top of fopen() and
fileno(), as I illustrated in another message.
There is no conceptual difference between fwrite() and write(),
although fwrite() is usually buffered and write() usually is not (and
if it is, there is no standardized API to manipulate the buffer). The
only stream-based functions which have no equivalent that operate on
file descriptors are the printf() / scanf() family (because they
cannot be implemented efficiently without a buffer).

Not that it hasn't stopped gnu from trying. [such a function, though,
could provide its own buffer, which it then write()s.]
 
C

CBFalconer

Dag-Erling Smørgrav said:
.... snip ...

There is no conceptual difference between fwrite() and write(),
although fwrite() is usually buffered and write() usually is not
(and if it is, there is no standardized API to manipulate the
buffer). The only stream-based functions which have no equivalent
that operate on file descriptors are the printf() / scanf() family
(because they cannot be implemented efficiently without a buffer).

There is a large difference. The fwrite etc. call family is
guaranteed to be available by the standard. The write etc. family
need not be available, and in fact is often not, or may have
entirely different undocumented semantics and characteristics.
Thus they are off-topic here, where we deal with the portable C
language only.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
K

Keith Thompson

Ian Collins said:
One issue that hasn't been addressed so far (maybe because it's off
topic?) is that the posix functions operate with a file descriptor,
which can refer to things other than files.

A FILE* can also refer to things other than "files" (depending on what
you mean by "file"). said:
For more information, go to comp.unix.programmer.

Indeed.
 
C

Christian Bau

"Vladimir S. Oka said:
If you are only ever going to use your program on Unix, whichever better
fits your needs. However, if you go the Unix I/O way, you're most
likely in for a nasty experience if ever you're required to port to
some other OS. Pick your poison...

Another advantage of Standard C is that anybody who knows the C language
can read and modify the code, so you are not restricted to those who
understand Unix as well.

So unless you can see a significant advantage in using Unix calls (and
the original poster was asking a question about that, so he _doesn't_
see any significant advantage), C functions are just more widely
portable than Unix functions, or MacOS functions, or Windows functions.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top