Originally intended to practice a simple model, the main focus on the main model, first with UNIX I/O fooled, but not encapsulated read and write used to be really tired, or directly with the predecessors have achieved a good advanced version of Read, write.
UNIX I/o Read, write
#include <unistd.h>ssize_t read (int fd, void* buf, size_t N), if successful it is the number of bytes read, if EOF is 0, if error is -1;ssize_t write (int fd, Const void* BUF, size_t n); The number of bytes written if successful, or 1 if an error occurs
BUF the location of the copied, n the maximum number of copies of bytes, FD descriptor
In some cases, read and write transmit less than the estimated number of bytes (short count) for various reasons, but sometimes this is not caused by errors, and may be due to several reasons.
1, read the EOF: Suppose we are going to read a file, the file from the current file location only contains 30 bytes, and we read in 60-byte slices (normally repeated calls to read, write incoming n fixed). This way down, the return value is 30, and after that, the EOF signal is emitted by returning to zero.
2, read from the terminal, each read function will send a line of text. (This will continue to be returned and then repeatedly called, which can be handled intelligently after the encapsulation of Read).
3, read and write network sockets (socket). The internal buffering constraints, and the network delay (mentioned in the red section above), affect read and write advance returns.
In non-network cases, read, and write basically do not encounter a non-EOF (short count) condition for direct reader files.
Advanced I/O
Non-buffered version (not without kernel buffering, two-level buffering without kernel buffering)
These functions transfer data directly between the memory and the file, with no application-level buffering. They are particularly useful for reading and writing binary data to and from the Web.
Readn
ssize_t readn (int fd,void *usrbuf,size_t n) { size_t nleft = n; ssize_t nread; char *BUFP = usrbuf; while (Nleft > 0) { if (nread = Read (fd,bufp,nleft)) < 0) { if (errno = = eintr) {/*interrupted by sig handler ret urn*/ nread = 0; } else{ return-1;/*error*/ } }else if (nread = = 0) {break ; /*eof*/ }else{/*read content*/ nleft-= nread; BUFP + = nread; } } return (n-nleft);}
writen
ssize_t rio_writen (int fd,void *usrbuf,size_t n) { size_t nleft = n; ssize_t Nwritten; char *BUFP = usrbuf; while (Nwritten = Write (Fd,bufp,nleft) <= 0) { if (errno = = eintr) { nwritten = 0; } else{ return-1; } Nleft-= Nwritten; BUFP + = Nwritten; } return n;}
As a tool function, concrete practice is temporarily not done, anyway, will often use later.
Note: The return value of the writen is actually fixed, each time n. But read is not fixed.
Reason: A simple understanding of remote Write---> remote computer (kernel buffering)----------(Network transport)-----------> local computer (kernel buffering)--------->read
As you can see, read is reading the contents of the far end, so it is not sure how much to read. But write is written locally, and the application knows how much data to write, and even if it is not finished at one time, it can be written over and over again by calling out the data in mind.
With buffered version (above the kernel buffer)
Such functions allow efficient reading of text lines and binary data from binary text, which are cached in the application-level cache, similar to buffers provided by standard I/O functions like printf.
Buffer structure (in fact, some information plus a large array)
#define RIO_BUFSIZE 8192typedef struct{ int rio_fd/*to operate the file descriptor*/ int rio_cnt;/*unread bytes In internal buf*/ char *rio_bufptr;/*next unread byte int internal buf*/ char rio_buf[rio_bufsize];/*internal bu f*/}rio_t;
initializes the buffer (in fact, the buffer and network descriptor FD are linked together)
Rio_init
Not open a file descriptor will be called once Rio_init
void Rio_readinitb (rio_t *rp,int fd) { rp->rio_fd = FD; rp->rio_cnt = 0; Rp->rio_bufptr = Rp->rio_buf;}
Rio_read (with buffered versions of Read, and Unix read ( not encapsulated ) with identical effects)
Static ssize_t Rio_read (rio_t *rp,char *usrbuf,size_t n) { int cnt; while (rp->rio_cnt <= 0) {/*read The file content if BUF is empty*/ rp->rio_cnt = Read (RP->RIO_FD, Rp->ri O_buf,sizeof (RP->RIO_BUF)); if (rp->rio_cnt < 0) { if (errno! = eintr) { return-1; } } else if (rp->rio_cnt = = 0) {/*eof*/ return 0; } else {/*reset buf ptr*/ rp->rio_bufptr = rp->rio_buf; } } /*when N < rp->rio_cnt, need copy some times */ CNT = n; if (rp->rio_cnt < n) {/*one time copy end*/ cnt = rp->rio_cnt; } memcpy (usrbuf,rp->rio_bufptr,cnt); Rp->rio_bufptr + = cnt; RP->RIO_CNT-= CNT; return CNT;}
Rio_readlineb
Each time the first line, up to read maxlen-1, the last word to the null character, more than maxlen-1 words will be truncated, and end with a null character
ssize_t Rio_readlineb (rio_t *rp, void *usrbuf,size_t maxlen) { int n,rc; char C,*BUFP = usrbuf; for (n = 1; n < maxlen; n++) { if (rc = Rio_read (rp,&c,1) = = 1) { *bufp++ = C; if (c = = ' \ n ') {break ; } } else if (rc = = 0) { if (n = = 1) {/*eof No data read*/ return 0; } Else{/*eof some data read*/break ; } } else{/*error*/ return-1; } } *BUFP = 0;/*string End sign: ' + ' */ return n;
RIO_READNB (with buffered version of READN)
ssize_t rio_readnb (rio_t *rp,void *usrbuf,size_t N) { size_t nleft = n; ssize_t nread; char *BUFP = usrbuf; while (Nleft > 0) { if (nread = Rio_read (RP,BUFP, Nleft)) < 0) { if (errno = = eintr) {/*interrupted by sig handle R return*/ nread =0; } Else{/*errno set by Read () */ return-1; } } else if (nread = = 0) {/*eof*/break ; } Nleft-= nread; BUFP + = nread; } return (n-nleft);/*return >=0*/}
For the light spray, most of the night is not easy ...
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Linux Network Programming (attached 1)--Package Read, write