I. function function
#include <sys/uio.h> ssize_t readv(int fd, const struct iovec *iov, int iovcnt); ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
- Concept: readv and writev functions are used to read and write multiple discontinuous caches in a function call. Sometimes these two functions are also called scatter read and gather write
Function structure
- Parameter 1: descriptor flag
- Parameter 2: pointer to the iovec structure array
- Parameter 3: iovcnt specifies the number of elements in the IOV array, and its maximum value is limited by IOV_MAX (recall figure 2-11)
struct iovec Structure:
struct iovec { void *iov_base; /* starting address of buffer */ size_t iov_len; /* size of buffer */ };
- The order in which the writev function gathers output data from the buffer is: iov[0], iov[1] to iov[iovcnt-1]
- writev returns: the total number of bytes output, usually equal to the sum of all buffer lengths. Error return - 1
- readv spreads the read data into the cache in the same order as above readv always fills one cache first and then the next
- readv returns: the total number of bytes read. If the end of the file is encountered and no data is readable, 0 is returned. Error returned 1
III. efficiency of writev
We need to complete one function: write the contents of two buffers to a file in succession. There are three methods to achieve this function:
- Here are the functions to complete the function:The second buffer is a parameter passed by the caller. The first buffer is created by ourselves. It contains the length of the second buffer and the file offset of other information about the file.
static void _db_writeidx(DB *db, const char *key,off_t offset, int whence, off_t ptrval) { struct iovec iov[2]; char asciiptrlen[PTR_SZ + IDXLEN_SZ + 1]; int len; if ((db->ptrval = ptrval) < 0 || ptrval > PTR_MAX) err_quit("_db_writeidx: invalid ptr: %d", ptrval); sprintf(db->idxbuf, "%s%c%lld%c%ld\n", key, SEP,(long long)db->datoff, SEP, (long)db->datlen); len = strlen(db->idxbuf); if (len < IDXLEN_MIN || len > IDXLEN_MAX) err_dump("_db_writeidx: invalid length"); sprintf(asciiptrlen, "%*lld%*d", PTR_SZ, (long long)ptrval,IDXLEN_SZ, len); /* * If we're appending, we have to lock before doing the lseek * and write to make the two an atomic operation. If we're * overwriting an existing record, we don't have to lock. */ if (whence == SEEK_END) /* we're appending */ if (writew_lock(db->idxfd, ((db->nhash+1)*PTR_SZ)+1,SEEK_SET, 0) < 0) err_dump("_db_writeidx: writew_lock error"); /* * Position the index file and record the offset. */ if ((db->idxoff = lseek(db->idxfd, offset, whence)) == -1) err_dump("_db_writeidx: lseek error"); iov[0].iov_base = asciiptrlen; iov[0].iov_len = PTR_SZ + IDXLEN_SZ; iov[1].iov_base = db->idxbuf; iov[1].iov_len = len; if(writev(db->idxfd, &iov[0], 2) != PTR_SZ + IDXLEN_SZ + len) err_dump("_db_writeidx: writev error of index record"); if (whence == SEEK_END) if (un_lock(db->idxfd, ((db->nhash+1)*PTR_SZ)+1,SEEK_SET, 0) < 0) err_dump("_db_writeidx: un_lock error"); }
-
Results of three methods:
- Other precautions