1

I have a function printtree which prints out a tree. I searched on many places on the internet and I found that mmap would be a good way to allocate memory and write into a file.

I want to use mmap to print the contents of the printtree into a file. I am learning mmap for the first time and I am not sure how to do it.

printtree() is as follows:

void printtree(struct Node *root, int indent)
{
int i;
        if(root != NULL)
        {
                printtree(root->right,indent + 1);
                for(i = 0;i<indent;i++)
                {
                        printf("\t");
                }
                printf("%d\n",root->key);
                printtree(root->left,indent + 1);
        }
}

In my main.c, I am trying this:

struct  Node *root = NULL;
        int     info ;
        int     *arr;
        int     choice;
        int     fd;
        int     mode = 0x0777;
        struct  stat mystat;
        void    *p;
        int     size;
        FILE    *file_ptr;
        if (argc != 2){ printf("Error\nIncorrect number of arguments\n");exit(1);}
        if (access(argv[1],F_OK) != -1)
        {
                fd = open(argv[1],O_RDWR);

              if (fd == -1)
                {
                        perror("open");
                        exit(1);
                }
                if(fstat(fd, &mystat)<0)
                {
                        perror("fstat");
                        close(fd);
                        exit(1);
                }
                p = mmap(0,mystat.st_size , PROT_READ | PROT_WRITE,
                         MAP_SHARED ,fd,0);
                if(p == MAP_FAILED)
                {
                        perror("mmap");
                        close(fd);
                        exit(1);
                }
while(1)
        {
        printf("1.Insert\n");
        printf("2.Delete\n");
        printf("3.Lookup\n");
        printf("4.Print\n");
        printf("5.Quit\n");
        printf("Enter your choice : ");

        scanf("%d",&choice);
        switch(choice)
        {
        case 1:
            printf("Enter the value to be inserted : ");
            scanf("%d", &info);
                //write(fd,&info,36);
           if( (root = insert(root,info)) == 0){}
        else

            break;
        case 2:
                printf("Enter the value you want to delete : ");
                scanf("%d",&info);
                root = deleteNode(root,info);
                break;
        case 4:
                printtree(root,0);
                break;
                //printf("%s",arr[0]);
                printf("\n");
            break;
        case 5:
                close(fd);
            exit(1);
        case 3:
                printf("Enter the element you want to look for : ");
                scanf("%d",&info);
                Search(root,info);
                break;
        case 6:
                printtree(root,0);
                break;
  default:
  printf("Wrong choice\n");
        }
        }
}
Vaibhav Borkar
  • 171
  • 2
  • 12

1 Answers1

1

Basically, the initialization of you map looks good (i.e., the call to mmap). You just have to make sure that the mapped file is large enough, probably expanding it before your call to mmap. Have a look at my answer here to get additional information on how to ensure that the memory mapped file is big enough.

The next step you have to do is to replace calls to printf in your function printtree by writes to you memory mapped file.

To do so, you may pass your file's memory map to your function, similar to the following example code. It handles the memory mapped file similar to a char[], using pointer arithmetics:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h> 
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

typedef struct Node {
    int key;
    struct Node* left;
    struct Node* right;
} Node;

void printtree(Node* root, int indent, char** mapped_file) {    
    if(root != NULL) {
        printtree(root->left, indent + 1, mapped_file);

        int i;
        for(i = 0; i < indent; i++) {
            **mapped_file = '\t';
            (*mapped_file)++;
        }
        char str[16];
        sprintf(str, "%d\n", root->key);
        memcpy(*mapped_file, str, strlen(str));
        *mapped_file+=strlen(str);

        printtree(root->right, indent + 1, mapped_file);
    }
}

void main(int argc, const char* argv[] ) {
    Node* root = (Node*) malloc( sizeof(Node));

    root->key = 1;
    root->left = (Node*) malloc( sizeof(Node));
    root->left->key = 2,
    root->left->left = NULL;
    root->left->right = NULL;
    root->right = (Node*) malloc( sizeof(Node));
    root->right->key = 3;
    root->right->left = (Node*) malloc( sizeof(Node));
    root->right->left->key = 4;
    root->right->left->left = NULL;
    root->right->left->right = NULL;
    root->right->right = NULL;

    printf("%s\n", argv[1]);
    int fd = open(argv[1], O_RDWR);

    if (fd == -1) {
        perror("open");
        exit(1);
    }

    struct  stat mystat;
    if(fstat(fd, &mystat) < 0) {
        perror("fstat");
        close(fd);
        exit(1);
    }

    char* mapped_file = (char*) mmap(0, mystat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(mapped_file == MAP_FAILED) {
        perror("mmap");
        close(fd);
        exit(1);
    }

    printtree(root, 0, &mapped_file);
}
Community
  • 1
  • 1
Markus Weninger
  • 11,931
  • 7
  • 64
  • 137