我正在尝试映射sg设备,例如/ dev / sg1,使用mmap()进入内存。我没有编写这段代码但继承了它。相关代码是:
uint8_t *pRegion = NULL;
int fd = open("/dev/sg1", O_RDWR | O_NONBLOCK);
pRegion = mmap(0, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if((void*)-1 == pRegion) {
perror("mmap error");
exit(1);
}
此代码在ENOMEM和perror()打印时出现错误,“无法分配内存”。我在这里读过一些与mmap()有类似问题的人的帖子。据我所知,我有足够的内存。我的系统有6GB(尽管这个系统只有4个可以访问,因为它是一个32位内核)。我看到其他海报显示记忆统计数据。这是我能找到的:
[andy@andylnx gcc_bin-32]$ free -m
total used free shared buffers cached
Mem: 6077 307 5770 0 30 102
-/+ buffers/cache: 174 5903
Swap: 4095 0 4095
交换空间似乎正常。根据我的记忆,将交换空间等于物理内存大小(适用于32位内核)是标准的。
[andy@andylnx gcc_bin-32]$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 47487
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 20000
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
来自sysctl的一些有趣数据:
vm.max_map_count = 65530
kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.shmmax = 33554432
我为什么失去记忆而感到茫然。虽然之前我没有使用过这个特定的POSIX调用,但如果我理解正确的话,我会要求将大约1mb的区域映射到设备/ dev / sg1的内存中。似乎我应该能够这样做。请帮助我理解我错过的东西。
哦,当错误发生但文件长度为零时,我也查看了/ proc / [PID] / maps这个过程。
谢谢, 安迪
答案 0 :(得分:1)
我认为你得到的错误不是因为你的进程中没有地址空间/内存,而是因为mmap调用试图分配1MB的"保留缓冲区"在内核中,但默认值很可能小于1MB。从 http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/mmap.html:
'长度'参数应小于或等于与' sg_fd'相关联的保留缓冲区的大小。如果它超过了保留的缓冲区大小(在'长度'已经四舍五入到页面大小倍数之后),则返回MAP_FAILED并将ENOMEM放在errno中。
我认为您需要使用ioctl标志SG_SET_RESERVED_SIZE设置缓冲区的大小。