使用MMAP将输出打印到文件

时间:2017-05-04 10:18:12

标签: c file mmap

我有一个打印出树的函数printtree。 我搜索了互联网上的很多地方,我发现mmap是分配内存和写入文件的好方法。

我想使用mmap将printtree的内容打印到文件中。我是第一次学习mmap而且我不知道该怎么做。

printtree()如下:

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

在我的main.c中,我正在尝试这个:

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

1 个答案:

答案 0 :(得分:1)

基本上,地图的初始化看起来很好(即,对mmap的调用)。您只需要确保映射文件足够大,可能在调用mmap之前扩展它。查看my answer here以获取有关如何确保内存映射文件足够大的其他信息。

您需要做的下一步是通过写入内存映射文件来替换函数printf中的printtree调用。

为此,您可以将文件的内存映射传递给函数,类似于以下示例代码。它使用指针算术处理类似于char[]的内存映射文件:

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