㈠ 内存访问断点和 硬件访问断点有什么区别
内存断点是通过把相应位置指令替换成int3来实现的。硬件断点是通过设置CPU相应硬件寄存器来阻止程序继续运行的。因为修改程序代码你想怎么改就怎么改。所以内存断点你可以设置很多个。而硬件寄存器数量有限,所以只能设置几个(目前大多数是4个)因为修改的是程序的代码,所以内存断点很容易被程序自身检测到。而硬件断点则很难被发现。
㈡ 怎样提高内存访问速度
你是不是发现电脑运行速度越来越慢了,却又找不到原因?电脑运行慢是很多用户苦恼的问题,经常使用大型软件的人更甚,比如喜欢玩游戏的用户。其实这有可能是内存的原因,那么如何解决电脑内存运行过慢问题呢?很快大家就不用烦恼了,因为小编要教大家如何巧妙的加快内存运行速度!第一招:调整高速缓存区域的大小我们通常说的高速缓存,是指系统在读取磁盘、光盘上的数据时,采取“预读取”技术,就是把估计快要读取的数据预先读取到内存的高速缓冲存储器中,这样CPU在高速缓冲存储器中读取数据时就会加快,可以提高运行速度。同样的在内存中设置高速缓冲存储器,也可以明显地加快读取数据的速度。Windows可以根据内存的大小自动地设置高速缓存的大小,也可以根据个人情况在内存中设置高速缓存的大小,来优化内存的使用。解决方法:只要在桌面上用鼠标右击“我的电脑”,在屏幕弹出的菜单中点击“属性”,在窗口中点击“性能”标签,再点击下面的“文件系统”,点击“硬盘”标签,拖动“预读式优化”调节杆,设置预读取条件,在“计算机的主要用途”栏设置系统利用高速缓存的比例,系统的内存较多的话可选择“网络服务器”,系统就会用较多的内存作为高速缓存了。在CD-ROM标签里,可以直接调节系统用多少内存作为CD-xviii) ROM光盘读写的高速缓存,注意要在“最佳访问方式”中选择“四倍速或更高速”,系统将根据情况设置缓存的大小,也可以调节“追加的高速缓存大小”栏中的调节杆,xxii) 追加高速缓存。
㈢ c语言的非法内存访问什么意思
这有好几种情况,常见的是C系统安排内存的有些区域是不能写数据的,如果代码误操作向这些保留区域写数据就要产生非法访问错误;有些区域即使读取也是不可以的,也会产生上述错误。
㈣ 如何高效的访问内存
影响内存访问速度的因素主要有:
1.内存带宽:每秒读写内存的数据量,由硬件配置决定。
2.CACHE高速缓冲:CPU与内存之间的缓冲器,当命中率比较高时能大大提供内存平均访问速度。
3.TLB转换旁视缓冲:系统虚拟地址向物理地址转换的高速查表机制,转换速度比普通转换机制要快。
我们能够优化的只有第2点和第3点。由于CACHE的小容量与SMP的同步竞争,如何最大限度的利用高速缓冲就是我们的明确优化突破口(以常用的数据结构体为例):
1.压缩结构体大小:针对CACHE的小容量。
2.对结构体进行对齐:针对内存地址读写特性与SMP上CACHE的同步竞争。
3.申请地址连续的内存空间:针对TLB的小容量和CACHE命中。
4.其它优化:综合考虑多种因素
具体优化方法
1.压缩结构体大小
系统CACHE是有限的,并且容量很小,充分压缩结构体大小,使得CACHE能缓存更多的被访问数据,无非是提高内存平均访问速度的有效方法之一。
压缩结构体大小除了需要我们对应用逻辑做好更合理的设计,尽量去除不必要的字段,还有一些额外针对结构体本身的压缩方法。
1.1.对结构体字段进行合理的排列
由于结构体自身对齐的特性,具有同样字段的结构体,不同的字段排列顺序会产生不同大小的结构体。
大小:12字节
struct box_a
{
char a;
short b;
int c;
char d;
};
大小:8字节
struct box_b
{
char a;
char d;
short b;
int c;
};
1.2.利用位域
实际中,有些结构体字段并不需要那么大的存储空间,比如表示真假标记的flag字段只取两个值之一,0或1,此时用1个bit位即可,如果使用int类型的单一字段就大大的浪费了空间。
示例:tcp.h
struct tcphdr {
__be16 source;
__be16 dest;
__be32 seq;
__be32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your defines"
#endif
__be16 window;
__sum16 check;
__be16 urg_ptr;
};
1.3.利用union
union结构体也是压缩结构体大小的方法之一,它允许我们在某些情况下能对结构体的多个字段进行合并或把小字节字段存放到大字节字段内。
示例:skbuff.h
struct sk_buff {
…
union {
__wsum csum;
struct {
__u16 csum_start;
__u16 csum_offset;
};
};
…
};
2.对结构体进行对齐
对结构体进行对齐有两层意思,一是指对较小结构体进行机器字对齐,二是指对较大结构体进行CACHE LINE对齐。
2.1.对较小结构体进行机器字对齐
我们知道,对于现代计算机硬件来说,内存只能通过特定的对齐地址(比如按照机器字)进行访问。举个例子来说,比如在64位的机器上,不管我们是要读取第0个字节还是要读取第1个字节,在硬件上传输的信号都是一样的。因为它都会把地址0到地址7,这8个字节全部读到CPU,只是当我们是需要读取第0个字节时,丢掉后面7个字节,当我们是需要读取第1个字节,丢掉第1个和后面6个字节。
当我们要读取的字节刚好落在两个机器字内时,就出现两次访问内存的情况,同时通过一些逻辑计算才能得到最终的结果。
因此,为了更好的提升性能,我们须尽量将结构体做到机器字(或倍数)对齐,而结构体中一些频繁访问的字段也尽量安排在机器字对齐的位置。
大小:12字节
struct box_c
{
char a;
char d;
short b;
int c;
int e;
};
大小:16字节
struct box_d
{
char a;
char d;
short b;
int c;
int e;
char padding[4];
};
上面表格右边的box_d结构体,通过增加一个填充字段padding将结构体大小增加到16字节,从而与机器字倍数对齐,这在我们申请连续的box_d结构体数组时,仍能保证数组内的每一个结构体都与机器字倍数对齐。
通过填充字段padding使得结构体大小与机器字倍数对齐是一种常见的做法,在Linux内核源码里随处可见。
2.2.对较大结构体进行CACHE LINE对齐
我们知道,CACHE与内存交换的最小单位为CACHE LINE,一个CACHE LINE大小以64字节为例。当我们的结构体大小没有与64字节对齐时,一个结构体可能就要占用比原本需要更多的CACHE LINE。比如,把一个内存中没有64字节长的结构体缓存到CACHE时,即使该结构体本身长度或许没有还没有64字节,但由于其前后搭占在两条CACHE LINE上,那么对其进行淘汰时就会淘汰出去两条CACHE LINE。
这还不是最严重的问题,非CACHE LINE对齐结构体在SMP机器上容易引发名为错误共享的CACHE问题。比如,结构体T1和T2都没做CACHE LINE对齐,如果它们(T1后半部和T2前半部)在SMP机器上合占了同一条CACHE,如果CPU 0对结构体T1后半部做了修改则将导致CPU 1的CACHE LINE 1失效,同样,如果CPU 1对结构体T2前半部做了修改则也将导致CPU 0的CACHE LINE 1失效。如果CPU 0和CPU 1反复做相应的修改则导致的不良结果显而易见。本来逻辑上没有共享的结构体T1和T2,实际上却共享了CACHE LINE 1,这就是所谓的错误共享。
Linux源码里提供了利用GCC的__attribute__扩展属性定义的宏来做这种对齐处理,在文件/linux-2.6.xx/include/linux/cache.h内可以找到多个相类似的宏,比如:
点击(此处)折叠或打开
#define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
该宏可以用来修饰结构体字段,作用是强制该字段地址与CACHE LINE映射起始地址对齐。
看/linux-2.6.xx/drivers/net/e100.c内结构体nic的实现,三个____cacheline_aligned修饰字段,表示强制这些字段与CACHE LINE映射起始地址对齐。
点击(此处)折叠或打开
struct nic {
/* Begin: frequently used values: keep adjacent for cache effect */
u32 msg_enable ____cacheline_aligned;
/* 4字节空洞 */
struct net_device *netdev;
struct pci_dev *pdev;
/* 40字节空洞 */
struct rx *rxs ____cacheline_aligned;
struct rx *rx_to_use;
struct rx *rx_to_clean;
struct rfd blank_rfd;
enum ru_state ru_running;
/* 20字节空洞 */
spinlock_t cb_lock ____cacheline_aligned;
spinlock_t cmd_lock;
struct csr __iomem *csr;
enum scb_cmd_lo cuc_cmd;
unsigned int cbs_avail;
struct napi_struct napi;
…
}
回到前面的问题,如果我们对结构体T2的第一个字段加上____cacheline_aligned修饰,则该错误共享即可解决。
2.3.只读字段和读写字段隔离对齐
只读字段和读写字段隔离对齐的目的就是为了尽量保证那些只读字段和读写字段分别集中在CACHE的不同CACHE LINE中。由于只读字段几乎不需要进行更新,因而能在CACHE中得以稳定的缓存,减少由于混合有读写字段导致的对应CACHE LINE的频繁失效问题,以便提高效率;而读写字段相对集中在一起,这样也能保证当程序读写结构体时,污染的CACHE LINE条数也就相对的较少。
点击(此处)折叠或打开
typedef struct {
/* ro data */
size_t block_count; // number of total blocks
size_t meta_block_size; // sizeof per skb meta block
size_t data_block_size; // sizeof per skb data block
u8 *meta_base_addr; // base address of skb meta buffer
u8 *data_base_addr; // base address of skb data buffer
/* rw data */
size_t current_index ____cacheline_aligned; // index
} bc_buff, * bc_buff_t;
3.申请地址连续的内存空间
随着地址空间由32位转到64位,页内存管理的目录分级也越来越多,4级的目录地址转换也是一笔不小是开销。硬件产商为我们提供了TLB缓冲,加速虚拟地址到物理地址的换算。但是,毕竟TLB是有限,对地址连续的内存空间进行访问时,TLB能得到更多的命中,同时CACHE高速缓冲命中的几率也更大。
两段代码,实现同一功能,但第一种方法在实际使用中,内存读写效率就会相对较好,特别是在申请的内存很大时(未考虑malloc异常):
点击(此处)折叠或打开
方法一:
#define MAX 100
int i;
char *p;
struct box_d *box[MAX];
p = (char *)malloc(sizeof(struct box_d) * MAX);
for (i = 0; i < MAX; i ++)
{
box[i] = (struct box_d *)(p + sizeof(struct box_d) * i);
}
方法二:
#define MAX 100
int i;
struct box_d *box[MAX];
for (i = 0; i < MAX; i ++)
{
box[i] = (struct box_d *)malloc(sizeof(struct box_d));
}
另外,如果我们使用更大页面(比如2M或1G)的分页机制,同样能够提升性能;因为相比于原本每页4K大小的分页机制,应用程序申请同样大小的内存,大页面分页机制需要的页面数目更少,从而占用的TLB项目也更少,减少虚拟地址到物理地址的转换次数的同时,提高TLB的命中率,缩短每次转换所需要的时间。因为大多数操作系统在分配内存时候都需要按页对齐,所以大页面分页机制的缺点就是内存浪费相对比较严重。只有在物理内存足够充足的情况下,大页面分页机制才能够体现出优势。
4.其它优化
4.1.预读指令读内存
提前预取内存中数据到CACHE内,提高CACHE的命中率,加速内存读取速度,这是设计预读指令的主要目的。如果当前运算复杂度比较高,那么预取和运算就可同步进行,从而消除下一步内存访问的时延。相应的预读汇编指令有prefetch0、prefetch1、prefetch2、 prefetchnta。
预取指令只是给CPU一个提示,所以它可被CPU忽略,而且就算预取一段错误的地址也不会导致CPU异常。一般使用prefetchnta预取指令,因为它不会污染CACHE,它把每次取得的数据都存放到L2 CACHE的第一条CACHE LINE,而另外几条指令会替换CACHE中最近最少使用的CACHE LINE。
4.2.非暂时移动指令写内存
我们知道为了保证CACHE与内存之间的数据一致性,CPU对CACHE的写操作主要有两种方式同步到内存,写透式(Write Through)和写回式(Write-back)。不管哪种同步方式都是要消耗性能的,而在某些情况下,写CACHE是不必要的:
有哪些情况不需要写CACHE呢?比如做数据拷贝(高效memcpy函数实现)时,或者我们已经知道写的数据在最近一段时间内(或者永远)都不会再使用了,那么此时就可以不用写CACHE,让对应的CACHE LINE自动失效,以便缓存其它数据。这在某些特殊场景非常有用,相应的汇编指令有movntq、movntsd、movntss、movntps、movntpd、movntdq、movntdqa。
完整的利用预读指令和非暂时移动指令实现的高速内存拷贝函数:
点击(此处)折叠或打开
void X_aligned_memcpy_sse2(void* dest, const void* src, const unsigned long size_t)
{
__asm
{
mov esi, src; //src pointer
mov edi, dest; //dest pointer
mov ebx, size_t; //ebx is our counter
shr ebx, 7; //divide by 128 (8 * 128bit registers)
loop_:
prefetchnta 128[ESI]; //SSE2 prefetch
prefetchnta 160[ESI];
prefetchnta 192[ESI];
prefetchnta 224[ESI];
movdqa xmm0, 0[ESI]; //move data from src to registers
movdqa xmm1, 16[ESI];
movdqa xmm2, 32[ESI];
movdqa xmm3, 48[ESI];
movdqa xmm4, 64[ESI];
movdqa xmm5, 80[ESI];
movdqa xmm6, 96[ESI];
movdqa xmm7, 112[ESI];
movntdq 0[EDI], xmm0; //move data from registers to dest
movntdq 16[EDI], xmm1;
movntdq 32[EDI], xmm2;
movntdq 48[EDI], xmm3;
movntdq 64[EDI], xmm4;
movntdq 80[EDI], xmm5;
movntdq 96[EDI], xmm6;
movntdq 112[EDI], xmm7;
add esi, 128;
add edi, 128;
dec ebx;
jnz loop_; //loop please
loop__end:
}
}
总结
要高效的访问内存,必须充分利用系统CACHE的缓存功能,因为就目前来说,CACHE的访问速度比内存快太多了。具体优化方法有:
1.用设计上压缩结构体大小。
2.结构体尽量做到机器字(倍数)对齐。
3.结构体中频繁访问的字段尽量放在机器字对齐的位置。
4.频繁读写的多个结构体变量尽量同时申请,使得它们尽可能的分布在较小的线性空间范围内,这样可利用TLB缓冲。
5.当结构体比较大时,对结构体字段进行初始化或设置值时最好从第一个字段依次往后进行,这样可保证对内存的访问是顺序进行。
6.额外的优化可以采用非暂时移动指令(如movntdq)与预读指令(如prefetchnta)。
7.特殊情况可考虑利用多媒体指令SSE2、SSE4等。
当然,上面某些步骤之间存在冲突,比如压缩结构体和结构体对齐,这就需要实际综合考虑。
㈤ cpu是怎么访问内存的这个访问是什么意思
内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行。
㈥ c语言如何访问内存
访问内存 只要知道内存地址就可以了
不过 一般都是动态分配的。
如果要访问固定内存地址 可以
unsigned char * p = (unsigned char *)0xB1234456;//内存地址值
然后通过*p访问该地址。
㈦ 内存分配访问无效
“内存分配访问无效”即为:软件所需的内存不能分配出来。
1:检查系统是否感染病毒.如果系统中已经或者曾经感染过文件型毒,那么系统文件就有可能受到破坏.杀毒软件有可能把病毒杀干净,但被破坏的系统文件却无法还原,你可以试着用SFC(开始--运行,在其中输入command(98等系统)或cmd(2000以上系统)命令修复系统文件.输入SFC 在根据机子提示走)
2:释放内存.也不知道你电脑内存多少.要不是多的话,还开的过大的应用程序(如Photoshop),那在玩游戏前就应该先重新启动一下,以免系统因内存不够造成运行不够造成运行错误.
3:修复 WMI 。在运行中输入“services.msc“ 回车打开系统服务管理,找到并关闭“Windows management instrumentation“服务,删除 Windows\system32\wbem\repository 目录下的所有文件(删除前要先备份哦),完成后重新启动该服务。 要还不行的话就试试 删除不必要的插件
㈧ 访问内存权限在哪里设置
1.点开【设置】。
2.在设置中找到【权限隐私】,并点开。
3.在【权限隐私】中找到【读取、写入或删除储存空间】,并点开。
4.在这里找到你想设置的软件,点击即可设置。
㈨ 计算机中根据什么访问内存
计算机中是根据地址访问内存
㈩ 关于非法内存访问
(1)非法内存访问有剩余空间的多少没关系,非法内存访问的意思就是不是分给你的空间,你却是用了,就是非法的。
(2)就像中国的土地还是很大的,但是你要是想找个地方盖房子,得政府批准,不批准你建了房子,那是违规违法的,这和土地多少没关系,是一种规则,不遵守规则的结果可能你用了一个没人用的荒地,没引起什么后果,但是如果你盖房子的地方已经有人了,那就有点想强拆了的感觉了,肯定出问题啊,即使是占用的荒地,现在没事,可是没准明天政府把这块荒地分给某个开发商了,那你就有麻烦了,摊上事了知道不,嘿嘿。
(3)这个scanf(),我觉得按你们出题这个思路,应该回答是没有给变量加&运算符,造成把你输入的变量值当成了地址值,那你得变量值肯定会使别人的地址啊,是他自己地址的情况太罕见了,基本不可能,所以就会出现用了不能用的内存(如你去占政府的地方去了),或者占用其他人的啥的就会引发内存访问错误。