Subject: [clisp-list] pros and cons of integer file descriptors vs. pointer objects

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Tue Jun 10 07:14:08 2003

Hi,

Sam Steingold wrote:
>> [*] Please write an essay on the pros and cons of open() etc. using
>> small integers vs. fopen() using FILE pointers. I'd be happy to
>> discuss such design issues with everybody.
>
>the original decision, I think, was predicated on avoiding 
>libc (amiga?).
Not because of Amiga. Because of mistrust on many libc (esp. malloc() therein) out there in the UNIX world at that time. But I hadn't raised my question with CLISP in mind.

Why did the design team around UNIX come up with small integers as file descriptors?
Why did the ANSI C people come up with FILE pointers instead?

When you release a library with opaque "references", what do you provide at the interface?
a) Pointers to some real objects, whose structure only you know?
b) tiny integers starting from 0, a la UNIX filedes?
c) "tickets" (aka access "cookies") i.e. arbitrary pseudo-random numbers?
d) other - please explain

How do you evaluate your library interface w.r.t. type safety, reliability, ease of use, portability, interoperability or whatever aspect you choose?

>I don't think it is worth our time to rewrite stream.d to use FILE.
Certainly not. Please don't.

Regards,
	Jorg Hohle.

---

From: Pascal Bourguignon <[email-masked]>
Date: Wed Jun 11 03:53:03 2003

> Why did the design team around UNIX come up with small integers as

Because the file descriptors refer data structures that are not in the
user space, but in the kernel  space.  Using indices in an array leaks
no information  about the  kernel, while even  using addresses  in the
kernel space leaks some information about the kernel (and possibly the
other  processes). In addition,  it would  prevent moving  kernel data
structures.

> Why did the ANSI C people come up with FILE pointers instead?

Because the FILE  structure is stored in the same  user space than the
client code of the library.  

> a) Pointers to some real objects, whose structure only you know?

Yes. Most often.

> b) tiny integers starting from 0, a la UNIX filedes?

Yes. Sometimes.

> c) "tickets" (aka access "cookies") i.e. arbitrary pseudo-random numbers?

Yes,  possibly.   While  this  is  done  usually  when  you  implement
capacities.  But this is worthwhile  only on a pure capacity based OS,
or in network protocols (thus when there is a separation of addressing
spaces again).

> How do you evaluate your library interface w.r.t. type safety,
> reliability, ease of use, portability, interoperability or whatever
> aspect you choose?

It  does not  matter very  much.  What  matters is  the  separation of
addressing spaces.  Otherwise, the  process can always scan its memory
space to find out library data structures.

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.

---

From: Kaz Kylheku <[email-masked]>
Date: Wed Jun 11 09:00:29 2003

> other  processes). In addition,  it would  prevent moving  kernel data

There are other reasons too. 

The descriptors behave like an array, so for example, it is possible to
loop over them and close them. If they were pointers, this would not be
possible without maintaining an external data structure.

Because the smallest available integer is always chosen, if an
application needs to associate a file descriptor with satellite data,
it can use a simple bounded array data structure to do so.

This is very convenient in an application that handles many tty's,
sockets or whatever. If a function like select() or poll() tells you
that some file descriptor is readable, you can index that into your
array and fetch the context structure.

The alternate design, namely providing some interface that lets the
user associate ``void *'' pointer value with a descriptor, is actually
weaker, because there may be several modules in a program that will
fight over that ``void *''. 

Oh yes, and there is one more reason: the file descriptors were
actually a fixed array in early UNIX kernels. The integer indexes are
simply a ``leak'' of the representation.

> client code of the library.  

It wasn't the ANSI C people, by the way. The Version 6 UNIX sources had
a <stdio.h> header with a FILE macro in it, I think it was like:

  #define FILE struct _iobuf

this explains why FILE is in all caps too; it started as a macro.

> > b) tiny integers starting from 0, a la UNIX filedes?

I did this some years ago in a communication protocol stack project.
An instance of the protocol stack was a C++ object. But distinct
logical communication channels were identified by integers, which were
guaranteed to be small. Thus I did not have to provide a way for the
calling application to associate context data with channels.

It was specifically that context association advantage  which led me to
duplicating the UNIX file descriptor design in that project. Not any
address space separation or anything like that.