Re: fopen v. open and more
- From: Rainer Weikusat <rweikusat@xxxxxxxxxxx>
- Date: Mon, 21 Nov 2011 20:49:55 +0000
scott@xxxxxxxxxxxxx (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@xxxxxxxxxxx> writes:
André Gillibert <MetaEntropy.removeThis@xxxxxxxxx> writes:
Fritz Wuehler <fritz@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
wrote:
I read fopen is a libc call and open is a syscall. I
understand the difference but I don't know what the Right Thing To Do is
when coding on UNIX. Should I use fopen and get the advantages of the
library wrapper or use a syscall to eliminate library overhead? If I use
open can I use fread or do I need to use all syscall or all libc call for a
specific type of request and not mix and match?
fopen(3) is more portable than open(2), as it's in the C90 and C99
standards, while open(2) is POSIX. However, open(2) is pretty portable
too. Even many MS-DOS and Win32 compilers got it.
On *NIX, the main difference between fopen(3) and open(2) is that fopen
is higher level, providing buffered I/O and formatting functions.
This is why for many single-byte read/write, fgetc/fputc is usually much
faster than read(2)/write(2).
stdio provides character stream semantics on top of a block based I/O
facility.
The underlying read(2)/write(2)/pread(2)/pwrite(2) that are traditionally
used for stdio implementations are not precisely block-based. While the
underlying device I/O's that are issued must be block aligned, and are
generally (but not necessarily) block-sized (where the block size is generally
a multiple of the host system page size, e.g. 4096 bytes), the operating system
itself will first buffer the I/O to or from the device in kernel memory
(known as the file cache (formerly buffer cache)), and the read/pread/write/pwrite
calls will copy from the kernel buffer to the requested application
buffer.
I was using the term more losely to mean 'I/O done in units >> 1
byte', either because this required by the underlying 'transport', eg,
the 'raw I/O' facilities you mentioned or datagram sockets, or to
achieve greater efficiency, such as when using regular files or TCP.
Logically, a stdio-stream is similar to something like a serial line
where characters arrive (or are sent) one after another. For example,
this is a program which reads the first line of text from its standard
input and prints it with the help of stdio (error handling purposely
omitted):
------------------
#include <stdio.h>
int main(void)
{
int c;
while (c = getchar(), c != EOF && c != '\n') putchar(c);
putchar('\n');
return 0;
}
------------------
A reasonably efficient way to the the same with read/write could look
like this:
------------------
#include <unistd.h>
static void Write(int fd, char *p, ssize_t tw)
{
ssize_t nw;
while (nw = write(fd, p, tw), nw > 0 && (tw -= nw)) p += nw;
}
int main(void)
{
char buf[4096], *p, *e;
int c;
ssize_t nr;
c = 0;
do {
nr = read(0, buf, sizeof(buf));
if (nr < 1) break;
p = buf;
e = p + nr;
while ((c = *p++) != '\n' && p < e);
Write(1, buf, p - buf);
} while (c != '\n');
if (c != '\n') Write(1, "\n", 1);
return 0;
}
------------------
It is also a nice demonstration that some more exotic C features are
genuinely useful (postincrement is exotic in the sense that people
usually used it habitually and not because of its specific semantics).
.
- Follow-Ups:
- Re: fopen v. open and more
- From: Scott Lurndal
- Re: fopen v. open and more
- References:
- fopen v. open and more
- From: Fritz Wuehler
- Re: fopen v. open and more
- From: André Gillibert
- Re: fopen v. open and more
- From: Rainer Weikusat
- Re: fopen v. open and more
- From: Scott Lurndal
- fopen v. open and more
- Prev by Date: Re: ps to display cpu per thread basis
- Next by Date: Re: ps to display cpu per thread basis
- Previous by thread: Re: fopen v. open and more
- Next by thread: Re: fopen v. open and more
- Index(es):
Relevant Pages
|