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;
}