㈠ 內存訪問斷點和 硬體訪問斷點有什麼區別
內存斷點是通過把相應位置指令替換成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(),我覺得按你們出題這個思路,應該回答是沒有給變數加&運算符,造成把你輸入的變數值當成了地址值,那你得變數值肯定會使別人的地址啊,是他自己地址的情況太罕見了,基本不可能,所以就會出現用了不能用的內存(如你去占政府的地方去了),或者佔用其他人的啥的就會引發內存訪問錯誤。