mmap()ing again ... I've looked around in kernel and bttv2 code while looking for a nice way to handle v4l2 mappings in bttv. Using page offsets as magic cookie isn't a good idea. The VM will take the offset as real offset and calculates a new value for it if a application does a partial unmap(). Which in turn can lead to *ahem* intresting effects like this one: bttv0: Granting 4 buffers. bttv0: vma_close called on buffer 1 (refcount -1) IHMO there is no way around using the offset as normal offset: Drivers should make sure that the mappings do not overlap, i.e. buf[n].offset + buf[n].size <= buf[n+1].offset There is also vma->vm_private_data which can be used by the drivers to keep track of the mappings. Gerd --------- [ mmap.c ] ----------------------------------------- #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <linux/videodev.h> #define BUFS 4 struct v4l2_format fmt = { type: V4L2_BUF_TYPE_CAPTURE, fmt: { pix: { width: 320, height: 240, depth: 32, pixelformat: V4L2_PIX_FMT_BGR32 }, }, }; struct v4l2_requestbuffers req = { count: BUFS, type: V4L2_BUF_TYPE_CAPTURE, }; struct v4l2_buffer bufs[BUFS]; int main() { unsigned char *map; int fd,i; fd = open("/dev/video0",O_RDWR); if (-1 == fd) { perror("open /dev/video0"); exit(1); } if (-1 == ioctl(fd,VIDIOC_S_FMT,&fmt)) { perror("ioctl VIDIOC_S_FMT"); exit(1); } if (-1 == ioctl(fd,VIDIOC_REQBUFS,&req)) { perror("ioctl VIDIOC_REQBUFS"); exit(1); } for (i = 0; i < BUFS; i++) { bufs[i].index = i; bufs[i].type = V4L2_BUF_TYPE_CAPTURE; if (-1 == ioctl(fd,VIDIOC_QUERYBUF,&bufs[i])) { perror("ioctl VIDIOC_QUERYBUF"); exit(1); } fprintf(stderr,"%d: offset=0x%x length=%d\n", i,bufs[i].offset,bufs[i].length); } fprintf(stderr,"mmap\n"); map = mmap(NULL, bufs[0].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufs[0].offset); if (-1 == (int)map) { perror("mmap"); exit(1); } fprintf(stderr,"munmap\n"); if (-1 == munmap(map, (bufs[1].offset - bufs[0].offset))) { perror("munmap"); exit(1); } fprintf(stderr,"done\n"); exit(0); }