这几天,写服务器代码的过程当中,顺便把以前看apue的代码拿来记录下,以便以后找起来方便一些。readv和writev函数用于在一次函数操作中读、写多个非连续的缓冲区。这在写http一类的协议头的时候感觉很方便。例如用writev把多个协议头用着一个函数写给fd。下面是我的一个例子:#include#include#include#include#include#includeconst char str1[] = "hello\n";const char str2[] = "world,fuck!!\n";void main(void){int ret, len;char temp;char readbuf1[30];char readbuf2[30];struct iovec iov[2];iov[0].iov_base = str1;iov[0].iov_len = strlen(str1);iov[1].iov_base = str2;iov[1].iov_len = strlen(str2);len = iov[1].iov_len + iov[0].iov_len;int fd = open("testfile", O_RDWR | O_CREAT);if(fd{printf("open file failed\n");exit(1);}ret = writev(fd, &iov[0], 2);if(ret != len){printf("writev failed\n");close(fd);exit(1);}fd = open("testfile", O_RDONLY);if(fd{printf("open file failed\n");exit(1);}printf("test writev:\n");while(read(fd, &temp, 1) != 0)write(STDOUT_FILENO, &temp, 1);close(fd);printf("sleep for a few seconds\n");sleep(3);printf("test readv:\n");iov[0].iov_base = readbuf1; iov[0].iov_len = 30;iov[1].iov_base = readbuf2;iov[1].iov_len = 30;fd = open("testfile", O_RDONLY);if(fd{printf("open file failed\n");exit(1);}memset(readbuf1, 0, 30);memset(readbuf2, 0, 30);ret = readv(fd, &iov[0], 2);if(ret != len){printf("readv failed\n");close(fd);exit(1);}close(fd);printf("readbuf1: %s\n", readbuf1);printf("readbuf2: %s\n", readbuf2);exit(0);}上面是执行结果,这里注意从文件读出来的时候,是把第一个缓冲区填满后,才往第二个缓冲区写入。上面的执行结果可以看出,第一个没有写满,所以第二个内容是空的,另外缓冲区的大小在读的时候是根据iov[0]和iov[1]的iov_len字段来确定的。即使缓冲区很大,但是读的时候读多少由len确定。如将上面代码中的iov[0].iov_base = readbuf1; iov[0].iov_len = 30;中的30改成3,则执行情况如下:另外,apue1,389页,有下面描述:对于少量数据,使用writev的固定开销大于得益,随着需要复制数据的增加,程序中复制数据的开销也会增多,此时,writev这种替代方法就会有更大的吸引力。