我正在努力将一些代码从AIX移植到Linux.部分代码使用shmat()系统调用来创建新文件.当SHM_MAP在可写模式下使用时,可以将文件扩展到其原始长度之外(在我的情况下为零):
将文件映射到段时,通过访问段来引用该文件.内存分页系统自动处理物理I/O. 超出文件末尾的引用会导致文件以页面大小的增量进行扩展.文件无法扩展到下一个段边界之外.
(AIX中的"段"是256 MB的地址空间块,"页面"通常是4 KB.)
我会想在Linux上做的是以下几点:
我知道我可以在Windows上使用VirtualProtect函数,PAGE_GUARD内存保护位和结构化异常处理程序执行此操作.Linux上相应的方法是做什么的呢?是否有更好的方法在Linux上实现这种写入扩展功能?
我已经考虑过:
mmap()一些固定的大尺寸,但我无法分辨应用程序代码写入了多少文件mmap() 本身似乎没有提供任何延长支持文件长度的工具当然,我只想对应用程序代码进行最小的更改即可.
这与我曾经做过的家庭作业非常相似.基本上我有一个"页面"列表和一个"框架"列表,以及相关信息.使用SIGSEGVI会捕获故障并根据需要更改内存保护位.我将包含您可能觉得有用的部分.
int w_create_mapping(size_t size, void **addr)
{
*addr = mmap(NULL,
size * w_get_page_size(),
PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
0
);
if (*addr == MAP_FAILED) {
perror("mmap");
return FALSE;
}
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
int w_set_exception_handler(w_exception_handler_t handler)
{
static struct sigaction sa;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGSEGV);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sa, &previous_action) < 0)
return FALSE;
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
static void fault_handler(int signum, siginfo_t *info, void *context)
{
void *address; /* the address that faulted */
/* Memory location which caused fault */
address = info->si_addr;
if (FALSE == page_fault(address)) {
_exit(1);
}
}
Run Code Online (Sandbox Code Playgroud)
int w_protect_mapping(void *addr, size_t num_pages, w_prot_t protection)
{
int prot;
switch (protection) {
case PROTECTION_NONE:
prot = PROT_NONE;
break;
case PROTECTION_READ:
prot = PROT_READ;
break;
case PROTECTION_WRITE:
prot = PROT_READ | PROT_WRITE;
break;
}
if (mprotect(addr, num_pages * w_get_page_size(), prot) < 0)
return FALSE;
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
由于团队可能会再次使用相同的作业,因此我无法公开全部使用.
| 归档时间: |
|
| 查看次数: |
2991 次 |
| 最近记录: |