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

静态网站生成器怎样做厦门网络推广

静态网站生成器怎样做,厦门网络推广,有ecs怎么做网站,四川营销型网站建设14.7 实现文件写入 这是一个网站有所有小节的代码实现,同时也包含了Bochs等文件 本节要实现的 sys_write 是系统调用 write 的内核实现,咱们之前的 write 是个简易版,它是为了临时完成输出打印的功能,不支持文件描述符。如今要让…

14.7 实现文件写入

这是一个网站有所有小节的代码实现,同时也包含了Bochs等文件
本节要实现的 sys_write 是系统调用 write 的内核实现,咱们之前的 write 是个简易版,它是为了临时完成输出打印的功能,不支持文件描述符。如今要让 write 支持文件描述符的话,还要修改下周边与此系统调用相关的内容。

14.7.1 实现file_write
/*把buf中的count个字节写入file,成功则返回写入的字节数,失败则返回-1*/
int32_t file_write(struct file* file, const void* buf, uint32_t count){if((file->fd_inode->i_size +count)>(BLOCK_SIZE * 140)){ //文件目前最大只支持512*140=71680字节printk("exceed max file_size 71680 bytes,write file failed\n");return -1;}uint8_t* io_buf = sys_malloc(512);if(io_buf==NULL){printk("file_write:sys_malloc for io_buf failed\n");return -1;}uint32_t* all_blocks = (uint32_t*)sys_malloc(BLOCK_SIZE+48);    //用来记录文件所有的块地址,一个地址4字节,一共有140个块所以要560字节内存if(all_blocks == NULL){printk("file_write: sys_malloc for all_blocks failed\n");return -1;}const uint8_t* src = buf;   //用src指向buf中待写入的数据uint32_t bytes_written = 0;     //用来记录已写入数据大小uint32_t size_left = count;     //用来记录未写入数据大小int32_t block_lba = -1; //用来记录块地址uint32_t block_bitmap_idx = 0;  //用来记录block对应于block_bitmap中的索引,作为参数传递给bitmap_syncuint32_t sec_idx;   //用来索引扇区uint32_t sec_lba;   //扇区地址uint32_t sec_off_bytes; //扇区内字节偏移量uint32_t sec_left_bytes;    //扇区内剩余字节量uint32_t chunk_size;    //每次写入硬盘的数据块大小int32_t indirect_block_table;   //用来获取一级间接表地址uint32_t block_idx; //块索引//判断文件是否是第一次写,如果是,先为其分配一个块if(file->fd_inode->i_sectors[0]==0){block_lba = block_bitmap_alloc(cur_part);if(block_lba == -1){printk("file_write:block_bitmap_alloc failed\n");return -1;}file->fd_inode->i_sectors[0]=block_lba;/*每分配一个块就将位图同步到磁盘*/block_bitmap_idx = block_lba-cur_part->sb->block_bitmap_lba;ASSERT(block_bitmap_idx!=0);bitmap_sync(cur_part,block_bitmap_idx,BLOCK_BITMAP);}/*写入count字节前,改文件已经占用的块数*/uint32_t file_has_used_blocks = file->fd_inode->i_size / BLOCK_SIZE + 1;/*存储count字节后该文件将占用的块数*/uint32_t file_will_use_blocks = (file->fd_inode->i_size + count) / BLOCK_SIZE + 1;ASSERT(file_will_use_blocks <= 140);/*通过此增量判断是否要分配扇区,如果增量为0,表示原扇区够用*/uint32_t add_blocks = file_will_use_blocks - file_has_used_blocks;/*将写文件所用到的块地址收集到all_blocks,系统中快大小等于扇区大小,后面都统一在all_blocks中获取写入扇区地址*/if(add_blocks==0){/*在同一扇区内写入数据,不涉及到分配新扇区*/if(file_will_use_blocks<=12){//文件数据将在12块之内block_idx = file_has_used_blocks - 1;   //指向最后一个已有数据扇区all_blocks[block_idx] = file->fd_inode->i_sectors[block_idx];}else{/*未写入新数据之前已经占用了间接块,需要将间接块地址读取出来*/ASSERT(file->fd_inode->i_sectors[12]!=0);indirect_block_table = file->fd_inode->i_sectors[12];ide_read(cur_part->my_disk,indirect_block_table,all_blocks+12,1);}}else{/*若是有增量,变涉及到分配新扇区及是否分配一级间接块表,下面要分三种情况处理*//*第一种情况:12个块直接够用*/if(file_will_use_blocks <= 12){/*先将剩余空间的可继续用的扇区地址写入all_blocks*/block_idx = file_has_used_blocks - 1;ASSERT(file->fd_inode->i_sectors[block_idx]!=0);all_blocks[block_idx] = file->fd_inode->i_sectors[block_idx];/*再将未来要用的扇区分配好后写入all_blocks*/block_idx = file_has_used_blocks;   //指向第一个要分配的扇区while(block_idx<file_will_use_blocks){block_lba = block_bitmap_alloc(cur_part);if(block_lba==-1){printk("file_write:block_bitmap_alloc for situation 1 failed\n");return -1;}/*写文件时,不应该存在块未使用但已经分配扇区的情况,当文件删除时,就会把块地址清0*/ASSERT(file->fd_inode->i_sectors[block_idx]==0);    //确保尚未分配扇区地址file->fd_inode->i_sectors[block_idx] = all_blocks[block_idx] = block_lba;/*每分配一个块就将位图同步到磁盘*/block_bitmap_idx = block_lba-cur_part->sb->block_bitmap_lba;ASSERT(block_bitmap_idx!=0);bitmap_sync(cur_part,block_bitmap_idx,BLOCK_BITMAP);block_idx++;    //分配下一个扇区}}else if(file_has_used_blocks <= 12 && file_will_use_blocks > 12){/*第二种情况:旧数据在12个直接块中,数据将使用间接块*//*先将剩余空间的可继续用的扇区地址写入all_blocks*/block_idx = file_has_used_blocks - 1;   //指向旧数据所在的最后一个扇区ASSERT(file->fd_inode->i_sectors[block_idx]!=0);all_blocks[block_idx] = file->fd_inode->i_sectors[block_idx];/*创建一级间接块表*/block_lba = block_bitmap_alloc(cur_part);if(block_lba==-1){printk("file_write:block_bitmap_alloc for situation 2 failed\n");return -1;}ASSERT(file->fd_inode->i_sectors[12]==0);//确保一级块表未分配/*分配一级块间接索引表*/indirect_block_table = file->fd_inode->i_sectors[12] = block_lba;block_idx = file_has_used_blocks;   //第-个未使用的块,即本文件最后一个已经使用的直接块的下一块while(block_idx < file_will_use_blocks){block_lba = block_bitmap_alloc(cur_part);if(block_lba==-1){printk("file_write:block_bitmap_alloc for situation 2 failed\n");return -1;}if(block_idx <  12){    //新创建的0-11快直接存入all_blocks数组中ASSERT(file->fd_inode->i_sectors[block_idx]==0);    //确保尚未分配扇区地址file->fd_inode->i_sectors[block_idx] = all_blocks[block_idx] = block_lba;}else{//间接块只写入到all_blocks数组中,待全部分配完成后一次同步到硬盘all_blocks[block_idx] = block_lba;}/*每分配一个块就将文图同步到硬盘*/block_bitmap_idx = block_lba - cur_part->sb->block_bitmap_lba;bitmap_sync(cur_part,block_bitmap_idx,BLOCK_BITMAP);block_idx++;}ide_write(cur_part->my_disk,indirect_block_table,all_blocks+12,1);   //同步一级间接块表到硬盘}else if(file_has_used_blocks > 12){/*第三种情况:新数据占间接块*/ASSERT(file->fd_inode->i_sectors[12]!=0);   //已经具备了一级间接块indirect_block_table = file->fd_inode->i_sectors[12];   //  获取一级间接表地址/*已经使用的间接块也将被读入all_blocks,无需单独收录*/ide_read(cur_part->my_disk,indirect_block_table,all_blocks+12,1);   //获取所有间接块地址block_idx = file_has_used_blocks;   //第一个为使用的间接块,即已经使用的间接块的下一块while(block_idx<file_will_use_blocks){block_lba = block_bitmap_alloc(cur_part);if(block_lba==-1){printk("file_write:block_bitmap_alloc for situation 3 failed\n");return -1;}all_blocks[block_idx] = block_lba;/*每分配一个块就将文图同步到硬盘*/block_bitmap_idx = block_lba - cur_part->sb->block_bitmap_lba;bitmap_sync(cur_part,block_bitmap_idx,BLOCK_BITMAP);block_idx++;}ide_write(cur_part->my_disk,indirect_block_table,all_blocks+12,1);//同步一级间接块表到硬盘}}/*用到的块地址已经收集到了all_blocks中,下面开是写数据*/bool first_write_block = true;  //含有剩余空间的块标识file->fd_pos = file->fd_inode->i_size - 1;  //置fd_pos为文件大小-1,下面在写数据时随时更新,这是文件内偏移量while(bytes_written < count){   //直到数据写完memset(io_buf,0,BLOCK_SIZE);sec_idx = file->fd_inode->i_size / BLOCK_SIZE;sec_lba = all_blocks[sec_idx];sec_off_bytes = file->fd_inode->i_size % BLOCK_SIZE;sec_left_bytes = BLOCK_SIZE - sec_off_bytes;/*判断此写入硬盘的大小数据*/chunk_size = size_left<sec_left_bytes ? size_left : sec_left_bytes;if(first_write_block){ide_read(cur_part->my_disk,sec_lba,io_buf,1);first_write_block = false;}memcpy(io_buf+sec_off_bytes,src,chunk_size);ide_write(cur_part->my_disk,sec_lba,io_buf,1);printk("file write at lba 0x%x\n",sec_lba); //调试,完成后去掉src+=chunk_size;    //将指针推移到下一个新数据file->fd_inode->i_size+=chunk_size; //更新文件大小file->fd_pos +=chunk_size;bytes_written+=chunk_size;size_left -= chunk_size;}inode_sync(cur_part,file->fd_inode,io_buf);sys_free(all_blocks);sys_free(io_buf);return bytes_written;
}

file_write:功能是把buf中的count个字节写入file,成功则返回写入的字节数,失败则返回-1。核心的原理是:传进函数的文件结构struct file指针中有个指向操作文件inode的指针,通过这个inode中的i_sizei_sectors[ ],我们可以顺利知道文件大小与存储位置信息。先将文件已有数据的最后一块数据读出来并与将要写入的数据在缓冲区中共同拼凑成一个完整的块,然后写入磁盘。剩下的数据以块为单位继续写入磁盘即可。

流程:1.先判断写入的buf会不会超出文件的大小;2.申请缓冲区;3.写入count字节前,先计算该文件已经占用的块数;4.计算存储count字节后该文件将占用的块数;5.将写文件所用到的块地址收集到all_blocks,共分为三种情况讨论;6.用到的块地址已经收集到了all_blocks中,开始写数据。

14.7.2 改进sys_write及write

因为之前我们实现的sys_write,由于没有实现file_write,所以它就是调用了console_put_str打印字符串,现在我们改进sys_write

如果传入的fd表示标准输出,直接调用console_put_str打印即可。否则就调用fd_local2global获取文件描述符fd对应于文件表中的下标_fd,然后获得待写入文件的文件结构指针wr_file,再判断他的flag,最后做出判断。

//fs.c
/*将buf中连续count个字节写入文件描述符fd,成功则返回写入的字节数,失败返回-1*/
int32_t sys_write(int32_t fd, const void* buf, uint32_t count){if(fd<0){printk("sys_write:fd error\n");return -1;}if(fd==stdout_no){char tmp_buf[1024] = {0};memcpy(tmp_buf,buf,count);console_put_str(tmp_buf);return count;}uint32_t _fd = fd_local2global(fd);struct file* wr_file = &file_table[_fd];if(wr_file->fd_flag & O_WRONLY || wr_file->fd_flag & O_RDWR){uint32_t bytes_written = file_write(wr_file,buf,count);return bytes_written;}else{console_put_str("sys_write: not allowed to write file without flag O_RDWR or O_WRONLY\n");return -1;}
}

同时修改write

/* 把buf中count个字符写入文件描述符fd */
uint32_t write(int32_t fd, const void *buf, uint32_t count)
{return _syscall3(SYS_WRITE, fd, buf, count);//其实就是更改这里
}

最后再把printf修改一下:

/* 格式化输出字符串format */
uint32_t printf(const char *format, ...)
{va_list args;va_start(args, format); // 使args指向formatchar buf[1024] = {0};   // 用于存储拼接后的字符串vsprintf(buf, format, args);va_end(args);return write(1, buf, strlen(buf));//其实就是更改这里
}
http://www.zhongyajixie.com/news/51810.html

相关文章:

  • 盗版小说网站怎么做的湖南做网站的公司
  • 洛阳做网站公司最打动人心的广告语
  • 如何虚拟一个公司网站班级优化大师免费下载学生版
  • 公司的网站建设费会计分录搭建网站平台
  • 太原网站排名公司哪家好搜索优化的培训免费咨询
  • 网站导航如何优化seo网站关键词优化
  • 怎么做asp网站公司的seo是什么意思
  • 商城类网站建设多少钱怎么做网络广告
  • 养殖推广网站怎么做新站优化案例
  • 群晖做网站域名重庆森林
  • 简单的做网站软件有啥外贸平台排名
  • 招网站建设销售免费网站制作成品
  • 互联网企业有哪些行业黄山seo
  • 高中网站制作蜂蜜网络营销推广方案
  • 临沂seo网站推广百度广告上的商家可靠吗
  • 网站建设多少钱杭州四川网站推广公司
  • 珠海选车牌号网站系统日本域名注册
  • 商会网站怎么做优化设计答案四年级上册语文
  • 网站建设 html国际新闻直播
  • 如何把图片放到网站后台国产系统2345
  • 徐州网站建设找哪家好软文广告
  • 大连建设工程设计院有限公司网站青岛网站制作seo
  • 哪个平台可以接推广任务百度app优化
  • 建设人才网站的目的十大场景营销案例
  • 哪个网站做相片书好企业网络营销推广方案策划
  • 站长工具亚洲高清推广软文代写
  • 兖州做网站seo是什么化学名称
  • 制作公众号的软件福州百度seo排名软件
  • jsp做网站开发前端开发培训机构推荐
  • 公司无网站无平台怎么做外贸搜索引擎优化答案