2017-04-11 21:13:36 +00:00
|
|
|
@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
|
2017-10-07 00:16:47 +00:00
|
|
|
* _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
|
2017-04-11 21:13:36 +00:00
|
|
|
* _lseek_r:: Reentrant version of lseek
|
2017-10-07 00:16:47 +00:00
|
|
|
@ifset STDIO64
|
|
|
|
* _open64_r:: Reentrant version of open64
|
|
|
|
@end ifset
|
|
|
|
* _open_r:: Reentrant version of open
|
2017-04-11 21:13:36 +00:00
|
|
|
* _read_r:: Reentrant version of read
|
2017-10-07 00:16:47 +00:00
|
|
|
* _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
|
2017-04-11 21:13:36 +00:00
|
|
|
* _wait_r:: Reentrant version of wait
|
2017-10-07 00:16:47 +00:00
|
|
|
* _write_r:: Reentrant version of write
|
2017-04-11 21:13:36 +00:00
|
|
|
@end menu
|
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@lowersections
|
|
|
|
@page
|
|
|
|
@include reent/closer.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/execr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
|
|
|
@ifset STDIO64
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/fstat64r.def
|
2017-04-11 21:13:36 +00:00
|
|
|
@end ifset
|
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/fstatr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/linkr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
|
|
|
@ifset STDIO64
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/lseek64r.def
|
2017-04-11 21:13:36 +00:00
|
|
|
@end ifset
|
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/lseekr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@ifset STDIO64
|
|
|
|
@page
|
|
|
|
@include reent/open64r.def
|
|
|
|
@end ifset
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/openr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/readr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/sbrkr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/signalr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
|
|
|
@ifset STDIO64
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/stat64r.def
|
2017-04-11 21:13:36 +00:00
|
|
|
@end ifset
|
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/statr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/timesr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/unlinkr.def
|
2017-04-11 21:13:36 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
@page
|
|
|
|
@include reent/writer.def
|
|
|
|
@raisesections
|