开发者

Is it possible to map just part of a file using mmap?

I have a input file which has a header like this:

P6\n
width\n
height\n
depth\n

and then a struct is writen, pixel*, into this file, which is going to be mapped.

So, I want to skip the header and make my mmap function return the ptr to that structure. How can I do this? with lseek perhaps? Could you please exemplify?

I will leave part of my code here:

printf("Saving header to output file\n");
    if (writeImageHeader(h, fpout) == -1) {
        printf("Could not write to output file\n");
        return -1;
    }

    last_index = (int)ftell(fpout);
    //printf("offset after header= %d\n",last_index);

    //alloc mem space for one row (width * size of one pixel struct)
    row = malloc(h->width * sizeof (pixel));

    /*Create a copy of the original image to the output file, which will be inverted*/
    printf("Starting work\n");
    for (i = 0; i < h->height; i++) {
        printf("Reading row... ");
        if (getImageRow(h->width, row, fpin) == -1) {
            printf("Error while reading row\n");
        }
        printf("Got row %d || ", (i + 1));

        printf("Saving row... ");
        if (writeRow(h->width, row, fpout) == -1) {
            printf("Error while reading row\n");
        }
        printf("Done\n");
    }


    /*Open file descriptor of the ouput file.
     * O_RDWR -  Read and Write operations both permitted
     * O_CREAT - Create file if it doesn't already exist
     * O_TRUNC - Delete existing contents of file*/
    if ((fdout = open(argv[2], O_RDWR, FILE_MODE)) < 0) {
        fprintf(stderr, "Can't create %s for writing\n", argv[2]);
        exit(1);
    }

    /*Get size of the output file*/
    if (fstat(fdout, &sbuf) == -1) {
        perror("Stat error ---------->\n");
        exit(1);
    }
    //printf("Size of output file: %d\n",(int)sbuf.st_size);

    /*Maps output file to memory*/
    if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0)) == (caddr_t) (-1)) {
        perror("Error mmaping");
        exit(EXIT_FAI开发者_高级运维LURE);
    }

As you see, right now my ppm image is mapped to char* data, but I want to skip the header and map just to the pixel* part.

Here's my code with the suggestion of using 2 pointers, a char* from mmap and another one equals that + offset.

main

c functions

header

makefile


If you read the man page for mmap, you wil find that its final parameter is off_t offset. The description:

... continuing or at most 'len' bytes to be mapped from the object described by 'fd', starting at byte offset 'offset'.

I suspect if you pass your offset in as that parameter, it will do what you want.


You can't if the amount you need to skip is less than the system page size, since offset must be a multiple of the page size on some systems.


You just need to keep 2 pointers - the pointer to the start of the mmap'd block, and the pointer to the start of the data you want inside there. As in:

unsigned char *block = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0);
unsigned char *data = block + offset;

where offset is the offset in the file to the data you want.


So, from what I understand, can I do something like this?

off_t offset_after_header = lseek(fdout, last_index, SEEK_SET);
    printf("Pointer is on %d\n",(int)offset_after_header);
    /*Maps output file to memory*/
    if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, offset_after_header)) == (caddr_t) (-1)) {
        perror("Error mmaping");
        exit(EXIT_FAILURE);
    }

and, from that, I could map my file to whatever type I want, in this case the pixel*

If this is ok, what cautions should I take? For example, like those Ignacio Vazquez-Abrams said


Um, you did notice the 'offset' parameter that you are supplying with a zero? Assuming you know the absolute offset of what you want, you pass it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜