400 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			TeX
		
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			TeX
		
	
	
	
@c                                           -*- Texinfo -*-
 | 
						|
@node Syscalls
 | 
						|
@chapter System Calls
 | 
						|
 | 
						|
@cindex linking the C library
 | 
						|
The C subroutine library depends on a handful of subroutine calls for
 | 
						|
operating system services.  If you use the C library on a system that
 | 
						|
complies with the POSIX.1 standard (also known as IEEE 1003.1), most of
 | 
						|
these subroutines are supplied with your operating system.
 | 
						|
 | 
						|
If some of these subroutines are not provided with your system---in
 | 
						|
the extreme case, if you are developing software for a ``bare board''
 | 
						|
system, without an OS---you will at least need to provide do-nothing
 | 
						|
stubs (or subroutines with minimal functionality) to allow your
 | 
						|
programs to link with the subroutines in @code{libc.a}.
 | 
						|
 | 
						|
@menu
 | 
						|
* Stubs::		Definitions for OS interface
 | 
						|
* Reentrant Syscalls::	Reentrant covers for OS subroutines
 | 
						|
@end menu
 | 
						|
 | 
						|
@node Stubs
 | 
						|
@section Definitions for OS interface
 | 
						|
@cindex stubs
 | 
						|
 | 
						|
@cindex subroutines for OS interface
 | 
						|
@cindex OS interface subroutines
 | 
						|
This is the complete set of system definitions (primarily subroutines)
 | 
						|
required; the examples shown implement the minimal functionality
 | 
						|
required to allow @code{libc} to link, and fail gracefully where OS
 | 
						|
services are not available.  
 | 
						|
 | 
						|
Graceful failure is permitted by returning an error code.  A minor
 | 
						|
complication arises here: the C library must be compatible with
 | 
						|
development environments that supply fully functional versions of these
 | 
						|
subroutines.  Such environments usually return error codes in a global
 | 
						|
@code{errno}.  However, the Red Hat newlib C library provides a @emph{macro}
 | 
						|
definition for @code{errno} in the header file @file{errno.h}, as part
 | 
						|
of its support for reentrant routines (@pxref{Reentrancy,,Reentrancy}).
 | 
						|
 | 
						|
@cindex @code{errno} global vs macro
 | 
						|
The bridge between these two interpretations of @code{errno} is
 | 
						|
straightforward: the C library routines with OS interface calls
 | 
						|
capture the @code{errno} values returned globally, and record them in
 | 
						|
the appropriate field of the reentrancy structure (so that you can query
 | 
						|
them using the @code{errno} macro from @file{errno.h}).
 | 
						|
 | 
						|
This mechanism becomes visible when you write stub routines for OS
 | 
						|
interfaces.   You must include @file{errno.h}, then disable the macro,
 | 
						|
like this:
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
@end example
 | 
						|
 | 
						|
@noindent
 | 
						|
The examples in this chapter include this treatment of @code{errno}.
 | 
						|
 | 
						|
@ftable @code
 | 
						|
@item _exit
 | 
						|
Exit a program without cleaning up files.  If your system doesn't
 | 
						|
provide this, it is best to avoid linking with subroutines that require
 | 
						|
it (@code{exit}, @code{system}).
 | 
						|
 | 
						|
@item close
 | 
						|
Close a file.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int close(int file) @{
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item environ
 | 
						|
A pointer to a list of environment variables and their values.  For a
 | 
						|
minimal environment, this empty list is adequate:
 | 
						|
 | 
						|
@example
 | 
						|
char *__env[1] = @{ 0 @};
 | 
						|
char **environ = __env;
 | 
						|
@end example
 | 
						|
 | 
						|
@item execve
 | 
						|
Transfer control to a new process.  Minimal implementation (for a system
 | 
						|
without processes):
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int execve(char *name, char **argv, char **env) @{
 | 
						|
  errno = ENOMEM;
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item fork
 | 
						|
Create a new process.  Minimal implementation (for a system without processes):
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int fork(void) @{
 | 
						|
  errno = EAGAIN;
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item fstat
 | 
						|
Status of an open file.  For consistency with other minimal
 | 
						|
implementations in these examples, all files are regarded as character
 | 
						|
special devices.  The @file{sys/stat.h} header file required is
 | 
						|
distributed in the @file{include} subdirectory for this C library.
 | 
						|
 | 
						|
@example
 | 
						|
#include <sys/stat.h>
 | 
						|
int fstat(int file, struct stat *st) @{
 | 
						|
  st->st_mode = S_IFCHR;
 | 
						|
  return 0;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item getpid
 | 
						|
Process-ID; this is sometimes used to generate strings unlikely to
 | 
						|
conflict with other processes.  Minimal implementation, for a system
 | 
						|
without processes:
 | 
						|
 | 
						|
@example
 | 
						|
int getpid(void) @{
 | 
						|
  return 1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item isatty
 | 
						|
Query whether output stream is a terminal.   For consistency with the
 | 
						|
other minimal implementations, which only support output to
 | 
						|
@code{stdout}, this minimal implementation is suggested:
 | 
						|
 | 
						|
@example
 | 
						|
int isatty(int file) @{
 | 
						|
  return 1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item kill
 | 
						|
Send a signal.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int kill(int pid, int sig) @{
 | 
						|
  errno = EINVAL;
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item link
 | 
						|
Establish a new name for an existing file.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int link(char *old, char *new) @{
 | 
						|
  errno = EMLINK;
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item lseek
 | 
						|
Set position in a file.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int lseek(int file, int ptr, int dir) @{
 | 
						|
  return 0;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item open
 | 
						|
Open a file.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int open(const char *name, int flags, int mode) @{
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item read
 | 
						|
Read from a file.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int read(int file, char *ptr, int len) @{
 | 
						|
  return 0;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item sbrk
 | 
						|
Increase program data space.  As @code{malloc} and related functions
 | 
						|
depend on this, it is useful to have a working implementation.  The
 | 
						|
following suffices for a standalone system; it exploits the symbol
 | 
						|
@code{_end} automatically defined by the GNU linker.
 | 
						|
 | 
						|
@example
 | 
						|
@group
 | 
						|
caddr_t sbrk(int incr) @{
 | 
						|
  extern char _end;		/* @r{Defined by the linker} */
 | 
						|
  static char *heap_end;
 | 
						|
  char *prev_heap_end;
 | 
						|
 
 | 
						|
  if (heap_end == 0) @{
 | 
						|
    heap_end = &_end;
 | 
						|
  @}
 | 
						|
  prev_heap_end = heap_end;
 | 
						|
  if (heap_end + incr > stack_ptr) @{
 | 
						|
    write (1, "Heap and stack collision\n", 25);
 | 
						|
    abort ();
 | 
						|
  @}
 | 
						|
 | 
						|
  heap_end += incr;
 | 
						|
  return (caddr_t) prev_heap_end;
 | 
						|
@}
 | 
						|
@end group
 | 
						|
@end example
 | 
						|
 | 
						|
@item stat
 | 
						|
Status of a file (by name).  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int stat(char *file, struct stat *st) @{
 | 
						|
  st->st_mode = S_IFCHR;
 | 
						|
  return 0;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item times
 | 
						|
Timing information for current process.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
int times(struct tms *buf) @{
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item unlink
 | 
						|
Remove a file's directory entry.  Minimal implementation:
 | 
						|
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int unlink(char *name) @{
 | 
						|
  errno = ENOENT;
 | 
						|
  return -1; 
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item wait
 | 
						|
Wait for a child process.  Minimal implementation:
 | 
						|
@example
 | 
						|
#include <errno.h>
 | 
						|
#undef errno
 | 
						|
extern int errno;
 | 
						|
int wait(int *status) @{
 | 
						|
  errno = ECHILD;
 | 
						|
  return -1;
 | 
						|
@}
 | 
						|
@end example
 | 
						|
 | 
						|
@item write
 | 
						|
Write to a file.  @file{libc} subroutines will use this
 | 
						|
system routine for output to all files, @emph{including}
 | 
						|
@code{stdout}---so if you need to generate any output, for example to a
 | 
						|
serial port for debugging, you should make your minimal @code{write}
 | 
						|
capable of doing this.  The following minimal implementation is an
 | 
						|
incomplete example; it relies on a @code{outbyte} subroutine (not
 | 
						|
shown; typically, you must write this in assembler from examples
 | 
						|
provided by your hardware manufacturer) to actually perform the output.
 | 
						|
 | 
						|
@example
 | 
						|
@group
 | 
						|
int write(int file, char *ptr, int len) @{
 | 
						|
  int todo;
 | 
						|
 | 
						|
  for (todo = 0; todo < len; todo++) @{
 | 
						|
    outbyte (*ptr++);
 | 
						|
  @}
 | 
						|
  return len;
 | 
						|
@}
 | 
						|
@end group
 | 
						|
@end example
 | 
						|
 | 
						|
@end ftable
 | 
						|
 | 
						|
@page
 | 
						|
@node Reentrant Syscalls
 | 
						|
@section Reentrant covers for OS subroutines
 | 
						|
 | 
						|
Since the system subroutines are used by other library routines that
 | 
						|
require reentrancy, @file{libc.a} provides cover routines (for example,
 | 
						|
the reentrant version of @code{fork} is @code{_fork_r}).  These cover
 | 
						|
routines are consistent with the other reentrant subroutines in this
 | 
						|
library, and achieve reentrancy by using a reserved global data block
 | 
						|
(@pxref{Reentrancy,,Reentrancy}).
 | 
						|
 | 
						|
@menu
 | 
						|
* _close_r::	Reentrant version of close
 | 
						|
* _execve_r::	Reentrant version of execve
 | 
						|
* _fork_r::	Reentrant version of fork
 | 
						|
@ifset STDIO64
 | 
						|
* _fstat64_r::	Reentrant version of fstat64
 | 
						|
@end ifset
 | 
						|
* _fstat_r::	Reentrant version of fstat
 | 
						|
* _getpid_r::	Reentrant version of getpid
 | 
						|
* _kill_r::	Reentrant version of kill
 | 
						|
* _link_r::	Reentrant version of link
 | 
						|
@ifset STDIO64
 | 
						|
* _lseek64_r::	Reentrant version of lseek64
 | 
						|
@end ifset
 | 
						|
* _lseek_r::	Reentrant version of lseek
 | 
						|
@ifset STDIO64
 | 
						|
* _open64_r::	Reentrant version of open64
 | 
						|
@end ifset
 | 
						|
* _open_r::	Reentrant version of open
 | 
						|
* _read_r::	Reentrant version of read
 | 
						|
* _sbrk_r::	Reentrant version of sbrk
 | 
						|
@ifset STDIO64
 | 
						|
* _stat64_r::	Reentrant version of stat64
 | 
						|
@end ifset
 | 
						|
* _stat_r::	Reentrant version of stat
 | 
						|
* _times_r::	Reentrant version of times
 | 
						|
* _unlink_r::	Reentrant version of unlink
 | 
						|
* _wait_r::	Reentrant version of wait
 | 
						|
* _write_r::	Reentrant version of write
 | 
						|
@end menu
 | 
						|
 | 
						|
@lowersections
 | 
						|
@page
 | 
						|
@include reent/closer.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/execr.def
 | 
						|
 | 
						|
@ifset STDIO64
 | 
						|
@page
 | 
						|
@include reent/fstat64r.def
 | 
						|
@end ifset
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/fstatr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/linkr.def
 | 
						|
 | 
						|
@ifset STDIO64
 | 
						|
@page
 | 
						|
@include reent/lseek64r.def
 | 
						|
@end ifset
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/lseekr.def
 | 
						|
 | 
						|
@ifset STDIO64
 | 
						|
@page
 | 
						|
@include reent/open64r.def
 | 
						|
@end ifset
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/openr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/readr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/sbrkr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/signalr.def
 | 
						|
 | 
						|
@ifset STDIO64
 | 
						|
@page
 | 
						|
@include reent/stat64r.def
 | 
						|
@end ifset
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/statr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/timesr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/unlinkr.def
 | 
						|
 | 
						|
@page
 | 
						|
@include reent/writer.def
 | 
						|
@raisesections
 |