美文网首页
write每次最大能写多少字节的数据

write每次最大能写多少字节的数据

作者: Beast2 | 来源:发表于2017-01-15 13:04 被阅读0次

背景

最近碰到一个线上的bug,具体情况是进程将24G左右的内存buffer写到磁盘上,但是每次write都写不完24G,然后重试导致磁盘写满,服务不可用。

在修这个bug的时候,对于到底write最大能写多少字节的数据产生了浓厚的兴趣,写了一个测试程序基本上每次最多写到2G多一点。

在研究了一段内核代码后一切霍然开朗。

write限制

write函数在以下三种情况下可能写入的字节数小于指定的字节数:

  1. 在底层的物理介质上没有足够的空间
  2. RLIMIT_FSIZE的限制
  3. 写入被信号打断

从内核代码来看,count在大于MAX_RW_COUNT的情况下,会赋值为MAX_RW_COUNT

而MAX_RW_COUNT是一个宏,展开为:INT_MAX & PAGE_MASK

INT_MAX也是一个宏,展开为((int)(~0U>>1)),也就是无符号数0取反后右移一位转换成int类型,也就是2^31.

PAGE_MASK也是一个宏,展开为(~(PAGE_SIZE-1)),而PAGE_SIZE展开为(_AC(1,UL) << PAGE_SHIFT),PAGE_SHIFT的值为12,也就是每页的大小是212,也就是说1左移12位,PAGE_SIZE的值为212,然后PAGE_SIZE-1取反

最后MAX_RW_COUNT的值为INT_MAX & PAGE_MASK,也就是说MAX_RW_COUNT的值是int的最大值最后12位屏蔽掉,保持4K地址对齐

所以理论上讲,每次write可写的buff大小是231-212=2147479552,这也是与实际的测试结果相一致

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
    printf("%d %s",sig,secret);
}
void sigtermHandler(int sig) {
    printf("%d\n",sig);
}

void setupSignalHandlers(void) {
    struct sigaction act;

    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = sigtermHandler;
    sigaction(SIGTERM, &act, NULL);

    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
    act.sa_sigaction = sigsegvHandler;
    sigaction(SIGSEGV, &act, NULL);
    sigaction(SIGBUS, &act, NULL);
    sigaction(SIGFPE, &act, NULL);
    sigaction(SIGILL, &act, NULL);
    return;
}

int main(int argc,char** argv){
    signal(SIGHUP, SIG_IGN);
        signal(SIGPIPE, SIG_IGN);
        setupSignalHandlers();
    //extern int errno;
    struct rlimit limit;
    limit.rlim_cur = RLIM_INFINITY;
    limit.rlim_max = RLIM_INFINITY;
    if(setrlimit(RLIMIT_FSIZE,&limit)){
        printf("set limit failed\n");
    }
    long long buff_size = atoll(argv[1]);
    char *buff = malloc(buff_size*sizeof(char));
    int fd = open("io.dat", O_CREAT|O_WRONLY|O_TRUNC, 0644);
    int ret = 0;
    while(buff_size>0){
    ret = write(fd,buff,buff_size);
    printf("written %d bytes\n",ret);
    if(ret<0){
        printf("write error: %s\n",strerror(errno));
        return 0;
    }
    buff_size-=ret;
    if(buff_size==0) break;
    }
    printf("write %lld bytes\n",buff_size);
    return 0;
}

相关文章

  • write每次最大能写多少字节的数据

    背景 最近碰到一个线上的bug,具体情况是进程将24G左右的内存buffer写到磁盘上,但是每次write都写不完...

  • Lecture 11 Assignment (20190508)

    IP数据报首部固定部分长度为多少字节?首部最大长度为多少字节?整个IP数据总长度最大值为多少字节? IP数据报总长...

  • HttpServletResponse

    字节流可以写任何数据,字符流只能写字符数据 getOutputStream字节流,getWriter字符流 1、r...

  • IO

    分类 输入流、输出流 数据 --> (单/双)管道 --> 输入数据 -->程序 字节流、字符流 每次读写 以字节...

  • 局域网中一个 UDP 包可以装多少数据?

    问题 使用 UDP 协议在局域网中一次传输最多能传多少数据? 分析 ****以太网数据帧的最大长度为1500字节,...

  • 无标题文章

    能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写多少字能写...

  • Java IO

    分类图 字节流和字符流字节流:以字节为单位,每次次读入或读出是8位数据,可以读任何类型数据。所有带InputStr...

  • JAVA面试必备的知识宝典(三)

    数据类型相关 java中int char,long各占多少字节? |类型|位数|字节数| |-|-|-| |sho...

  • 数据库 之 MySQL数据类型和常用字段属性总结

    前言 好比C++中,定义int类型需要多少字节,定义double类型需要多少字节一样,MySQL对表每个列中的数据...

  • 数据库 之 MySQL命名、设计及使用规范

    前言 好比C++中,定义int类型需要多少字节,定义double类型需要多少字节一样,MySQL对表每个列中的数据...

网友评论

      本文标题:write每次最大能写多少字节的数据

      本文链接:https://www.haomeiwen.com/subject/nehdrttx.html