前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux单向循环链表源码分析(基于linux1.2.13)

linux单向循环链表源码分析(基于linux1.2.13)

作者头像
theanarkh
发布2019-07-30 18:48:56
6280
发布2019-07-30 18:48:56
举报
文章被收录于专栏:原创分享原创分享
代码语言:javascript
复制
extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
{
  unsigned long flags;

#ifdef DEBUG
  if (wait->next) {
    unsigned long pc;
    __asm__ __volatile__("call 1f\n"
      "1:\tpopl %0":"=r" (pc));
    printk("add_wait_queue (%08x): wait->next = %08x\n",pc,(unsigned long) wait->next);
  }
#endif
  save_flags(flags);
  cli();
  // 队列为空,头指针指向待插入的节点wait,末节点的next指针指向自己
  if (!*p) {
    wait->next = wait;
    *p = wait;
  } else {
    /* 
      在第一个节点后面插入节点,形成单向循环链表 thanks to zym.
      插入第二个节点的时候,是在第一个节点后面插入,后面在插入的时候,
      是在第一个第二个节点中间插入,然后是从第一第三个直接插入,如此类推
      *p指向第一个节点,(*p)->next指向第一个节点的下一个,插入第二个节点的时候,
      第一个节点的下一个节点是自己。wait->next即新节点的next指向第一个节点的下一个节点,
      (*p)->next = wait;即第一个节点的next指针指向新加入的节点。
      传统的头插法只能形成单链表,不能循环,因为循环需要拿尾指针的next指向第一个
      节点,但是随着链表的变成,无法找到尾节点。
      p -> head -> null
      p -> head -> node1
                 next
              |------->
      p -> head -> node1     node2
              <-------
                next  
                next    next
              |------->   |------->
      p -> head -> node1     node3    node2
              <------------------
                next
      测试代码
      #include <stdio.h>
      struct wait_queue {
        int task;
        struct wait_queue * next;
      };
      void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
      {

        if (!*p) {
          //printf("%d", 1);
          wait->next = wait;
          *p = wait;
        } else {
          
          // 头插法,形成单向链表
          wait->next = (*p)->next;
          (*p)->next = wait;
          //printf("%d", wait->next == *p);
        }
      }
      int main()
      {
        struct wait_queue wait = { 1, NULL };
        struct wait_queue wait1 = { 2, NULL };
        struct wait_queue wait2 = { 3, NULL };
        struct wait_queue * head = NULL;
        add_wait_queue(&head, &wait);
        add_wait_queue(&head, &wait1);
        add_wait_queue(&head, &wait2);
        int c = 5;
        while(c--) {
          printf("%d", head->task);
          head = head->next;
        }
      }
    */
    wait->next = (*p)->next;
    (*p)->next = wait;
  }
  restore_flags(flags);
}

extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
{
  unsigned long flags;
  struct wait_queue * tmp;
#ifdef DEBUG
  unsigned long ok = 0;
#endif

  save_flags(flags);
  cli();
  // 删除的是第一个节点并且只有一个节点了则头指针指向NULL
  if ((*p == wait) &&
#ifdef DEBUG
      (ok = 1) &&
#endif
      ((*p = wait->next) == wait)) {
    *p = NULL;
  } else {
    // 从自己开始遍历单向循环链表,找到next指向自己的,然后更新指针
    tmp = wait;
    while (tmp->next != wait) {
      tmp = tmp->next;
#ifdef DEBUG
      if (tmp == *p)
        ok = 1;
#endif
    }
    tmp->next = wait->next;
  }
  wait->next = NULL;
  restore_flags(flags);
#ifdef DEBUG
  if (!ok) {
    printk("removed wait_queue not on list.\n");
    printk("list = %08x, queue = %08x\n",(unsigned long) p, (unsigned long) wait);
    __asm__("call 1f\n1:\tpopl %0":"=r" (ok));
    printk("eip = %08x\n",ok);
  }
#endif
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档