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