无法将设备映射到内存

时间:2013-08-26 22:06:57

标签: c linux posix mmap

我正在尝试映射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这个过程。

谢谢, 安迪

1 个答案:

答案 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设置缓冲区的大小。

另见: http://sg.danny.cz/sg/s_packet.html#mmap_notes