免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123
最近访问板块 发新帖
楼主: kouu

通过mmap读文件, 进程收到SIGBUS而退出 [复制链接]

论坛徽章:
0
发表于 2010-04-24 13:10 |显示全部楼层
sorry,非常汗颜了,做了试验后,确实发现我错了

如LZ所说:
那么在本例中,既然没有写,MAP_PRIVATE 和 MAP_SHARED 也就没有什么区别了。

确实,这里对于只读取的来说,对于只有读取需求的情况下,MAP_PRIVATE和MAP_SHARED确实没有区别了

这里想起,主要是内核从哪个版本开始,对于普通文件,开始不支持VM_DENYWRITE参数
后续的版本,VM_DENYWRITE只对可执行文件有效了,对普通文件,mmap后,并不能阻止其他文件已写的方式打开文件(lz可以试验下,cp覆盖一个你正在运行的可执行文件,肯定会报FILE BUSY的错误)

LZ和Godbach兄的覆盖文件,都是因为用到了O_TRUNC参数,而内核中O_TRUNC参数的实现,会把相应文件的页缓存全部清除,及把页缓存对应的mmap全部unmap掉
LZ可以试验下,自己open下tmp.ttt文件,不带O_TRUNC,然后再往里面塞东西,不要截断文件大小,就不会对正在mmap读取的进程产生威胁了

论坛徽章:
0
发表于 2010-04-24 13:13 |显示全部楼层
以前追踪过O_TRUNC

O_TRUNC跟踪:
从fs/open.c->filp_open()开始:O_TRUNC就在flags中
struct file *filp_open(const char * filename, int flags, int mode) ->
   open_namei(filename, namei_flags, mode, &nd)                    ->
       may_open(nd, acc_mode, flag)                                ->在这个函数看到,对于O_TRUNC,会比其他情况下,多调用一个do_truncate()
         do_truncate(dentry, 0)                                    ->第二个参数就是0了
         notify_change(dentry, &newattrs)                          -> 长度为0,存储在newattrs中
             inode_setattr(inode, attr)                            ->设置inode的相关属性了
                vmtruncate(inode, attr->ia_size)                   ->进行vm的截断操作了。
vmtruncate()是这次的重点了,贴出注视和最关键的三句:
/*
* Handle all mappings that got truncated by a "truncate()"
* system call.
*
* NOTE! We have to be ready to update the memory sharing
* between the file and the memory map for a potential last
* incomplete page.  Ugly, but necessary.
*/
int vmtruncate(struct inode * inode, loff_t offset)//这里offset为0,从0开始截断,就全截了,相当清空一次inode的所有页缓存,
{
        struct address_space *mapping = inode->i_mapping;//获取的就是inode的页缓存结构,后两个函数有很好的注释
        unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
        truncate_inode_pages(mapping, offset);
}

unmap_mapping_range()的注视:
/**
* unmap_mapping_range - unmap the portion of all mmaps
* in the specified address_space corresponding to the specified
* page range in the underlying file.
* @address_space: the address space containing mmaps to be unmapped.
* @holebegin: byte in first page to unmap, relative to the start of
* the underlying file.  This will be rounded down to a PAGE_SIZE
* boundary.  Note that this is different from vmtruncate(), which
* must keep the partial page.  In contrast, we must get rid of
* partial pages.
* @holelen: size of prospective hole in bytes.  This will be rounded
* up to a PAGE_SIZE boundary.  A holelen of zero truncates to the
* end of the file.
* @even_cows: 1 when truncating a file, unmap even private COWed pages;
* but 0 when invalidating pagecache, don't throw away private data.
*/
void unmap_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen, int even_cows)
{
}

truncate_inode_pages()的注视:
/**
* truncate_inode_pages - truncate *all* the pages from an offset
* @mapping: mapping to truncate
* @lstart: offset from which to truncate
*
* Truncate the page cache at a set offset, removing the pages that are beyond
* that offset (and zeroing out partial pages).
*
* Truncate takes two passes - the first pass is nonblocking.  It will not
* block on page locks and it will not block on writeback.  The second pass
* will wait.  This is to prevent as much IO as possible in the affected region.
* The first pass will remove most pages, so the search cost of the second pass
* is low.
*
* When looking at page->index outside the page lock we need to be careful to
* copy it into a local to avoid races (it could change at any time).
*
* We pass down the cache-hot hint to the page freeing code.  Even if the
* mapping is large, it is probably the case that the final pages are the most
* recently touched, and freeing happens in ascending file offset order.
*
* Called under (and serialised by) inode->i_sem.
*/
void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
{
}

论坛徽章:
0
发表于 2010-04-24 21:17 |显示全部楼层
VM_DENYWRITE只对可执行文件有效了,对普通文件,mmap后,并不能阻止其他文件已写的方式打开文件(lz可以试验下,cp覆盖一个你正在运行的可执行文件,肯定会报FILE BUSY的错误)
augustusqing 发表于 2010-04-24 13:10


呵呵, 之前一直有注意到这个现象, 本来说要找下原因的, 一直忘记... 今天经augustusqing兄这么一指点, 原来如此... 非常感谢~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP