当前位置: 首页 > news >正文

辽阳建设银行网站锁定网站导航栏

辽阳建设银行网站,锁定网站导航栏,网站建设服务器介绍图片,大型网站开发流程和步骤目录 一、实验现象二、初步认知缓冲区2.1 缓冲区的刷新策略2.2 缓冲区在哪里 三、缓冲区模拟实现四、再次全面理解缓冲区4.1 用户强制刷新缓冲区(fflush/fsync) 一、实验现象 我们先来看一个现象#xff1a; 在显示器中打印内容时#xff0c;fprintf先打印出来#xff0c;w… 目录 一、实验现象二、初步认知缓冲区2.1 缓冲区的刷新策略2.2 缓冲区在哪里 三、缓冲区模拟实现四、再次全面理解缓冲区4.1 用户强制刷新缓冲区(fflush/fsync) 一、实验现象 我们先来看一个现象 在显示器中打印内容时fprintf先打印出来write后打印出来这也是非常正常的现象因为fprintf代码在write之前嘛但是我们可以看到将1号下标重定向到log.txt此时write函数的内容先进行打印了这是什么原因 下面我们再来看一个奇怪的现象 上述实验中fprintf打印了两次这必定与fork函数有关而向显示器中打印内容与向文件中打印内容fprintf与write打印的顺序不一致fprintf函数是C库函数而write是系统调用函数我们初步猜想这必定与两者的内部实现有关系事实上这是由于两者的刷新策略不同而导致的而刷新策略又跟缓冲区有联系所以下面我们将一步引出缓冲区的概念对它进行着重分析。 二、初步认知缓冲区 实际上我们的数据并不是立马就被显示出来的我们的C库以及操作系统都会提供一个缓冲区数据先会被保存在这个缓冲区当中然后结合一定的刷新策略数据才显示出来 缓冲区的本质其实就是充当一个内存暂存数据的地方 为什么要引入缓冲区这个概念有什么意义我们通过一个例子感性的理解一下 假设你的朋友小库要生日了你想在他生日当天送一个礼物给他但是小库跟你不在同一个地方小库在美国而你在湖南。那么你将礼物交给他有两种方式一种方式是你自己订机票飞往小库的地方将礼物交给他另外一种方式是去快递点将礼物交给快递公司让它送给小库。那么你会选择哪种方式呢我想大部分都应该会选择用快递的方式将礼物送给他吧。那么其实快递公司就充当了缓冲区的角色快递公司会通过它的方式将礼物交给小库不需要你亲自送给小库这有什么好处呢它节省了你的时间你将礼物交给了快递公司那么你就可以继续去干你自己的事情剩下的事交给快递公司就可以了。那么在进程中假设我们调用了fprintf函数它就会转而将数据拷贝到缓冲区中让缓冲区帮你实现功能然后立马返回进程继续执行剩下的任务 所以为什么要有缓冲区呢有什么意义 提高了IO效率节省了调用者的时间 2.1 缓冲区的刷新策略 引出缓冲区的概念之后那么在缓冲区的数据是如何被使用的呢这就需要采取一定的刷新策略了。 缓冲区的刷新策略 无缓冲数据直接传送到目标设备不经过缓冲区。这种方式的特点是数据传输速度快但效率低下容易产生垃圾数据。行缓冲数据存储在缓冲区中当填满一行或遇到换行符时就会将整行数据一起刷新到目标设备中。行缓冲的特点是占用空间小效率较高但无法立即显示输出(当未填满一行或未遇到换行符时会一直存留在缓冲区中无法立即输出到目标设备中)。显示器采用的刷新策略。全缓冲数据存储在缓冲区中缓冲区填满后将整个缓冲区一次性刷新到目标设备中。全缓冲的特点是效率高但需要占用大量的存储空间。普通文件采用的刷新策略。特殊情况 1、进程退出时需要刷新缓冲区在进程退出时操作系统会自动关闭该进程的所有文件并刷新缓冲区确保数据正确保存。 2、关闭文件(close)时需要刷新缓冲区在关闭文件时操作系统会自动刷新该文件的缓冲区确保数据正确保存。 3、用户强制刷新缓冲区有些操作系统提供了命令或函数可以手动刷新缓冲区例如Unix/Linux中的sync命令或fsync函数Windows中的FlushFileBuffers函数等。 上述我说的是基于用户层的缓冲区刷新策略实际上操作系统的缓冲区刷新策略更为复杂采用定时刷新、事件触发刷新、混合策略刷新等等但是大致的思想肯定是一样的下面我们重点讲解用户层缓冲区的刷新策略就可以了。 行缓冲是现阶段语言层面我们用的最多的一种刷新策略通过找到\n将缓冲区中的数据刷新出来这也就是我们通常在printf中带\n数据能立马将缓冲区中的数据刷新出来最终在显示器上看到的原因。有了这个概念我们就能对printf带\n有了更进一步的了解了实际上\n不仅仅是为了调整格式而且能使我们保存在缓冲区的数据刷新出来最终显示在显示器上 为什么显示器通常采用的是行缓冲 这是为了用户有更好的体验我们通常希望看到一次一次的现象而不是把缓冲区填满之后再一次性的刷新缓冲区最终在显示器上只看到一次现象。 对于缓冲区的设计者来说为了极大的提高IO效率通常采用的是类似全缓冲的刷新策略因为需要刷新的数据量非常大数据将缓冲区填满之后再进行刷新。这样为什么能提高IO效率 对于显示器文件来说我们使用的是行缓冲找到\n就刷新缓冲区刷新缓冲区的本质就是进行写入最终将数据写入到显示器文件中而数据写入外设必定要遵循冯诺依曼体系换句话说每刷新一次就进行一次IO而对于全缓冲来说我们将缓冲区填满之后才刷新一次不发生刷新的本质不进行写入就是不进行IO不进行调用系统调用所以fwrite函数调用会非常快数据会暂时保存在缓冲区中可以在缓冲区中积压多份数据最后再统一进行刷新写入换句话说就是就是一次IO可以IO更多的数据。IO是需要花费时间的我们通过全缓冲减少了IO的次数不就是节省了时间提高了效率吗 注进行IO必定需要访问外设调用库函数将数据拷贝到缓冲区都不IO叫拷贝数据 2.2 缓冲区在哪里 在之前的实验现象中我们看到1号下标重定向到log.txt文件后调用write与fprintf此时在普通文件中打印内容采用的是全缓冲策略那么fprintf比write先进行调用但是write比fprintf先进行打印write是系统调用接口而fprintf是C库函数。由此说明缓冲区一定不在内核层所以此时的缓冲区一定是在用户层它是C库提供的更具体的来说它在FILE结构体中 接下来我们回答一下之前出现的奇怪现象 用户先调用fprintf函数实际fprintf会调用fwrite函数将数据先写入缓冲区中fwrite在这里就充当一个拷贝函数。发生重定向之后我们采用的全缓冲刷新策略此时hello fprintf暂存在缓冲区中而write它是系统调用接口它的数据根本不放在用户级缓冲区中而是放在内核层缓冲区中然后结合操作系统的刷新策略将数据写入到显示器文件所以它会较fprintf先打印出来。在最后我们使用fork创建子进程在进程退出前要刷新缓冲区此时谁先刷新缓冲区就要发生写时拷贝所以最终我们可以看到两份fprintf打印的内容 关于缓冲区的理解到现在还是不够的我们后续讲完缓冲区的模拟实现之后还会再次进行谈论到时候我们就能彻底明白缓冲区以及它的刷新策略了。 三、缓冲区模拟实现 下面是我们进行缓冲区的简单模拟实现代码 mystdio.h #pragma once#include stdio.h#define NUM 1024 #define BUFF_NONE 0x1 #define BUFF_LINE 0x2 #define BUFF_ALL 0x4typedef struct _MY_FILE {int fd; // 文件描述符int flags; // flush method, 刷新策略char outputbuffer[NUM]; // 缓冲区int current; // 当前指向缓冲区字符的位置 } MY_FILE;MY_FILE *my_fopen(const char *path, const char *mode); // fopen函数 size_t my_fwrite(const void *ptr, size_t size, size_t nmemb,MY_FILE *stream); // fwrite函数 int my_fclose(MY_FILE *fp); // fclose函数 int my_fflush(MY_FILE *fp); // fflush函数mystdio.c #include mystdio.h #include string.h #include sys/types.h #include sys/stat.h #include fcntl.h #include malloc.h #include unistd.h #include assert.hMY_FILE *my_fopen(const char *path, const char *mode) {//1. 识别标志位int flag 0;if(strcmp(mode, r) 0) flag | O_RDONLY;else if(strcmp(mode, w) 0) flag | (O_CREAT | O_WRONLY | O_TRUNC);else if(strcmp(mode, a) 0) flag | (O_CREAT | O_WRONLY | O_APPEND);else {//other operator...//r, w, a}//2. 尝试打开文件mode_t m 0666; // 文件权限int fd 0;// 如果文件需要不存在需要创建此时我们就需要设置文件权限if(flag O_CREAT) fd open(path, flag, m);else fd open(path, flag);if(fd 0) return NULL;//3. 给用户返回MY_FILE对象,需要先进行构建MY_FILE *mf (MY_FILE*)malloc(sizeof(MY_FILE));// 如果创建结构体失败就关闭文件if(mf NULL) {close(fd);return NULL;}//4. 初始化MY_FILE对象mf-fd fd;mf-flags 0;mf-flags | BUFF_LINE; // 默认为行缓冲刷新策略memset(mf-outputbuffer, \0,sizeof(mf-outputbuffer)); // 初始化缓冲区//mf-outputbuffer[0] 0; //初始化缓冲区mf-current 0; // 当前指向缓冲区字符的位置//5. 返回打开的文件return mf; }void my_fflush(MY_FILE *fp) {assert(fp);//刷新的本质是将用户缓冲区中的数据通过系统调用接口冲刷给OSwrite(fp-fd, fp-outputbuffer, fp-current);fp-current 0; // 刷新缓冲区之后将指向缓冲区字符的置为0 -- 起始位置fsync(fp-fd); // 用户强制将缓冲区的数据刷新到外设中 }size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, MY_FILE *stream) {// 1. 缓冲区如果已经满了就先刷新缓冲区if(stream-current NUM) my_fflush(stream);// 2. 根据缓冲区剩余情况进行数据拷贝即可size_t user_size size * nmemb; // 用户需要传入的字节大小size_t my_size NUM - stream-current; // 缓冲区剩余字节大小size_t writen 0;// 如果缓冲区剩余字节大小大于等于用户传入的字节大小此时将数据拷贝至current之后反之则最多拷贝my_size字节到current后if(my_size user_size){memcpy(stream-outputbufferstream-current, ptr, user_size);//3. 更新当前位置stream-current user_size;writen user_size;}else{memcpy(stream-outputbufferstream-current, ptr, my_size);stream-current my_size;writen my_size;}// 4. 开始计划刷新// 全缓冲if(stream-flags BUFF_ALL){if(stream-current NUM) my_fflush(stream);}// 行缓冲else if(stream-flags BUFF_LINE){if(stream-outputbuffer[stream-current-1] \n) my_fflush(stream);}// 无缓冲else{//...}return writen; }void my_fclose(MY_FILE *fp) {assert(fp);//1. 冲刷缓冲区if(fp-current 0) my_fflush(fp);//2. 关闭文件close(fp-fd);//3. 释放堆空间free(fp);fp NULL; } main.c // main.c读者可以自行去进行测试 #include mystdio.h #include string.h #include unistd.h#define MYFILE log.txtint main() {MY_FILE *fp my_fopen(MYFILE, w);if(fp NULL) return 1;const char *str hello my fwrite;int cnt 500;//操作文件while(cnt){char buffer[1024];snprintf(buffer, sizeof(buffer), %s:%d, str, cnt--);//snprintf(buffer, sizeof(buffer), %s:%d\n, str, cnt--);size_t size my_fwrite(buffer, strlen(buffer), 1, fp);sleep(1);printf(当前成功写入: %lu个字节\n, size);//my_fflush(fp);}my_fclose(fp);return 0; }我们先来看看行缓冲区的现象 当snprintf带\n时我们发现数据一次一次的回显在log.txt文件中 当snprintf不带\n时此时默认还是行缓冲刷新当行缓冲区未满一行或找不到\n时此时数据在缓冲区中一直积压直到此时进程结束该缓冲区刷新此时一下在文件中一次就看到了缓冲区的所有数据 如果我们一次一次的回显到文件中我们可以通过我们自己实现的my_fflush强制刷新缓冲区 四、再次全面理解缓冲区 有了上述缓冲区的模拟实现我们对缓冲区的刷新策略有了更近一步的了解。 接下来我们谈谈用户进行IO的整个流程 这里以用户使用C语言调用printf打印数据到显示器上为例在用户层printf会先调用fwrite函数将数据拷贝到用户层缓冲区当中然后结合一定的刷新策略-通过系统调用(write)将数据拷贝到内核层缓冲区当中随后操作系统也同样的采取一定的刷新策略将数据最终写入磁盘所以最终我们就能在显示器文件中看到我们打印的数据了。 我们平时在语言级别中提到的缓冲区其实都是用户层缓冲区因为内核级缓冲区我们也见不到。 4.1 用户强制刷新缓冲区(fflush/fsync) 下面我想重点讲讲fflush库函数与fsync系统调用接口 fflush()函数 fflush()函数是用来刷新标准I/O库的缓冲区的其中包括用户层的缓冲区。当我们使用C语言中的输出函数(如printf())向文件中写入数据时这些数据首先被写入用户层的缓冲区中而不是直接写入磁盘中。只有在缓冲区已满、文件关闭或调用fflush()函数时才会将缓冲区的数据刷新到内核缓冲区中。那么如果此时我的刷新策略不符合第一二点此时就使用fflush()函数将数据强制刷新到内核缓冲区中。刷新缓冲区的本质是什么将用户缓冲区的数据通过系统调用(write)冲刷给操作系统那么实际上fflush函数强制刷新缓冲区在底层就是通过调用系统调用(write)来完成这项工作的 结论fflush()函数并不会直接将数据写入磁盘而是将数据写入内核缓冲区中由操作系统决定何时将数据写入磁盘。 fsync函数 fsync()函数会强制将一个文件的所有缓冲区数据和元数据如文件大小、修改时间等都写入磁盘中包括文件的用户层缓冲区和内核缓冲区。当fsync()函数返回时表示数据已经写入磁盘并且已经被持久化保存。这个函数在需要确保数据被持久化保存的场景中非常有用比如在操作系统崩溃或断电时而内存具有断点易失的性质一旦断电文件中所有的数据就丢失了。但是由于磁盘I/O的性能非常低所以fsync()函数的执行速度也较慢尤其是在写入大量数据时。因此如果需要频繁调用fsync()函数来写入小量的数据可能会对性能造成一定的影响。一个很常见的例子我们在CSDN写博客时我们边写它会边自动保存实际它就是调用了fsync函数使我们的数据被持久化保存防止我们突然断网断电导致数据丢失的问题而且我们也知道有时候这种自动保存的方式是有点卡顿的这是很常见的问题 值得注意的是对于某些文件系统如ext3、ext4等即使使用fsync()函数操作系统仍然可能会将数据先写入到内存中然后再在后台将数据写入磁盘中。这种行为被称为延迟写delayed write或异步写asynchronous write可以提高磁盘I/O的性能。因此在使用fsync()函数时不能保证数据一定已经写入磁盘中只能保证已经被提交到操作系统并由操作系统尽快写入磁盘。 结论fsync()函数用于确保数据被持久化保存。 本篇文章的内容就讲到这里了关于本文如果有任何疑问或者错处欢迎大家评论区相互交流orz~
http://www.dnsts.com.cn/news/77903.html

相关文章:

  • 长沙本土网站建设公司网站开发 设计制作合同
  • 网站备案上传照片几寸色see琪琪电影院
  • 微信微网站模版中小企业网站建设渠道
  • 海口小学网站建设视频网站如何做
  • 经营阅读网站需要怎么做wordpress添加视频解析
  • 网站建设方案书1500域名备案要钱吗
  • 企业官方网站如何做蓝v认证文字做图网站
  • 以做网站为毕设购物网站图片素材
  • 做动漫的网站wordpress 用户权限管理
  • wordpress导航站源码东道设计招聘要求
  • 假发网站是怎么做的有创意的网络公司名称
  • 绿色配色的企业网站android开发是做什么的
  • 汉中住房和城乡建设部网站河南建设协会官网
  • 欧洲cn2 vpsseo关键词推广
  • 快速建站公司电话wordpress接收表单
  • 如何关联网站与网站手机网站建设公司电话咨询
  • 公司建立网站的好处wordpress中文附件
  • 龙江做网站计算机外包公司
  • 网站建设代码怎么导入图片网页设计欣赏和解析
  • 公司网站打不开不知道谁做的酒店网站建设方案策划
  • 外包网页制作页面多少钱一张网站优化升级
  • 空间租用网站模板网站报价书
  • 做汽配网站需要多少钱电商运营具体是做什么的
  • 企业站网页制作实训步骤中国域名网站排名
  • 包装设计网站免费法华寺网站建设
  • 网站制作怎么做图标二手交易网站建设内容策划
  • 网站语言选择常州网站定制
  • 成都做网站建设公司网络营销方式有哪些?举例说明
  • 嘉兴网站制作报价怎么做坑人网站
  • wordpress多站点 用户网站架构设计师有哪些学校可以报考