大并发服务器必备技术:writev

前面我们说过,对于静态文件的传输,用sendfile可以减少系统调用,现在我们看看动态的数据应 该如何处理。

首先,如果数据足够小(小于1024)且只有唯一的一个buffer,我们直接用 send/write 就可以了。

通常的情况下,程序可能会在多个地方产生不同的buffer,如 nginx, 第一个phase里都可能会产生buffer,放进一个chain里,

如果对每个buffer调用一次send,系 统调用的个数将直接等于buffer的个数,对于多buffer的情况会很糟。

可能大家会想到重新分 配一个大的buffer, 再把数据全部填充进去,这样其实只用了一次系统调用了。

又或者在一开 始就预先分配一块足够大的内存。

这两种情况是能满足要求,不过都不足取,前一种会浪费内 存,后一种方法对phase的独立性有影响。

linux 有一个writev可以支持这种情况,先看下函数 声明:

ssize_t writev (int fd, __const struct iovec * iov, int count)

相关 的结构:

struct iovec {
char *iov_base;               /*缓冲区起始地址*/
size_t iov_len;                 /*缓冲区长度*/
};

函数声明很明显的告诉我们可以同时发送多个buffer。

不妨看一下nginx的用法:

ngx_chain_t   *cl;
struct iovec  *iov, headers[NGX_HEADERS];
for (cl = in; cl && send < limit; cl = cl->next) {
<span style="white-space:pre">      </span>iov = ngx_array_push(&header);
                iov->iov_base = (void *) cl->buf->pos;
                iov->iov_len = (size_t) size;
}
writev(c->fd, header.elts, header.nelts);

一开始创建一下 struct iovec  数 组,将每个元素的 iov_base指向 单个要发送的buffer,iov_len 则是等于长度。

最后调用 writev一齐发送。

接着我们看一下函数posix定义:

ssize_t writev(int fd, const 

struct iovec *vecs, size_t count){
    ssize_t bytes = sys_writev(fd, vecs, count);  

    RETURN_AND_SET_ERRNO(bytes);
}

内核函数sys_writev:

ssize_t sys_writev(unsigned long fd, const struct 

iovec __user *vec, unsigned long vlen)
{
    struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;  

    file = fget_light(fd, &fput_needed);
    if (file) {
        ret = vfs_writev(file, vec, vlen, &file->f_pos);
        fput_light(file, fput_needed);
    }  

    return ret;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索file
, struct
, 函数
, buffer
一个
,以便于您获取更多的相关知识。

时间: 2016-04-04

大并发服务器必备技术:writev的相关文章

大并发服务器必备技术:sendfile

socket发送函数. int send( SOCKET s, const char FAR *buf, int len, int flags ); 如果内容是动态生成的,一般是把传输内容直接丢给buf中用send函数传输,没有优化的空 间. 文件传输则要先把内容read到buf中,因此至少两次内核调用,如果文件很大,可能会用一 个循环调用,如: while( size == PER_SIZE ) { size = read( fd, buf, PER_SIZE ); if( size >0 )

大并发服务器必备技术:connect 异步

前面我们谈的大多是服务端与客户端的技术,服务器开发其实有时还会涉及到跨服务器的访问,比 如腾讯的拍拍服务器需要知道登录的会员信息,就需要访问会员服务器. 跨务器访问会涉及到 很多的技术,比如访问权限控制,数据同步等,这里主要来学习一下传输层. 为了更容易理解 ,我们将访问端服务器称为客户端,被访问端服务器称为服务端. 客户端发起一个连接的过程 : socket_fd = socket( AF_INET,SOCK_STREAM,0 ); ret = connect( socket_fd, (soc

大并发服务器必备技术:http 缓存

前面所说技术订都是服务器端一个人在努力,有时候也需要客户端配合. 一个链接请求过程 大致可以分成几个阶段 如果客户端发送同样的 请求,且结果都一样,我们是不是可以缓冲一下呢?是不是可以减少几步呢? 的确可以,一般来 说以下几种方法: 1.我们先试着在服务端进行缓冲,我们试着将一个已经返回的长链接发送内 容不作释放,下次请求时直接返回刚才发送的内容,这个不适用于频繁访问,适用于一些特殊的情况, 特殊的请求. 2.对于静态的文件都有上次修改时间lastupdatetime,客户端第一次请求返回的 h

大并发服务器必备技术:tcp cork

如果把tcp当成服务端与客户端的管道,cork 就是给管道加个塞子. 为什么 要加个塞子呢 ? 先来举个例子: int times = 10; while( times--) { send( sock_fd, buf, 1, 0 ) } 这段program会发送数据10次,每次就发送1个字节,这样会不会什么问题呢? 记得 以前农忙的时候,田里的稻子收割完了,要打成稻谷,就放一个打稻机子,父亲在机子旁打稻,而我则 负责抱起稻子送给他.父亲打稻的速度很快,很小的时候我每次只抱一捆稻子,就会不停 地奔

大并发服务器内存转换的灵活运用,memcpy的思考

在很多的网络开发中,经常会碰到一些内存转换,如下面的场景: #define PACKAGE_PARSE_ERROR -1 #define PACKAGE_PARSE_OK 0 int parse_package( int* a, int* b, int* c, int* d, char* buf, int buf_len ) { if( !buf || buf_len < 16 ){ return PACKAGE_PARSE_ERROR; } memcpy( a, buf, 4 ); memcp

搭建一个后台服务器:服务端(异步,大并发)

上篇的阻塞模式下服务器的并发只有几K,而真正的server 像nginx, apache, yumeiz 轻轻松松处 理几万个并发完全不在话下,因此大并发的场合下是不能用阻塞的. 1W的并发是一个分隔点,如果单进程模型下能达到 的话,说明至少在服务器这块你已经很厉害了. 服务器开发就像一门气功,能不能搞出大并发,容错性处理得怎么样,就是你有没有内功,内功有 多深. 异步模式是专门为大并发而生,linux下一般用 epoll 来管理事件,下面就开始我们的异步大并发 服务器实战吧. 跟阻塞开发一样,

高并发服务器的设计之架构与瓶颈的设计

做架构设计,难免有时候被人问及系统的瓶颈在哪,那首先来了解下什么是瓶颈? 打个形象 的比方,人的嘴巴可以吞下一整个面包,但是却咽不下去,因为食管不给力,它比较细,所以嘴巴能吞 下的食物大小要受到食管的粗细限制. 城市内部每天会产生几十万件跨城快递,可是跨城的交 通不给力,只允许走小型卡车,一卡车一次就能装几千件,一天下来也不一定能投送的完. 人 在一定时间内能咽下多少食物,货运公司在一天运送多少货物,物理上叫做吞吐量,系统整体的吞吐量 等于最小区域的吞吐量. 下面这张图能够反映: 土黄色管子的流

Comet:基于 HTTP 长连接的“服务器推”技术

很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客户端不停地刷新.发送请求.本文首先介绍.比较了常用的"服务器推"方案,着重介绍了 Comet - 使用 HTTP 长连接.无须浏览器安装插件的两种"服务器推"方案:基于 AJAX 的长轮询方式;基于 iframe 及 htmlfile 的流方式.最后分析了开发 Comet 应用需要注意的一些问题,以及如何借助开源的 Comet 框架-pushlet 构建自己的"服务器推&

文字直播专题列表如何解决大并发问题

问题描述 文字直播专题列表如何解决大并发问题 今天想在CSDN与各位探讨一个弹窗大并发的问题.应用表现:图片.文字直播类新闻列表,编辑实时发布最新内容,前端页面最新的内容在上面,老的在下面 并发场景:因为是新闻类直播,遇到突发性事件(如马航失联.亚航失联),需要对重大新闻进行消息弹窗,推送的用户量级别是3000W左右. 问题:如何解决这种短事件内人大并发问题,平台架构方面如何搭建? 缓存机制可否优化?TIPS:服务器有22台,程序已经做了缓存加速. 抱歉,账号下没有金币了,希望各位技术大牛能一起