Chapter 8: The UNIX System Interface

  The UNIX operating system provides its services through a set of system calls, which are in effect functions within the operating system that may be called by user programs.

8.1 File Descriptors

  In the UNIX operating system, all input and output is done by reading or writing files, beacuse all peripheral devices, even keyboard and screen, are files in the file system. A file descriptor is a small non-negative integet, which is analogous to the file pointer used by the standard library, or to the file handle of MS-DOS.

  When the command interpreter (the "shell") runs a program, three files are open, with file descriptors 0, 1, and 2, called the standard input, the standard output, and the standard error. If a program reads 0 and writes 1 and 2, it can do input and output without worrying about opening files.

  The user of a program can redirect I/O to and from files with < and > : prog <infile >outfile. In this case, the shell changes the default assignments for file descriptors 0 and 1 to the named files. Normally file descriptor 2 remains attached to the scree, so error messages can go there. Similar observations hold for input or output associated with a pipe. In all cases, the file assignments are changed by the shell, not by the program. The program does not know where its input comes from nor where its output goes, so long as it uses file 0 for input and 1 and 2 for output.

8.2 Low Level I/O---Read and Write

  Input and Output uses the read and write system calls, which are accessed from C programs through two functions called read and write. For both, the first argument is a file descriptor. The second argument is a character array in your program where the data is to go or come from. The third argument is the number of bytes to be transferred.

int n_read = read(int fd, char *buf, int n);
int n_write = write(int fd, char *buf, int n);

Each call returns a count of the number of bytes transferred. On reading, the number of bytes returned may be less than the number requested. A return value of zero bytes implies end of file, and -1 indicates an error of some sort. For writing, the return value is the number of bytes written; an error has occured if this isn't equal to the number requested.

  Any number of bytes can be read or written in one call. The most common values are 1, which means one character at a time ("unbuffered"), and a number like 1024 or 4096 that corresponds to a physical block size on a peripheral device. Larger size will be more efficient beacuse fewer system calls will be made.

#include “syscalls.h”

/* getchar: unbuffered single character input */
int getchar(void)
{
    char c;

    return (read(0, &c, 1) == 1) ? (unsigned char) c : EOF;
}
#include "syscalls.h"

/* getchar: simple buffered version */
int getchar(void)
{
    static char buf[BUFSIZ];
    static char *bufp = buf;
    static int n = 0;
    
    if (n == 0) {    /* buffer is empty */
        n = read(0, buf, sizeof buf);
        bufp = buf;
    }
    return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
}

 8.3 Open, Creat, Close, Unlink

#include<fcntl.h>

int fd;
int open(char *name, int flags, int perms);

fd = open(name, flags, perms);

  open is rather like the fopen discussed in Chapter 7, except that instead of returning a file pointer, it returns a file descriptor, which is just an int. open returns -1 if any error occurs. As with fopen, the name argument is a character string containg the filename. The second argument, flags, is an int that specifies how the file to be opened; the main valuse are O_RDONLY, O_WRONLY, and O_RDWR. These constants are defined in <fcntl.h> on System V UNIX systems, and in <sys/file.h> on Berkeley (BSD) versions.

int create(char *name, int perms);

fd = create(name, perms);

  create returns a file descriptor if it was able to create the file, and -1 or not. If the file already exists, create will truncate it to zero length, thereby discarding its previous contents; it is not an error to create a file that already exists.

  If the file does not already exist, create creates it with the permissions specified by the perms argument. In the UNIX system, there are nine bits of permission information associated with a file that control read, write and execute access for the owner of the file, for the owner's group, and for all others.

  The function close(int fd) breaks the connection between a file descriptor and an open file, and frees the file descriptor for use with some other file; it corresponds fclose in the standard library except that there is no buffer to flush. Termination of a program via exit or return from the main program closes all files.

  The function unlink(char *name) removes the file name from the file system. It corresponds to the standard library function remove.

8.4 Random Access---Lseek

  The system call lseek provides a way to move around in a file without reading or writing any data.

long lseek(int fd, long offset, int origin);

  lseek sets the current position in the file whose descriptor is fd to offset, which is taken relative to the location specified by origin. Subsequent reading or writing will begin at that position. origin can be 0, 1, 2 to specify that offset is to be measured from the begining, from the current position, or from the end of the file respectively.

posted @ 2014-07-12 19:29  infraio  阅读(135)  评论(0)    收藏  举报