免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1341 | 回复: 0
打印 上一主题 下一主题

如何理解memory-mapped [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-05-07 19:13 |只看该作者 |倒序浏览
如下这段代码编译成功后,使用如下命令:

add lastname
del lastname
find lastname
list
quit


  1. /*
  2. * This program implements a simple address book.  It is implemented as a
  3. * binary tree inside a memory-mapped file so that it can survive
  4. * between executions of the program.
  5. */

  6. #include <stdio.h>;
  7. #include <string.h>;
  8. #include <stdlib.h>;
  9. #include <errno.h>;

  10. /* Header record placed at the start of the storage area.  It describes the
  11.    free parts and contains the root of the BST. */
  12. struct header
  13. {
  14.         int nunused;        /* Number of unused blocks. */
  15.         int firstun;        /* Offset of the first unused block. */
  16.         int firstfree;        /* First block of the freelist. */
  17.         int root;        /* Root of the tree. */
  18. };
  19. /* Note that nodes on the free list, when the exist, are linked into a single
  20.    linked list using the left pointer of each node, and ignoring the right
  21.    pointer. */

  22. /* Form of the tree nodes. */
  23. struct node
  24. {
  25.         char lname[20];                /* First name. */
  26.         char fname[20];                /* Last name. */
  27.         char addr[40];                /* Address. */
  28.         char phone[14];                /* Phone number. */
  29.         int left, right;        /* Tree links. */
  30. };
  31. /* Note that left and right are integers.  They represent the byte offset
  32.    of the left and right nodes relative to the start of the header. */

  33. /* Macros to convert between offsets relative to the base of the area, and
  34.    pointers to node structures. */
  35. #define OFFSET_TO_PTR(base, offset)        \
  36.         ((struct node *)((char *)(base) + (offset)))
  37. #define PTR_TO_OFFSET(base, ptr)        \
  38.         ((char *)(ptr) - (char *)(base))

  39. /* Location record returned by the tree search function. */
  40. struct lrec {
  41.         int *plink;                /* Where the node found is specified. */
  42.         struct node *node;        /* The node found, or NULL. */
  43. };

  44. /* Program name. */
  45. char *pname;

  46. /* Number of node records in the storage area.  Any portion of them may be
  47.    marked free. */
  48. #define NREC 1000

  49. /*
  50. * Store a new header to inialize the space the first time.
  51. */
  52. void format(char *area)
  53. {
  54.         struct header *header = (struct header *)area;
  55.        
  56.         /* Fill in the header information. */
  57.         header->;nunused = NREC;                /* All records initially unused. */
  58.         header->;firstun =                 /* The first follows immediately. */
  59.                 sizeof(struct header);
  60.         header->;firstfree = 0;                /* The free list is empty. */
  61.         header->;root = 0;                /* The tree is empty. */
  62. }

  63. /*
  64. * Free list operations.
  65. */

  66. /* Get a free node.  The links are cleared. */
  67. struct node *getnode(struct header *head)
  68. {
  69.         struct node *retval;        /* Return value. */

  70.         /* See if there is a node on the free list. */
  71.         if(head->;firstfree != 0) {
  72.                 /* Use it. */
  73.                 retval = OFFSET_TO_PTR(head, head->;firstfree);
  74.                 head->;firstfree = retval->;left;
  75.         }
  76.         else
  77.                 /* See if there is a node which has never been used. */
  78.                 if(head->;nunused)
  79.                 {
  80.                         /* Use it. */
  81.                         retval = OFFSET_TO_PTR(head, head->;firstun);
  82.                         head->;firstun += sizeof(struct node);
  83.                         --head->;nunused;
  84.                 }
  85.                 else
  86.                 {
  87.                         /* Cannot allocate.  Bye. */
  88.                         fprintf(stderr, "Allocation failed.\n");
  89.                         exit(10);
  90.                 }


  91.         retval->;left = retval->;right = 0;
  92.         return retval;
  93. }

  94. /* Add a node to the free list. */
  95. void freenode(struct node *node, struct header *head)
  96. {
  97.         node->;left = head->;firstfree;
  98.         head->;firstfree = PTR_TO_OFFSET(head, node);
  99. }

  100. /* Search the BST for a key.  It takes the pointer to the control area, and
  101.    returns a locator record which contains enough info to delete, insert, or
  102.    just access the node with the indicated key. */
  103. struct lrec locate(struct header *head, char *key)
  104. {
  105.         int *locator = &head->;root;

  106.         while(1)
  107.         {
  108.                 int cmp;                /* Comparison result. */
  109.                 struct node *node =         /* Present node of scan. */
  110.                         OFFSET_TO_PTR(head, *locator);

  111.                 /* See if we reached a leaf. */
  112.                 if(*locator == 0)
  113.                 {
  114.                         struct lrec retval = { locator, NULL };
  115.                         return retval;
  116.                 }

  117.                 /* See if we have found the node. */
  118.                 cmp = strcmp(key, node->;lname);
  119.                 if(cmp == 0)
  120.                 {
  121.                         /* Found. */
  122.                         struct lrec retval = { locator, node };
  123.                         return retval;
  124.                 }
  125.                 else if(cmp < 0)
  126.                         /* The key was less than the node. */
  127.                         locator = &(node->;left);
  128.                 else
  129.                         /* The key was greater than the node. */
  130.                         locator = &(node->;right);
  131.         }
  132. }

  133. /* Insert the node n into the tree, using the loc information returned by
  134.    locate.  Obviously, if insert is passed a bad value for loc, it can
  135.    corrupt the tree by inserting in the wrong place. */
  136. insert(struct header *header, struct node *n, struct lrec loc)
  137. {
  138.         n->;right = 0;
  139.         n->;left = *loc.plink;
  140.         *loc.plink = PTR_TO_OFFSET(header, n);
  141. }

  142. /*
  143. * Delete the node described by loc.
  144. */
  145. delete(struct header *head, struct lrec loc)
  146. {
  147.         struct node *node = loc.node;
  148.         if(node == NULL) return;

  149.         /* Check the cases. */
  150.         if(node->;left == 0)
  151.                 /* Can connect up to right. */
  152.                 *loc.plink = node->;right;
  153.         else if(node->;right == 0)
  154.                 /* Can connect to left. */
  155.                 *loc.plink = node->;left;
  156.         else
  157.         {
  158.                 /* Two children.  Must find a leaf. */
  159.                 struct node *surr;                /* Single child repl. node */
  160.                 int surroff;                        /* Offset of surr. */
  161.                 int *scan = &node->;left;        /* Scanner to find it. */

  162.                 while(1)
  163.                 {
  164.                         int rlink = OFFSET_TO_PTR(head, *scan)->;right;
  165.                         if(rlink == 0) break;
  166.                         scan = &OFFSET_TO_PTR(head, *scan)->;right;
  167.                 }

  168.                 /* Get information about the replacement. */
  169.                 surroff = *scan;
  170.                 surr = OFFSET_TO_PTR(head, surroff);

  171.                 /* Detach the replacement. */
  172.                 *scan = surr->;left;

  173.                 /* Link it in place of the doomed node. */
  174.                 surr->;left = node->;left;
  175.                 surr->;right = node->;right;
  176.                 *loc.plink = surroff;
  177.         }

  178.         /* Return the node to the free list. */
  179.         freenode(node, head);
  180. }

  181. /* Print the tree. */
  182. prtree_r(struct header *head, struct node *node)
  183. {
  184.         if(node->;left != 0)
  185.                 prtree_r(head, OFFSET_TO_PTR(head, node->;left));
  186.         printf("%s\n", node->;lname);
  187.         if(node->;right != 0)
  188.                 prtree_r(head, OFFSET_TO_PTR(head, node->;right));
  189. }
  190. prtree(struct header *head)
  191. {
  192.         if(head->;root == 0)
  193.                 printf("No entries.\n");
  194.         else
  195.                 prtree_r(head, OFFSET_TO_PTR(head, head->;root));
  196. }

  197. /*
  198. * Prompt and get an answer, and place it into place, which is of size size.
  199. */
  200. void prompt(char *p, char *place, int size)
  201. {
  202.         char buf[200];                /* Temp storage for response. */
  203.         int end;                /* Loc. of last char. */

  204.         printf("%s: ", p);
  205.         fgets(buf, sizeof buf, stdin);
  206.         end = strlen(buf) - 1;
  207.         if(buf[end] == '\n') buf[end] = 0;
  208.         strncpy(place, buf, size - 1);
  209.         place[size - 1] = 0;
  210. }

  211. /*
  212. * Run the command interpreter.
  213. */
  214. void commands(char *area)
  215. {
  216.         struct header *head = (struct header *)area;
  217.         char buf[200];

  218.         printf("addrs>; ");
  219.         for(;fgets(buf, sizeof buf, stdin) != NULL; printf("addrs>; "))
  220.         {
  221.                 char cmd[21], lname[21];
  222.                 int ret = sscanf(buf, "%20s %20s", cmd, lname);
  223.                 if(ret < 1) continue;

  224.                 if(strcmp(cmd, "add") == 0)
  225.                 {
  226.                         /* Return value of locate. */
  227.                         struct lrec loc;

  228.                         /* Add an entry. */
  229.                         struct node *n = getnode(head);

  230.                         if(ret >; 1) {
  231.                                 printf("Last name: %s\n", lname);
  232.                                 strncpy(n->;lname, lname, sizeof n->;lname);
  233.                                 n->;lname[sizeof n->;lname - 1] = 0;
  234.                         }
  235.                         else
  236.                                 prompt("Enter last name",
  237.                                        n->;lname, sizeof n->;lname);

  238.                         loc = locate(head, n->;lname);
  239.                         if(loc.node != NULL)
  240.                         {
  241.                                 printf("There is alredy a %s on file.\n",
  242.                                        lname);
  243.                                 continue;
  244.                         }

  245.                         prompt("Enter first name", n->;fname, sizeof n->;fname);
  246.                         prompt("Enter address", n->;addr, sizeof n->;addr);
  247.                         prompt("Enter phone", n->;phone, sizeof n->;phone);

  248.                        
  249.                         insert(head, n, loc);
  250.                 }
  251.                 else if(strcmp(cmd, "del") == 0)
  252.                 {
  253.                         /* Return value of locate. */
  254.                         struct lrec loc;

  255.                         if(ret < 2)
  256.                         {
  257.                                 printf("Please give a name to delete.\n");
  258.                                 continue;
  259.                         }

  260.                         /* Search the tree, and delete. */
  261.                         loc = locate(head, lname);
  262.                         if(loc.node == NULL)
  263.                                 printf("%s not found.\n", lname);
  264.                         else
  265.                                 delete(head, loc);
  266.                 }
  267.                 else if(strcmp(cmd, "find") == 0)
  268.                 {
  269.                         /* Return value of locate. */
  270.                         struct lrec loc;

  271.                         /* Find and print an entry. */
  272.                         if(ret < 2)
  273.                         {
  274.                                 printf("Please give a name to find.\n");
  275.                                 continue;
  276.                         }

  277.                         /* Search the tree. */
  278.                         loc = locate(head, lname);
  279.                         if(loc.node == NULL)
  280.                                 printf("%s not found.\n", lname);
  281.                         else
  282.                         {
  283.                                 printf("Last name:  %s\n", loc.node->;lname);
  284.                                 printf("First name: %s\n", loc.node->;fname);
  285.                                 printf("Address:    %s\n", loc.node->;addr);
  286.                                 printf("Phone:      %s\n", loc.node->;phone);
  287.                         }
  288.                 }
  289.                 else if(strcmp(cmd, "list") == 0)
  290.                 {
  291.                         printf("The following names are on file:\n");
  292.                         prtree(head);
  293.                 }
  294.                 else if(strcmp(cmd, "quit") == 0)
  295.                         return;
  296.                 else
  297.                 {
  298.                         printf("No such command %s.\n", cmd);
  299.                 }
  300.         }
  301. }

  302. /*
  303. * Do the work.
  304. */
  305. int main(int argc, char **argv)
  306. {
  307.         /* Get the space. */
  308.         char *area = malloc(sizeof(struct header) + NREC*sizeof(struct node));
  309.         if(area == NULL)
  310.         {
  311.                 fprintf(stderr, "Allocation failed.\n");
  312.                 exit(1);
  313.         }

  314.         /* Format it into an empty phone book. */
  315.         format(area);

  316.         /* Run commands. */
  317.         commands(area);

  318.         /* Free the space. */
  319.         free(area);

  320.         exit(0);
  321. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP