linux write一次性能写多大字节,Write每次最多能写多少字节的数据

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

背景

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

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

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

write限制

write函数在以下三种情况下可能写入的字节数小于指定的字节数:在底层的物理介质上没有足够的空间

RLIMIT_FSIZE的限制

写入被信号打断

从内核代码来看,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,也就是每页的大小是2^12,也就是说1左移12位,PAGE_SIZE的值为2^12,然后PAGE_SIZE-1取反

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

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

测试代码

#include

#include

#include

#include

#include

#include

#include

#include void sigsegvHandler(int sig, siginfo_t *info, void *secret) {

printf("%d %s",sig,secret);

}

void sigtermHandler(int sig) {

printf("%dn",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 failedn");

}

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 bytesn",ret);

if(ret<0){

printf("write error: %sn",strerror(errno));

return 0;

}

buff_size-=ret;

if(buff_size==0) break;

}

printf("write %lld bytesn",buff_size);

return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`channel.write(buffer)` 方法一次最多可以出 `buffer` 中的剩余数据大小,即 `buffer.remaining()` 字节。 `ByteBuffer` 类的 `remaining()` 方法返回当前位置与限制之间的元素数,即剩余可读或可字节数。在进行操作时,`remaining()` 方法表示还有多少字节可以入通道。 以下是使用 `channel.write(buffer)` 方法数据的示例: ```java import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class NIOExample { public static void main(String[] args) { try { // Open a file channel in write mode RandomAccessFile file = new RandomAccessFile("example.txt", "rw"); FileChannel channel = file.getChannel(); // Create a ByteBuffer for writing ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put("Hello, World!".getBytes()); buffer.flip(); // Switch to reading mode // Write data from the buffer to the channel int bytesWritten = channel.write(buffer); System.out.println("Bytes written: " + bytesWritten); // Close the channel channel.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上述示例中,我们创建了一个 `ByteBuffer` 并将字符串 "Hello, World!" 入缓冲区。然后,我们使用 `channel.write(buffer)` 方法将缓冲区中的数据入文件通道。`bytesWritten` 变量将包含成功入通道的字节数。 请注意,在实际应用程序中,您可能需要循环调用 `channel.write(buffer)` 直到缓冲区中的所有数据都被入通道为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值