做招聘求职网站,写一个app需要多少钱,建筑工程自我鉴定300字,2008vps做网站SIGBUS
SIGBUS是一个在Unix-like操作系统中的信号#xff0c;它通常表示非法访问内存#xff0c;而这种非法访问的原因与常见的SIGSEGV#xff08;段错误#xff09;有所不同。以下是可能导致SIGBUS的常见情况#xff1a; 未对齐的内存访问#xff1a;某些硬件平台要求数…SIGBUS
SIGBUS是一个在Unix-like操作系统中的信号它通常表示非法访问内存而这种非法访问的原因与常见的SIGSEGV段错误有所不同。以下是可能导致SIGBUS的常见情况 未对齐的内存访问某些硬件平台要求数据如整数或浮点数在内存中以特定的地址对齐如2或4的倍数。如果程序试图在这些平台上访问未对齐的数据就可能收到SIGBUS。 映射文件I/O问题使用mmap()系统调用映射文件到内存并尝试访问文件后面的内容可能会产生SIGBUS。例如如果文件在被映射后被截断那么当程序尝试访问被截断部分的数据时就会得到SIGBUS。 硬件故障虽然不常见但内存损坏或其他硬件问题有时可能导致SIGBUS。 堆栈溢出在某些系统上尝试超出预分配的堆栈空间可能会导致SIGBUS而不是更常见的SIGSEGV。 访问不存在的内存页如果程序尝试访问一个标记为不存在的内存页那么可能会得到SIGBUS。
应对SIGBUS的策略与处理其他运行时错误类似需要检查代码以找出可能的问题并使用调试工具帮助诊断。 映射文件I/O问题
当使用 mmap() 系统调用将文件映射到进程的内存地址空间时基本上是在告诉操作系统“请将这个文件的内容让我像内存一样直接访问它。” 实际的文件内容并不会立即加载到物理内存中相反操作系统会设置页面表条目以反映文件的内容然后只在实际访问这些地址时才从磁盘加载内容。这被称为按需分页demand paging。
考虑以下场景
使用 mmap() 映射了一个文件长度为100字节。接着另一个进程或可能是同一个进程的另一个部分截断该文件使其长度变为50字节。现在我们的进程尝试访问映射中的第60字节。
由于该字节已经不再文件中操作系统不知道应该返回什么。这时它会发送 SIGBUS 信号给进程。这样进程就知道它试图访问的数据不再存在。
为什么不使用 SIGSEGV通常用于无效的内存访问呢因为这不是一个真正的段错误。地址本身是有效的但由于文件被截断该地址不再反映任何文件内容。为了区分这两种情况操作系统选择发送 SIGBUS。
如何处理这种情况通常我们需要确保在使用 mmap() 映射的文件不会在需要它时被其他进程或线程截断。如果这种情况可能发生我们的程序需要能够适当地处理 SIGBUS或者至少在这种情况下能够优雅地失败。
在UNIX和类UNIX系统上ftruncate() 函数经常与文件系统上的空洞holes相关联。下面我们来详细了解一下。 空洞文件Sparse File
空洞文件sparse file是一个文件其中有些部分没有分配存储空间通常这些部分的内容都被视为零。这些未分配空间的部分就是所谓的“空洞”。这意味着如果我们有一个大部分由零组成的非常大的文件只为其中的非零部分分配磁盘空间而为零部分不分配那么该文件在磁盘上实际占用的空间会小于其表面大小。文件系统知道这些“空洞”并会在需要时适当地处理它们。
使用ftruncate()创建空洞文件
ftruncate() 函数可以调整已打开文件的大小。如果我们使用 ftruncate() 将文件扩展到比其当前大小更大的大小新添加的部分不会有实际磁盘空间与之关联从而形成一个空洞。
例如考虑以下的程序段
int fd open(sparsefile, O_RDWR | O_CREAT, 0666);
ftruncate(fd, 1024 * 1024); // 将文件大小设置为1MB
close(fd);在上面的代码执行后sparsefile 的大小会报告为1MB但它在磁盘上可能实际上占用的空间远远小于这个数值因为文件中的内容全都是未初始化的并被视为零。这样文件系统就为我们创建了一个空洞文件。
为什么要使用空洞文件 节省空间特别是在处理大量包含零的数据时使用空洞文件可以节省大量磁盘空间。 快速文件创建如果我们知道将创建一个非常大的文件但一开始只需要使用其中的一小部分使用空洞文件可以避免预先分配大量不必要的磁盘空间。
需要注意的是不是所有的文件系统都支持空洞文件但许多现代文件系统如ext3、ext4和xfs都支持。