| @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 |