Andrew Falanga
Andrew Falanga

Reputation: 2484

Unable to map device into memory

I'm attempting to map an sg device, e.g. /dev/sg1, into memory using mmap(). I did not write this code but inherited it. The relevant code is:

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);
}

This code consitently errors out with ENOMEM and perror() prints, "Cannot allocate memory." I've read some earlier posts here from individuals having similar issues with mmap(). As far as I know, I have enough RAM. My system has 6gb (though only 4 should be accessible to this system since is a 32-bit kernel). I saw other posters showing memory stats. Here's what I can find:

[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

The swap space seems to be about normal. From what I recall, it's standard to make the swap space equal to your physical memory size (which it is for a 32-bit kernel).

[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

Some interesting data from sysctl:

vm.max_map_count = 65530
kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.shmmax = 33554432

I'm at a loss for why I'm out of memory. Although I've not used this particular POSIX call before, if I understand it correctly, I'm asking to map a region of approximately 1mb into memory from the device /dev/sg1. It would seem that I should be able to do so. Please help me to understand what I'm missing.

Oh, I also looked at /proc/[PID]/maps for this process when the error occurs but the file is zero length.

Thanks, Andy

Upvotes: 1

Views: 1537

Answers (1)

emou
emou

Reputation: 189

I think you are getting the error not because you're out of address space/memory in your process, but because the mmap call is trying to allocate 1MB of the "reserved buffer" in the kernel, but the default is most likely less than 1MB. From http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/mmap.html:

The 'length' argument should be less than or equal to the size of the reserved buffer associated with 'sg_fd'. If it exceeds the reserved buffer size (after 'length' has been rounded up to a page size multiple) then MAP_FAILED is returned and ENOMEM is placed in errno.

I think you need to set the size of the buffer using the ioctl flag SG_SET_RESERVED_SIZE.

See also: http://sg.danny.cz/sg/s_packet.html#mmap_notes

Upvotes: 2

Related Questions