主存(内存)一般被视为非可抢占资源,即进程已经分配内存后,操作系统不会轻易将其从该进程中抢占。然而在一些情况下,主存也可以被视为可抢占资源。
一、 内存分配
在大多数情况下,内存是由操作系统在进程启动时分配的。操作系统负责为进程中的每个线程分配一些私有内存,进程中的所有线程共享一些公共内存。
例如,在Linux中,可以使用malloc()函数为变量或数组分配内存。该函数从进程的堆中分配内存,并返回一个指向所分配内存的指针。操作系统将返回的内存区域映射到该进程的地址空间中,这样进程就可以访问该内存区域。
然而,在某些情况下,操作系统可能会抢占部分内存区域并将其分配给其他进程。例如,当系统的物理内存不足时,操作系统可能会利用虚拟内存技术将进程的部分内存映射到磁盘上,在需要时再将其读入内存中。当系统需要更多内存时,操作系统可能会将进程占用的部分内存写回磁盘并将其抢占。
int main()
{
// 分配10个整数的数组
int* nums = (int*)malloc(10 * sizeof(int));
if (nums == NULL)
{
printf("内存分配失败!n");
return -1;
}
for (int i = 0; i < 10; i++)
{
nums[i] = i;
}
// 释放内存
free(nums);
return 0;
}
二、 内存泄漏
内存泄漏是指应用程序分配内存后,未能释放该内存,最终导致系统中的可用内存不足。内存泄漏可能导致系统崩溃或严重性能下降。
例如,在下面的代码中,如果忘记使用free()函数释放nums变量,则可能导致内存泄漏。
int main()
{
// 分配10个整数的数组
int* nums = (int*)malloc(10 * sizeof(int));
if (nums == NULL)
{
printf("内存分配失败!n");
return -1;
}
// 忘记释放内存
return 0;
}
三、虚拟内存
虚拟内存是一种将进程内存映射到磁盘空间的技术。当进程需要访问某个内存页时,操作系统将从磁盘中读取该页到物理内存中。因此,虚拟内存为进程提供了一个比物理内存更大的地址空间。
当系统物理内存不足时,操作系统可能会将某些页写回磁盘并将其抢占。因此,虚拟内存是一种可抢占资源。
下面的代码演示了如何使用虚拟内存技术,将进程的内存映射到磁盘上:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
int main()
{
int fd, i;
char* ptr;
// 打开文件,如果不存在则创建它
fd = open("test.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
{
printf("文件打开失败!n");
return -1;
}
// 调整文件大小为4KB
if (ftruncate(fd, 4096) == -1)
{
printf("文件调整大小失败!n");
close(fd);
return -1;
}
// 将文件映射到内存中
ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED)
{
printf("内存映射失败!n");
close(fd);
return -1;
}
// 写入数据
for (i = 0; i < 4096; i++)
{
ptr[i] = i % 256;
}
// 解除内存映射
if (munmap(ptr, 4096) == -1)
{
printf("内存解除映射失败!n");
close(fd);
return -1;
}
// 关闭文件
close(fd);
return 0;
}
四、可交换内存
可交换内存是一种仅在内存不足时才会被抢占的内存。例如,在Linux中,可交换内存可以通过将页面从物理内存中交换到交换分区或磁盘上来实现。
下面的代码演示了如何创建一个使用可交换内存的进程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i;
char* ptr;
// 使用可交换内存分配10MB内存
ptr = (char*)malloc(1024 * 1024 * 10);
if (ptr == NULL)
{
printf("内存分配失败!n");
return -1;
}
// 写入数据
for (i = 0; i < 1024 * 1024 * 10; i++)
{
ptr[i] = i % 256;
}
// 休眠10秒,等待操作系统将页面写回磁盘
sleep(10);
// 释放内存
free(ptr);
return 0;
}