Sunday, August 3, 2014

Unix Prog: Unix System Overview - IO

1. Input and Output

File Descriptor: non-negative integer which is used to identify the file being accessed by the process

standard input, standard output, standard error: these are 3 file descriptors which are open whenever a new program run.

cp.c
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 #define BUFFERSIZE 4096  
   
 void err_sys(const char* msg)  
 {  
  printf("%s\n", msg);  
  exit(1);  
 }  
   
 int main(void)  
 {  
  int n;  
  char buf[BUFFERSIZE];  
   
  // Read in BUFFERSIZE(4096) characters from standard input, save into buf  
  // char array, return the number of characters written  
  // Then write the content saved in buf array to standard output, write n  
  // characters. write return the number of characters written  
  while((n=read(STDIN_FILENO,buf, BUFFERSIZE))>0)  
   if(write(STDOUT_FILENO, buf, n)!=n)  
    err_sys("write_error");  
   
  if(n<0)  
   err_sys("read error");  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./cp.out  
 Hello world!  
 Hello world!  
 Hello New York City!  
 Hello New York City!  

Explanation:
read, write, STDIN_FILENO, STDOUT_FILENO are defined at "unistd.h"
shell:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
   
 ......  
   
 /* Standard file descriptors. */  
 #define STDIN_FILENO  0    /* Standard input. */  
 #define STDOUT_FILENO  1    /* Standard output. */  
 #define STDERR_FILENO  2    /* Standard error output. */  
   
 ......  
   
 /* Read NBYTES into BUF from FD. Return the  
   number read, -1 for errors or 0 for EOF.  
   
   This function is a cancellation point and therefore not marked with  
   __THROW. */  
 extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur;  
   
 /* Write N bytes of BUF to FD. Return the number written, or -1.  
   
   This function is a cancellation point and therefore not marked with  
   __THROW. */  
 extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;  
   
 ......  

2. Standard I/O

standard I/O provide a buffered interface to the unbuffered I/O functions, which prevents us from worrying about choosing the optimal buffer size.

cp.c
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 void err_sys(const char* msg)  
 {  
  printf("%s\n", msg);  
  exit(1);  
 }  
   
 int main(void)  
 {  
  char c;  
   
  // Read one character from the stdin(standard input file stream)  
  // As long as we don't reach to the end, we write the character  
  // to stdout(standard output as file stream)  
  while((c=getc(stdin))!=EOF)  
   {  
    if (putc(c, stdout)==EOF)  
     err_sys("output error");  
   }  
   
  if(ferror(stdin))  
   err_sys("input error");  
   
  exit(0);  
 }  

shell:
After running the cp.out, whenever user put in some characters, it will get output to the standard output(screen). It never stops until user put in "CTRL+D"
 ubuntu@ip-172-31-23-227:~$ ./cp.out  
 Hello world!  
 Hello world!  
 Amazing world!  
 Amazing world!  

Explanation:
stdin, stdout: a file stream which is similar from regular file stream
getc: read one character from the specified file stream
putc: write one character to the specified file stream
shell:
1) stdio.h includes "libio.h", which defines "struct _IO_FILE"
2) Print out the libio.h which includes the definition of "struct _IO_FILE"
 ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h  
   
 ......  
   
 #include <libio.h>  
   
 ......  
   
 /* Standard streams. */  
 extern struct _IO_FILE *stdin;     /* Standard input stream. */  
 extern struct _IO_FILE *stdout;     /* Standard output stream. */  
 extern struct _IO_FILE *stderr;     /* Standard error output stream. */  
 /* C89/C99 say they're macros. Make them happy. */  
 #define stdin stdin  
 #define stdout stdout  
 #define stderr stderr  
   
 ......  
 ubuntu@ip-172-31-23-227:~$ less /usr/include/libio.h  
   
 ......  
   
 struct _IO_FILE {  
  int _flags;      /* High-order word is _IO_MAGIC; rest is flags. */  
 #define _IO_file_flags _flags  
   
  /* The following pointers correspond to the C++ streambuf protocol. */  
  /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */  
  char* _IO_read_ptr;  /* Current read pointer */  
  char* _IO_read_end;  /* End of get area. */  
  char* _IO_read_base; /* Start of putback+get area. */  
  char* _IO_write_base; /* Start of put area. */  
  char* _IO_write_ptr; /* Current put pointer. */  
  char* _IO_write_end; /* End of put area. */  
  char* _IO_buf_base;  /* Start of reserve area. */  
  char* _IO_buf_end;  /* End of reserve area. */  
  /* The following fields are used to support backing up and undo. */  
  char *_IO_save_base; /* Pointer to start of non-current get area. */  
  char *_IO_backup_base; /* Pointer to first valid character of backup area */  
  char *_IO_save_end; /* Pointer to end of non-current get area. */  
   
  struct _IO_marker *_markers;  
   
  struct _IO_FILE *_chain;  
   
  int _fileno;  
 #if 0  
  int _blksize;  
 #else  
  int _flags2;  
 #endif  
  _IO_off_t _old_offset; /* This used to be _offset but it's too small. */  
   
 #define __HAVE_COLUMN /* temporary */  
  /* 1+column number of pbase(); 0 is unknown. */  
  unsigned short _cur_column;  
  signed char _vtable_offset;  
  char _shortbuf[1];  
   
  /* char* _save_gptr; char* _save_egptr; */  
   
  _IO_lock_t *_lock;  
 #ifdef _IO_USE_OLD_IO_FILE  
 };  
   
 ......  

No comments:

Post a Comment