Complete.Org: Mailing Lists: Archives: linux-help: June 2000:
[linux-help] Re: Blood and Guts
Home

[linux-help] Re: Blood and Guts

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: linux-help@xxxxxxxxx
Subject: [linux-help] Re: Blood and Guts
From: Tom Hull <thull@xxxxxxxxxxx>
Date: Wed, 07 Jun 2000 18:29:43 -0500
Reply-to: linux-help@xxxxxxxxx

I don't have all of the answers here, nor the time to try to figure them
out. The authors of gcc made some style decisions, which help them to use
the same header files to support a plethora of compiler options (k&r c,
ansi c, c++) and platform choices.

The first thing to understand is that ANSI C reserves all symbols beginning
with __ (two underscore characters) for the compiler/system implementers.

"Lrs v.d.Ast" wrote:
> 
> Hallo Linux C gurus:
> 
> I was poking around with man pages and I found the write(2) systems call. It
> writes to a file descriptor (the default is 1, standard output). As I
> understand printf calls this to actually get the "printing" done. I started
> poking around the #include file, unistd.h (required to use write), and I found
> a (for me) the cryptic lines:
> 
> extern ssize_t __write __P ((int __fd, __const __ptr_t __buf, size_t __n));
> extern ssize_t write __P ((int __fd, __const __ptr_t __buf, size_t __n));

__P() is a preprocessor macro (a #define). See <sys/cdefs.h>. It either drops
the contents, or disappears, so that the first line can be:

  extern ssize_t __write(int __fd, __const __ptr_t __buf, size_t __n);
  extern ssize_t __write();

Depends on whether you want prototypes or not.

The reason there's two function declarations, one for __write() and one for
write(), is that the latter is a weak symbol. This means you can write your
own write() without creating a multiply-defined link error when you link in
-lc. This is useful for programs like strace. The default write() calls the
real __write(); so can you.

__fd, __buf, and __n are just identifiers. They have __ in front of them for
the simple reason that you are not supposed to ever write a program where you
declare symbols beginning with __; only the compiler/system implementer is
allowed to do that. (Nothing stops you but good sense.) If you were to do
something like:

  #define buf ((char*) mystructp.myvoidp)

which is legal, even if bizarre, this wouldn't mess up the __buf declaration.

I'm less sure of the following, but I think these are good guesses:

  -- __const is a built-in keyword, which means const for ansi c and c++,
     nothing for k&r c (which didn't use const).

  -- __ptr_t is a funky typedef; this is basically because modern versions of
     write(2) declare the second argument as (void*), but k&r c doesn't do
     (void*), and early versions of write(2) used (char*). gcc can decide
     what to do with __ptr_t at run time according to compiler flags.

> I understand extern to allow globally declared stuff to not step on each 
> other,
> hence ssize_t is declared as a global in some other file, right? I'm confused
> by how ssize_t is followed by a __write (or write) but then a space then __P
> then double parentheses! What's going on here?

The space just separates the two tokens: __write and __P. ssize_t is a typedef.
There's messy history behind this: originally an int, then it became a size_t
or -1, and now it can be a 64-bit value with large file support.

> I guess __P is the real write
> function, embedded in the __write function? Also, what is the convention for
> this double underscore stuff? And finally, where is the code where my write()
> function actually gets done?

The write() function is in glibc (-lc), but the only thing it does is to make
a system call. write(2) is implemented in the kernel, through the vfs interface
(virtual file system) and ultimately through the device driver via some messy
cache management.

Any function foo referred to as foo(2) is a system call, which is implemented
in the kernel. (Well, almost always; some are faked in glibc.)

> Hopefully somebody knows and maybe somebody can put me on the trail of a book,
> etc. that will explain some of this blood and guts stuff.

Start with:

  http://www.gnu.org/software/gcc/onlinedocs/

Expect some tough sledding. Don't know where you go from there.

> Lars v.d. Ast
> 
> -- This is the linux-help@xxxxxxxxx list.  To unsubscribe,
> visit http://tmp2.complete.org/cgi-bin/listargate-aclug.cgi

-- 
/*
 *  Tom Hull * thull@xxxxxxxxxxx * http://www.ocston.org/~thull/
 */

-- This is the linux-help@xxxxxxxxx list.  To unsubscribe,
visit http://tmp2.complete.org/cgi-bin/listargate-aclug.cgi


[Prev in Thread] Current Thread [Next in Thread]