如何解决ftruncate() 总是精确的吗?
我正在尝试 ftruncate
一个特定长度的共享内存对象。例如,我想使用以下代码段将其长度设置为 1 个字节:
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main() {
struct stat fd_stat;
int fd;
fd = shm_open("NAME",O_RDWR | O_CREAT,S_IRUSR | S_IWUSR);
fstat(fd,&fd_stat);
printf("Size before: %lld\n",fd_stat.st_size);
ftruncate(fd,1);
fstat(fd,&fd_stat);
printf("Size after: %lld\n",fd_stat.st_size);
}
在 Ubuntu 20.04 中打印:
Size before: 0
Size after: 1
这是我期望的输出。
但是,在 macOS X Big Sur 中,我得到:
Size before: 0
Size after: 4096
如您所见,它似乎将大小扩展到页面大小。
ftruncate
Linux man page 读作:
truncate() 和 ftruncate() 函数导致由 path 命名或由 fd 引用的常规文件被截断为大小精确长度字节。。 >
尽管如此,POSIX specification 并不具体(双关语):
如果 fildes 引用常规文件,则 ftruncate() 函数将导致文件的大小被截断为长度。 [...] 如果之前的文件小于这个大小,ftruncate() 应该增加文件的大小。
这是否意味着 ftruncate
总是将长度设置为恰好指定的字节数?如果确实如此,则意味着 macOS X Big Sur 不完全符合 POSIX(即使它已被证明如此)。如果没有,我如何保证它会将 fd
截断为我想要的大小?
解决方法
简而言之,您无法保证您的共享内存对象的大小正好符合您要求的 ftruncate
大小。这是因为,正如@user3386109 所说,“您引用的 POSIX 规范部分以“If fildes 引用常规文件””开头。
如果你想把自己限制在任意长度,你总是可以使用一个辅助变量来跟踪你假设的大小(即使实际大小可能实际上不同,毕竟这可能并不那么重要)。您的代码如下所示:
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main() {
struct stat fd_stat;
int fd;
off_t fd_size;
fd = shm_open("NAME",O_RDWR | O_CREAT,S_IRUSR | S_IWUSR);
fstat(fd,&fd_stat);
printf("Size before: %lld\n",fd_stat.st_size);
fd_size = 1;
ftruncate(fd,fd_size);
fstat(fd,&fd_stat);
printf("Actual size: %lld\n",fd_stat.st_size);
printf("Perceived size: %lld\n",fd_size);
}
最重要的是,如果您想在不同进程之间共享大小,可以将 fd_size
转换为 mmap
ed 共享内存对象,以跟踪您假设它跨越的大小他们都是。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。