怎么通过代码实现seesionstorage和localstorage的切换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么通过代码实现seesionstorage和localstorage的切换相关的知识,希望对你有一定的参考价值。
参考技术A sessionStorage 和 localStorage 是html5 Web Storage API 提供的,可以方便的在web请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。 sessionStorage、localStorage、cookie都是在浏览器端存储的数据,其中sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念。sessionStorage是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁。同时“独立”打开的不同窗口,即使是同一页面,sessionStorage对象也是不同的。 Web Storage带来的好处:减少中国络流量:一旦数据保存在本地后,就可以避免再向服务器请求数据,因此减少不必要的数据请求,减少数据在浏览器和服务器间不必要地来回传递。快速显示数据:性能好,从本地读数据比通过中国络从服务器获得数据快得多,本地数据可以即时获得。再加上中国页本身也可以有缓存,因此整个页面和数据都在本地的话,可以立即显示。临时存储:很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用sessionStorage非常方便。 浏览器本地存储与服务器端存储之间的区别其实数据既可以在浏览器本地存储,也可以在服务器端存储。 浏览器端可以保存一些数据,需要的时候直接从本地获取,sessionStorage、localStorage和cookie都由浏览器存储在本地的数据。 服务器端也可以保存所有用户的所有数据,但需要的时候浏览器要向服务器请求数据。一.服务器端可以保存用户的持久数据,如数据库和云存储将用户的大量数据保存在服务器端。二.服务器端也可以保存用户的临时会话数据。服务器端的session机制,如jsp的 session 对象,数据保存在服务器上。实现上,服务器和浏览器之间仅需传递session id即可,服务器根据session id找到对应用户的session对象。会话数据仅在一段时间内有效,这个时间就是server端设置的session有效期。 服务器端保存所有的用户的数据,所以服务器端的开销较大,而浏览器端保存则把不同用户需要的数据分布保存在用户各自的浏览器中。浏览器端一般只用来存储小数据,而服务器可以存储大数据或小数据。服务器存储数据安全一些,浏览器只适合存储一般数据。 sessionStorage 、localStorage 和 cookie 之间的区别 共同点:都是保存在浏览器端,且同源的。区别:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过四k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。 sessionStorage 和 localStorage 之间的区别见上面的区别三、四 sessionStorage与页面 js 数据对象的区别页面中一般的 js 对象或数据的生存期是仅在当前页面有效,因此刷新页面或转到另一页面这样的重新加载页面的情况,数据就不存在了。而sessionStorage 只要同源的同窗口(或tab)中,刷新页面或进入同源的不同页面,数据始终存在。也就是说只要这个浏览器窗口没有关闭,加载新页面或重新加载,数据仍然存在。 cookie,容量四kb,默认各种浏览器都支持,缺陷就是每次请求,浏览器都会把本机存的cookies发送到服务器,无形中浪费带宽。 userdata,只有ie支持,单个容量陆四kb,每个域名最多可存一0个共计陆四0k数据。默认保存在C:\Documents and Settings\Administrator\UserData\目录下,保存格式为xml。关于userdata更多资料参考中国msdn.microsoft中国/library/default.asp?url=/workshop/author/behaviors/reference/behaviors/userdata.asp sessionStorage与localStorage Web Storage实际上由两部分组成:sessionStorage与localStorage。 sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。 localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。 为什么选择Web Storage而不是Cookie? 与Cookie相比,Web Storage存在不少的优势,概括为以下几点: 一. 存储空间更大:IE吧下每个独立的存储空间为一0M,其他浏览器实现略有不同,但都比Cookie要大很多。 二. 存储内容不会发送到服务器:当设置了Cookie后,Cookie的内容会随着请求一并发送的服务器,这对于本地存储的数据是一种带宽浪费。而Web Storage中的数据则仅仅是存在本地,不会与服务器发生任何交互。 三. 更多丰富易用的接口:Web Storage提供了一套更为丰富的接口,使得数据操作更为简便。 四. 独立的存储空间:每个域(包括子域)有独立的存储空间,各个存储空间是完全独立的,因此不会造成数据混乱cpu设计和实现(协处理器hi和lo)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
很多同学可能不了解mips处理器,如果个人想补充一点mips cpu的知识,可以找些书籍资料来读一下,比如《See Mips Run》。
上一期说到了,在cpu设计的过程当中,使用了数据预取的技术。它解决的问题就是,因为流水线的关系,后续数据在计算的过程当中,如果仅仅从寄存器获取数据,就有可能发生数据读取错误的情况。因为这个时候,相关寄存器的数据可能在执行、访存、写回的阶段就已经被改写了,只不过数据暂时还没有写到寄存器里面而已。所以,这个时候就需要从执行、访存、写回模块把数据提前读回来,这样就不会发生数据读取错误的情况。
1、添加更多mips 命令
有了数据预取的操作,这个时候cpu就可以添加更多汇编指令来执行了。比如说,简单的逻辑指令and、andi、or、ori、xor、xori、nor、lui,简单的移位指令sll、sllv、sra、srav、srl、srlv等等。完成这些指令的解析之后,可以准备一段汇编代码,
.org 0x0
.global _start
.set noat
_start:
lui $1,0x0101
ori $1,$1,0x0101
ori $2,$1,0x1100
or $1,$1,$2
andi $3,$1,0x00fe
and $1,$3,$1
xori $4,$1,0xff00
xor $1,$4,$1
nor $1,$4,$1
生成对应的二进制代码inst_rom.data,
3c010101
34210101
34221100
00220825
302300fe
00610824
3824ff00
00810826
00810827
有了这些二进制代码,加上在译码、执行阶段添加必要的verilog代码。这样就可以通过波形图来验证我们的设计是否正确了。
因为对应的汇编代码比较简单,所以可以直接通过一些寄存器的阅读就可以判断汇编代码是否执行正确。被引入的波形主要是三部分,第一部分是pc_reg0;第二部分是mem_wb0;第三部分是regfile1。pc_reg0主要看pc地址有没有层层递进;mem_wb0则查看exe-wb阶段要写回的寄存器地址、数值是什么,对不对;regfile1则确认一下写回的寄存器数值对不对。
比如说从wb_wd寄存器地址为1开始,也就是汇编第一条指令的访存结束阶段,寄存器地址为1,数值为0x01010000,可以结合汇编指令看下是否正确。下一条写回的寄存器地址还是1,数值为0x01010101,继续结合汇编看下对不对。以此类推,不断检测要写的寄存器地址、寄存器数值,就可以判断之前添加的译码、执行、数据预取有没有做正确。这就是怎么读波形的一个方法。
需要注意的是,regfile1会比mem_wb0晚一个上升沿,这个留意一下即可。
2、hi和lo寄存器
hi和lo属于协处理器,不在通用寄存器的范围内。这两个寄存器主要是在用来处理乘法和除法。以乘法作为示例,如果两个整数相乘,那么乘法的结果低位保存在lo寄存器,高位保存在hi寄存器。当然,这两个寄存器也可以独立进行读取和写入。读的时候,使用mfhi、mflo;写入的时候,用mthi、mtlo。
和通用寄存器不同,mfhi、mflo是在执行阶段才开始从hi、lo寄存器获取数值的。写入则和通用寄存器一样,也是在写回的时候完成的。
也许这个时候,就有同学发现了一个问题。如果mfhi、mflo发现在访存和写回阶段,hi和lo的数值已经发生了变更怎么办?其实方法很简单,就是继续使用数据预取的方法即可。在数值还没有写回到hi和lo的时候,就提前把这些数据读回来。
`include "defines.v"
module hilo_reg(
input wire clk,
input wire rst,
input wire we,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if((we == `WriteEnable)) begin
hi_o <= hi_i;
lo_o <= lo_i;
end
end
endmodule
这是hi、lo寄存器的访问文件hilo_reg.v。内容还是比较简单的。复位的时候,直接置为0;如果有写入的操作,则对hi_o、lo_o进行赋值操作。
解决了hi、lo的写入、读取问题,下面就要在ex.v中解决数据依赖的问题,
always @ (*) begin
if(rst == `RstEnable) begin
HI,LO <= `ZeroWord,`ZeroWord;
end else if(mem_whilo_i == `WriteEnable) begin
HI,LO <= mem_hi_i,mem_lo_i;
end else if(wb_whilo_i == `WriteEnable) begin
HI,LO <= wb_hi_i,wb_lo_i;
end else begin
HI,LO <= hi_i,lo_i;
end
end
这段代码是组合逻辑。如果复位,则HI、LO为0;如果访存做了修改,那么直接从访存获取数值;如果写回做了修改,那么直接从写回获取数值;否则就是正常从hilo_reg.v那里获取数值。有了这段代码,那么对访存阶段的hi、lo输出就有了基本的依据,
always @ (*) begin
if(rst == `RstEnable) begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if(aluop_i == `EXE_MTHI_OP) begin
whilo_o <= `WriteEnable;
hi_o <= reg1_i;
lo_o <= LO;
end else if(aluop_i == `EXE_MTLO_OP) begin
whilo_o <= `WriteEnable;
hi_o <= HI;
lo_o <= reg1_i;
end else begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
end
注意,这段代码同样是一段组合逻辑。复位之后,没有操作;如果是mthi,那么将reg1_i和LO进行输出,这里的LO来自刚刚介绍的组合逻辑;如果是mtlo,那么将HI和reg1_i进行输出,同样HI也是来自之前的组合逻辑;当然如果上面的情况都不对,直接返回0。
上面只是说了hi、lo操作的方法和原理。真正要实施起来,还需要对访存阶段的代码修改一下。至少需要把hi、lo必要的寄存器透传下去。
`include "defines.v"
module ex_mem(
input wire clk,
input wire rst,
input wire[`RegAddrBus] ex_wd,
input wire ex_wreg,
input wire[`RegBus] ex_wdata,
input wire[`RegBus] ex_hi,
input wire[`RegBus] ex_lo,
input wire ex_whilo,
output reg[`RegAddrBus] mem_wd,
output reg mem_wreg,
output reg[`RegBus] mem_wdata,
output reg[`RegBus] mem_hi,
output reg[`RegBus] mem_lo,
output reg mem_whilo
);
always @ (posedge clk) begin
if(rst == `RstEnable) begin
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
mem_wdata <= `ZeroWord;
mem_hi <= `ZeroWord;
mem_lo <= `ZeroWord;
mem_whilo <= `WriteDisable;
end else begin
mem_wd <= ex_wd;
mem_wreg <= ex_wreg;
mem_wdata <= ex_wdata;
mem_hi <= ex_hi;
mem_lo <= ex_lo;
mem_whilo <= ex_whilo;
end
end
endmodule
接下来就可以准备一段汇编代码测试下,
.org 0x0
.set noat
.global _start
_start:
lui $1,0x0000
lui $2,0xffff
lui $3,0x0505
lui $4,0x0000
movz $4,$2,$1
movn $4,$3,$1
movn $4,$3,$2
movz $4,$2,$3
mthi $0
mthi $2
mthi $3
mfhi $4
mtlo $3
mtlo $2
mtlo $1
mflo $4
转成必要的指令数据,16行有效汇编代码对应16条32位数据,
3c010000
3c02ffff
3c030505
3c040000
0041200a
0061200b
0062200b
0043200a
00000011
00400011
00600011
00002010
00600013
00400013
00200013
00002012
做好了这些准备之后,就可以开始进行仿真测试了。同样,这里使用的都是《自己动手写cpu》里面的参考代码,是Chapter6里面的代码。借鉴使用别人的代码问题不大,关键是能够看懂、学会,这样就可以在自己的项目中不断实践了。当然,之前说过,需要对代码进行修改一下。
简单分析下,先找到pc第一次取指操作,然后找到第一次wb数据。从图形上看,第一次写回数据的时候是290ns。写回的地址是0x1,数值是0x0,这个时候就可以结合汇编第一条代码确认下是不是这样的。没有问题的话,可以再确认下一个周期里面,是不是regs1真的发生了改变。这就是第一条汇编指令的分析过程。
继续分析,直到450ns的时候,开始执行第一个协处理器指令mthi。
这里分析下mthi是否正确,可以直接把两组信号拖出来。一组信号来自于mem_wb0;另一组信号来自于hilo_reg0。从450ns开始,第一次写入的数据hi是0x0、lo是0x0;第二次写入的数据hi是0xffff0000、lo是0x0,以此类推。这两个数据写的对不对,可以结合汇编代码一起来看下。对应的汇编代码应该是mthi $0,mthi $2这样的。
从530ns开始,执行的命令变成了mtlo,分析方法和刚才mthi还是一样的。
从上面可以看出,cpu的实现主要还是要静下心来慢慢做,耐得烦。要相信自己,问题总是可以解决的。
以上是关于怎么通过代码实现seesionstorage和localstorage的切换的主要内容,如果未能解决你的问题,请参考以下文章
「GoCN酷Go推荐」基于泛型的 Golang lodash 库 — samber/lo
Linux-eth0 eth0:1 ifcfg-lo ifcfg-lo:0 和eth0.1关系ifconfig以及虚拟IP实现介绍