open vs. fopen

L

Lowell Kirsh

I'm wondering when to use one function versus the other. I know open is
Unix and fopen is standard C, so I was wondering when one would want to
use open and thus lose portability. I'd imagine there must be some
advantages to open, I was just wondering what they are.

Lowell
 
C

Chris Torek

I'm wondering when to use one function versus the other. I know open is
Unix and fopen is standard C, so I was wondering when one would want to
use open and thus lose portability. I'd imagine there must be some
advantages to open, I was just wondering what they are.

More precisely, open() is in the POSIX standard, while fopen() is
in the C standard.

POSIX "imports" the entire C standard (more or less), so any POSIX
system will have fopen(), but not all ANSI/ISO C systems will have
the POSIX semantics for open(), even if they have open(). (The
comp.unix.programmer newsgroup is suitable for POSIX questions, in
general. That would be the place to ask "what can I do with open()
that I cannot do with fopen(), on a POSIX-conformant system?"
There are a few things, but not many, because POSIX also has
fcntl().)

The advantage to using a narrower standard -- that is, one that
applies to fewer systems -- is that it limits you to fewer systems,
so that you know more about them. If the only machine you *ever*
have to program is the Zorblatt-45, then things that only work on
the Zorblatt-45 are fine. It may be trivial to gronkle the
ribberlatch on the Zorblatt-45, but very difficult on the most
models of the Franikle; but the trivial code is all you need.

The advantage to using a broader standard -- that is, one that
applies to virtually every computer in the world -- is that your
code is broadly applicable. Of course, you cannot gronkle anything
in "pure" ANSI/ISO C. You cannot even draw graphics, or fsync()
files. Picking narrower standards allows you to "do more stuff",
on fewer machines.

Can you achieve your goal using the broad standard that has few
bells and whistles? Will it be significantly easier to code using
the narrow standard that only works on three brands of computer?
Or is there a middle road, in which you decide what functionality
is required above and beyond the broad (but feature-poor) ANSI/ISO
C standard, and write your code so that most of it is completely
portable, and only the "feature-invoking" code requires a rewrite
when moving from Linux to Windows, or MacOS, or Tandem NonStop, or
OS/MVS?
 
R

Richard Tobin

Lowell Kirsh said:
I'm wondering when to use one function versus the other. I know open is
Unix and fopen is standard C, so I was wondering when one would want to
use open and thus lose portability. I'd imagine there must be some
advantages to open, I was just wondering what they are.

The main reason for using open() is so that you can use the other unix
functions associated with the file descriptors it returns, like
select(). If you only need the standard C functions, use fopen().

Another situation were you might use open() is where you are going to
implement your own buffering mechanism; in that case the overhead of
stdio would be unnecessary (though probably small).

-- Richard
 
L

Lowell Kirsh

Thanks, that's exactly what I wanted to know. So it fopen buffered but
open is not?
 
L

Lowell Kirsh

You didn't really answer my question, but your response was interesting
anyway. Next time I'll take a question like this to a unix newsgroup.

Lowell
 
K

Keith Thompson

Lowell Kirsh said:
Thanks, that's exactly what I wanted to know. So it fopen buffered but
open is not?

Please don't top-post. Your response should follow any quoted text.
See most of the articles in this newsgroup for examples.

The C Rationale's discussion implies that the open/read/write
functions are unbuffered. I don't know whether that's part of their
definition. Presumably there can be some buffering in the lower-level
primitives on which these functions are implemented (e.g., in the OS
or in the firmware of a disk drive).

I don't know that much about the open/read/write family of function --
and even if I did, it wouldn't be appropriate to discuss the details
here because my inevitable mistakes wouldn't nececessarily be
corrected. Something like comp.unix.programmer would be a better
place to discuss the details.
 
R

Richard Tobin

Lowell Kirsh said:
Thanks, that's exactly what I wanted to know. So it fopen buffered but
open is not?

Yes, though you can control the buffering of stdio streams with
setvbuf(). Even if you make them unbuffered there is still likely to
be a (very) small overhead compared with the lower-level unix file
descriptors.

-- Richard
 
R

Richard Tobin

Keith Thompson said:
The C Rationale's discussion implies that the open/read/write
functions are unbuffered. I don't know whether that's part of their
definition. Presumably there can be some buffering in the lower-level
primitives on which these functions are implemented (e.g., in the OS
or in the firmware of a disk drive).

Yes there is - disk i/o works in fixed size blocks with read-ahead and
write-behind, and terminal i/o is usually line-buffered. The
motivation for stdio buffering is to avoid the overhead of a system
call for each read or write (originally on unix, but the same applies
to most operating systems). And the C preprocessor is just good
enough to allow getc() and putc() to be macros, so that
single-character i/o doesn't even need a function call each time. Of
course with inline functions that's no longer very important.
I don't know that much about the open/read/write family of function --
and even if I did, it wouldn't be appropriate to discuss the details
here

Oops, too late.

-- Richard
 
W

Walter Roberson

:I'm wondering when to use one function versus the other. I know open is
:Unix and fopen is standard C, so I was wondering when one would want to
:use open and thus lose portability.

- If you have a behaviour that you want to fcntl()
- If you want to use flags beyond those available by rwab+

For example if you want to open a modem line which does not have
carrier present then you would normally open() it with O_NDELAY .

A number of the behaviours you can impose after opening by fcntl() the
fileno() of the FILE* .

fileno() is not part of the C89 standard. fd's are not part of the
standard either -- nothing to do with open(), close(), read(), write(),
fcntl(), ioctl(), tc[gs]etattr(), dup() and so on, are part of the
C89 standard. Corner cases about what is to happen in various
conditions on a read() or write() if various flags are set or various
types of files/devices are being used, are not part of the C89
standard. Scatter/gather I/O is not part of the C89 standard.
Sockets and network connections are not part of the C89 standard.

If your needs map quite well onto the byte-stream or seekable-
byte-stream paradigm offered by fopen(), fread()/fwrite() and kin,
then you might as well use those for the sake of portability.

If you just need a little tweak into implimentation-defined
behaviour then you might choose to write in terms of the f*()
family with a stray fileno() drop-down here and there.

As your needs get further and further removed from the
byte-stream paradigm, you will likely find it increasingly
tempting to drop the f*() layer and use POSIX or system-
dependant I/O with fd's.
 
R

Randy Howard

I'm wondering when to use one function versus the other.

Well, obviously if you are concerned about portability to non-POSIX
platforms, then you use fopen() and company. If you are only
interested in POSIX (or other platforms that support open() family
calls) then you do either.
I know open is Unix and fopen is standard C,

Note that open() could do something completely different than what
you expect on some obscure system, since it's not part of standard C,
it could cause the CD-ROM to eject for all we know here. :)
so I was wondering when one would want to use open and thus lose
portability. I'd imagine there must be some advantages to open, I
was just wondering what they are.

Well, first off a lot of existing software uses it, so people aren't
likely to just eliminate the interfaces any time soon. Also, on
some platforms you may find that if you need to support files over
some arbitrary size limit (like 2GB or 4GB on a lot of 32-bit
platforms), you may be forced to use them instead of fopen() and
family. It all depends upon what extensions are provided (if any)
to get around that problem.

Also, people sometimes think that one or the other will be faster
in a given situation, and sometimes they are actually correct
about it.

A few other examples have already been given as well, so I won't
repeat them.

Just keep in mind that if fopen() and friends will do what you
need, the safest thing is to use them. If you have a special
reason to use open() instead, that isn't served by fopen(),
then there isn't really much to argue about, just do it.
 
S

Stephen Sprunk

Lowell Kirsh said:
Thanks, that's exactly what I wanted to know. So it fopen buffered but
open is not?

<OT>
Typical implementations will layer fopen() on top of open(), with additional
userland buffering to reduce the number of syscalls. open() is itself
likely to be buffered in the kernel as well to improve throughput.

There is no guarantee on any of this, though. All ISO C and POSIX specify
is the interface, not the particular implementation.
</OT>

S
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top