計算機存儲器是計算機系統中最為核心的部分之一,它是計算機系統中的數據存儲、讀寫操作的場所,使用了如 DRAM、SRAM 等晶元作為存儲媒介,是計算機系統中最快速的部分之一。以下從不同的方面來闡述計算機存儲器:
一、內存分類
內存通常分為隨機存儲器(RAM)和只讀存儲器(ROM)。RAM 是一種易失性存儲器,存放的內容需要經過電源供電才能保留,常見的有動態隨機存儲器(DRAM)和靜態隨機存儲器(SRAM)。DRAM 存儲單元需要定期刷新數據才能保持,而 SRAM 存儲單元不需要定期刷新。ROM 是一種非易失性存儲器,存放的內容不需要經過電源供電就可以保存,常見的有隻讀存儲器(ROM)、可編程只讀存儲器(PROM)、可擦寫可編程只讀存儲器(EPROM)和電可擦可編程只讀存儲器(EEPROM)。
// C 語言代碼示例:使用指針動態分配內存
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ptr; // 定義一個指向整型數據的指針
int num = 5; // 定義一個整型變數
ptr = (int*)malloc(num * sizeof(int)); // 動態分配內存
if (ptr == NULL) {
printf("動態分配內存失敗!");
exit(0);
}
for (int i = 0; i < num; i++) {
*(ptr + i) = i; // 給指針所指向的內存賦值
}
for (int i = 0; i < num; i++) {
printf("%d ", *(ptr + i)); // 輸出指針所指向的內存
}
free(ptr); // 釋放內存
return 0;
}
二、內存定址
內存定址指的是CPU對內存單元進行訪問的方式,在程序運行時,CPU 訪問內存的地址是由程序中指定的內存地址決定的。CPU 提供了一組地址匯流排,根據地址匯流排的數位規定,計算機的內存定址空間大小也就被確定下來。在現代計算機中,CPU 的地址匯流排寬度一般為 32 位或 64 位,因此可以定址的內存空間大小為 2^32個位元組或2^64個位元組。
// C 語言代碼示例:從指定地址的內存單元讀取數據
#include <stdio.h>
#include <stdlib.h>
int main() {
char* data = (char*)malloc(1 * sizeof(char));
if (data == NULL) {
printf("動態分配內存失敗!");
exit(0);
}
long address = 0x7fff5fbff718; // 一個 64 位地址
*data = *(char*)address; // 從指定地址的內存單元讀取一個位元組的數據
printf("讀取的數據為:%c\n", *data);
free(data); // 釋放內存
return 0;
}
三、內存映射
內存映射指的是將計算機外部設備的狀態映射到計算機內存空間的技術。內存映射使得在編程中可以像讀寫內存單元一樣來讀寫外部設備的狀態,極大地簡化了編程。例如,在 Linux 系統中,可以將硬碟上的文件映射到內存中,以便更快地進行讀寫操作。
// C 語言代碼示例:使用內存映射文件進行讀寫操作
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
int fd = open("file.txt", O_RDWR); // 打開文件
if (fd == -1) {
printf("打開文件失敗!");
exit(0);
}
struct stat sb; // stat 結構體
if (fstat(fd, &sb) == -1) { // 獲取文件狀態
printf("獲取文件狀態失敗!");
exit(0);
}
char* addr = (char*)mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // 映射文件到內存
if (addr == MAP_FAILED) {
printf("映射文件到內存失敗!");
exit(0);
}
char str[] = "Hello, world!"; // 字元串
int len = sizeof(str) / sizeof(*str); // 確定字元串長度
for (int i = 0; i < len; i++) {
*(addr + i) = *(str + i); // 寫入字元串到內存
}
printf("%s\n", addr); // 從內存讀取字元串
munmap(addr, sb.st_size); // 取消內存映射
close(fd); // 關閉文件
return 0;
}
四、內存管理
內存管理是指對計算機內存的使用、分配、釋放進行有效控制,以提高內存的使用效率和程序的健壯性。常見的內存管理策略有靜態分配、動態分配、內存池和垃圾回收等。在使用動態分配內存時,程序員需要自行分配和釋放內存,如果出現錯誤可能會造成內存泄漏或內存損壞等問題。內存池技術可以對內存進行緩存,實現快速的內存分配和回收,從而提高程序的性能和穩定性。垃圾回收技術可以自動地回收不再使用的內存資源,減少了程序員的工作量,但會造成一定的程序性能損失。
// C 語言代碼示例:使用內存池分配和釋放內存
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 10 // 內存池大小
void* my_malloc(int size); // 內存分配函數
void my_free(void* ptr); // 內存釋放函數
int main() {
int* ptr1 = (int*)my_malloc(sizeof(int)); // 分配內存
*ptr1 = 10; // 給內存賦值
printf("%d\n", *ptr1); // 輸出內存中的數據
int* ptr2 = (int*)my_malloc(sizeof(int)); // 內存不足時,再次分配內存
*ptr2 = 20; // 給內存賦值
printf("%d\n", *ptr2); // 輸出內存中的數據
my_free(ptr1); // 釋放已經使用的內存
my_free(ptr2);
return 0;
}
void* my_malloc(int size) {
static char memory[MAX_NUM * sizeof(int)]; // 內存池
static int start = 0; // 下一個可用塊的索引
int block_num = MAX_NUM - start; // 當前還剩下的內存塊數量
if (block_num * sizeof(int) < size) {
printf("內存分配失敗!");
exit(0);
}
void* ptr = (void*)(memory + start * sizeof(int)); // 分配內存並返回
start += size / sizeof(int);
return ptr;
}
void my_free(void* ptr) {
// 略去釋放內存的具體實現
}
五、內存保護
內存保護是指通過操作系統以及硬體的支持,為了避免程序出現內存錯誤而採取的一系列措施。內存保護可以限制程序的訪問內存的範圍,防止程序訪問非法的內存區域,以及檢測訪問內存的錯誤。在計算機系統中,可以通過硬體支持的內存保護機制(如MMU)來實現,可以設置預設參數對內存進行保護,防止程序訪問到系統內核區域、只讀內存區域、未使用內存區域等。
// C 語言代碼示例:在 Linux 系統中使用 mprotect 系統調用保護內存
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main() {
int* ptr = (int*)malloc(1 * sizeof(int));
if (ptr == NULL) {
printf("分配內存失敗!");
exit(0);
}
// 將內存區設置為只讀
if (mprotect(ptr, sizeof(int), PROT_READ) == -1) {
printf("設置內存保護失敗!");
exit(0);
}
*ptr = 5; // 寫入數據
printf("%d\n", *ptr); // 讀取數據
free(ptr); // 釋放內存
return 0;
}
原創文章,作者:PRDGN,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/371554.html