视频网站策划,秦皇岛市保障性住房官网,快云服务器怎么做网站,静态网页设计作品欣赏目录 为什么需要缓冲区自动增长的缓冲区buffer数据结构buffer类 写详细比较费时间#xff0c;就简单总结下。 总结自Linux 多线程服务端编程#xff1a;使用 muduo C 网络库
Muduo网络编程#xff1a; IO-multiplexnon-blocking
为什么需要缓冲区
Non-blocking IO 的核心… 目录 为什么需要缓冲区自动增长的缓冲区buffer数据结构buffer类 写详细比较费时间就简单总结下。 总结自Linux 多线程服务端编程使用 muduo C 网络库
Muduo网络编程 IO-multiplexnon-blocking
为什么需要缓冲区
Non-blocking IO 的核心思想是避免阻塞在 read() 或 write() 或其他 IO 系统调 用上所以应用层的缓冲是必须的每个 TCP socket 都要有 input buffer 和 output buffer。
自动增长的缓冲区
一方面希望减少系统调用所以缓冲区越大越好 另一方面希望减少内存占用如果缓冲区很大而连接很多将会占用大量内存空间。而大多数时候缓冲区的使用率又很低。
buffer数据结构 buffer类
Muduo Buffer的size()是自适应的一开始的初始值是1k。
抽取相关代码
class Buffer:public muduo::copyable{public:static const size_t kCheapPrepend 8;static const size_t kInitialSize 1024;explicit Buffer(size_t initialSize kInitialSize): buffer_(kCheapPrepend initialSize),readerIndex_(kCheapPrepend),writerIndex_(kCheapPrepend){...}...std::vectorchar buffer_;
}vector数组保证了可以扩展初始化了1k可用空间并在头部预留了1Byte。 具体做法是在栈上准备一个 65536 字节的 extrabuf然后利用 readv() 来读取数据。 iovec 有两块第一块指向muduo Buffer 中的 writable 字节另一块指向 栈上的 stackbuf。 这样如果读入的数据不多那么全部都读到Buffer 中去了如果长度超过 Buffer 的 writable 字节数就会读到栈上的 extrabuf 里然后程序再把extrabuf 里的数据 append 到 Buffer 中。 这么做利用了临时栈上空间避免开巨大 Buffer 造成的内存浪费也避免反复 调用 read() 的系统开销通常一次 readv()系统调用就能读完全部数据。 代码相关实现Buffer::readFd()
ssize_t Buffer::readFd(int fd, int* savedErrno)
{// saved an ioctl()/FIONREAD call to tell how much to readchar extrabuf[65536];struct iovec vec[2];const size_t writable writableBytes();vec[0].iov_base begin()writerIndex_;vec[0].iov_len writable;vec[1].iov_base extrabuf;vec[1].iov_len sizeof extrabuf;// when there is enough space in this buffer, dont read into extrabuf.// when extrabuf is used, we read 128k-1 bytes at most.const int iovcnt (writable sizeof extrabuf) ? 2 : 1;const ssize_t n sockets::readv(fd, vec, iovcnt);if (n 0){*savedErrno errno;}else if (implicit_castsize_t(n) writable){writerIndex_ n;}else{writerIndex_ buffer_.size();append(extrabuf, n - writable);}return n;
}首先写buffer写不下的写extrabuf然后把extrabuf的写入buffer具体函数是append。 void append(const char* /*restrict*/ data, size_t len){ensureWritableBytes(len);std::copy(data, datalen, beginWrite());hasWritten(len);}ensureWritableBytes检查buffer是否有空余空间可以被写入没有就vector.resize(len)扩展len。然后通过std::copy把extrabuf上的内存copy到buffer上。最后更新writerIndex_。