织梦系统怎么做单页网站国内有什么网站

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

织梦系统怎么做单页网站,国内有什么网站,什么是权重高的网站,西宁建设局官方网站14.7 实现文件写入 这是一个网站有所有小节的代码实现#xff0c;同时也包含了Bochs等文件 本节要实现的 sys_write 是系统调用 write 的内核实现#xff0c;咱们之前的 write 是个简易版#xff0c;它是为了临时完成输出打印的功能#xff0c;不支持文件描述符。如今要让…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)){ //文件目前最大只支持51214071680字节printk(exceed max file_size 71680 bytes,write file failed\n);return -1;}uint8_t io_buf sys_malloc(512);if(io_bufNULL){printk(file_write:sys_malloc for io_buf failed\n);return -1;}uint32_t* all_blocks (uint32_t)sys_malloc(BLOCK_SIZE48); //用来记录文件所有的块地址一个地址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_blocks0){/在同一扇区内写入数据不涉及到分配新扇区/if(file_will_use_blocks12){//文件数据将在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_blocks12,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_idxfile_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_blocks12,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_blocks12,1); //获取所有间接块地址block_idx file_has_used_blocks; //第一个为使用的间接块即已经使用的间接块的下一块while(block_idxfile_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_blocks12,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_leftsec_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_bufsec_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); //调试完成后去掉srcchunk_size; //将指针推移到下一个新数据file-fd_inode-i_sizechunk_size; //更新文件大小file-fd_pos chunk_size;bytes_writtenchunk_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_size与i_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(fd0){printk(sys_write:fd error\n);return -1;}if(fdstdout_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));//其实就是更改这里 }