UNIX环境高级编程:存储映射I/O(mmap函数)
31-38 读出内存映射区中每个页面的首字节和尾字节,并输出他们的值。我们预期这些值全为0.同时把每个页面的这两个字节设置为1,。我们预期某个引用会最终引发一个信号,它将终止程序。当for循环结束时,我们输出下一页的首字节,并预期这会失败。 运行结果: huangcheng@ubuntu:~$ ls -l test ls: 无法访问test: 没有那个文件或目录 huangcheng@ubuntu:~$ ./a.out test 5000 5000 PAGESIZE = 4096 ptr[0] = 0 ptr[4095] = 0 ptr[4096] = 0 ptr[8191] = 0 段错误 huangcheng@ubuntu:~$ ls -l test -rwxr-xr-x 1 huangcheng huangcheng 5000 2013-07-09 15:48 test huangcheng@ubuntu:~$ od -b -A d test 0000000 001 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 0000016 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 * 0004080 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 001 0004096 001 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 0004112 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 * 0004992 000 000 000 000 000 000 000 040 0005000 页面大小为4096字节,我们能够读完整的第2页(下标为4096-8191),但是访问第3页时(下标为8192)引发SIGSEGV信号,shell将它输出成"Segmentation Fault(分段障)"。尽管我们把ptr[8191]设置成1,它也不写到test文件中,因而该文件的大小仍然是5000.内核允许我们读写最后一页中映射区以远部分(内核的内存保护是以页面为单位的)。但是我们写向这部分扩展区的任何内容都不会写到test文件中。设置成1的其他3个字节(下标分别为0,4905和4906)复制回test文件,这一点可使用od命令来验证。(-b选项指定以八进制数输出各个字节,-A d选项指定以十进制数输出地址。) 我们仍然能访问内存映射区以远部分,不过只能在边界所在的那个内存页面内(下标为5000-8191)。访问ptr[8192]将引发SIGSEGV信号,这是我们预期的。 现在我们把内存映射区大小(15000字节)指定成大于文件大小(5000字节)。 huangcheng@ubuntu:~$ ./a.out test 5000 15000 PAGESIZE = 4096 ptr[0] = 0 ptr[4095] = 0 ptr[4096] = 0 ptr[8191] = 0 总线错误 huangcheng@ubuntu:~$ ls -l test -rwxr-xr-x 1 huangcheng huangcheng 5000 2013-07-09 16:00 test 其结果与先前那个文件大小等于内存映射区大小(都是5000字节)的例子类似。本例子引发SIGBUS信号(其shell输出为"Bus Error(总线出错)"),前一个例子则引发SIGSEGV信号。两者的差别是,SIGBUS意味着我们是在内存映射区访问的,但是已超出了底层支撑对象的大小。上一个例子中的SIGSEGV则意味着我们已在内存映射区以远访问。可以看出,内核知道被映射的底层支撑对象(本例子中为文件test)的大小,即使我们访问不了该对象以远的部分(最后一页上该对象以远的那些字节除外,他们的下标为5000-8191)。 (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |