• linux中链表_队列等的基本原理以及操作以及堆栈


    内核版本为:2.4.10
    等待队列
    相关结构体:
    DECLARE_WAITQUEUE(wait, current); // 定义一个等待队列,和当前进程挂钩
    #define DECLARE_WAITQUEUE(name, tsk) wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)

    #define __WAITQUEUE_INITIALIZER(name, tsk) {
      task: tsk,
      task_list: { NULL, NULL },

    // 等待队列
    struct __wait_queue {
      unsigned int flags;
    #define WQ_FLAG_EXCLUSIVE 0x01
      struct task_struct *task;
      struct list_head task_list;
    #if WAITQUEUE_DEBUG
      long __magic;
      long __waker;
    #endif
    };
    typedef struct __wait_queue wait_queue_t;

    // 等待队列头
    struct __wait_queue_head {
      wq_lock_t lock; // 读写锁
      struct list_head task_list;
    #if WAITQUEUE_DEBUG
      long __magic;
      long __creator;
    #endif
    };
    typedef struct __wait_queue_head wait_queue_head_t;

    // 信号量
    struct semaphore {
      atomic_t count;
      int sleepers;
      wait_queue_head_t wait;
    #if WAITQUEUE_DEBUG
      long __magic;
    #endif
    };

    函数操作:
    将等待队列挂入等待队列头
    add_wait_queue_exclusive(&sem->wait, &wait); // void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait)
      wait->flags &= ~WQ_FLAG_EXCLUSIVE;
      __add_wait_queue_tail(q, wait); // (&sem->wait, &wait) //
        list_add_tail(&new->task_list, &head->task_list); // &wait->task_list挂入sem->wait->task_list尾部

    将等待队列从队列头上卸载
    remove_wait_queue(&sem->wait, &wait);
      __remove_wait_queue(q, wait); // (&sem->wait, &wait)
        list_del(&old->task_list); // wait->task_list

    唤醒等待队列头
      wake_up(&sem->wait); // 唤醒信号量上面的进程

    链表相关的操作:
    结构体
    struct list_head {
      struct list_head *next, *prev;
    };
    初始化
    1 结构体方式
    #define LIST_HEAD_INIT(name) {&(name), &(name)}
    #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
    2 指针方式
    #define INIT_LIST_HEAD(ptr) do {    
      (ptr)->next = (ptr); (ptr)->prev = (ptr);
    } while (0)

    向链表里面插入元素
    void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
    {
      prev->next = new;
      new->prev = prev;
      new->next = next;
      next->prev = new;
    }
    // 把new插入head后面,插入表头
    void list_add(struct list_head *new, sturct list_head *head)
    {
      __list_add(new, head, head->next);
    }
    // 把new插入head前面,插入表尾
    void list_add_tail(struct list_head *new, struct list_head *head)
    {
      __list_add(new, head->prev, head);
    }

    // 从链表里删除元素
    void __list_del(struct list_head *prev, struct list_head *next)
    {
      prev->next = next;
      next->prev = prev;
    }
    void list_del(struct list_head *entry)
    {
      __list_del(entry->prev, entry->next); // 出队列
      entry->prev = entry->next = NULL; // 重新初始化entry
    }

    // 删除元素并初始化
    void list_del_init(struct list_head *entry)
    {
      __list_del(entry->prev, entry->next);
      INIT_LIST_HEAD(entry);
    }

    // 判断链表队列是否为空
    int list_empty(struct list_head *head)
    {
      return (head->next == head);
    }

    // 链表拼接
    // 把list链表接到head后面,实现链表合并,------> 链表队列的合并以及堆栈的原理!
    void list_splice(struct list_head *list, struct list_head *head)
    {
      struct list_head *first = list->next;
      if (list != first)
      {
        struct list_head *last = list->prev;
        struct list_head *at = head->next;
        head->next = first;
        first->prev = head;

        last->next = at;
        at->prev = last;
      }
    }

    // 通过指针获取到宿主结构,基本思想为通过list_head插槽的地址减去对应在宿主结构的偏移量,然后进行强制类型转换!
    #define list_entry(ptr, type, member)   
      (type *)((char *)ptr - (unsigned long)(&(((type *)0)->member)))

    以上基本上为内核里面的代码,可以基于上面的代码实现堆栈!

    typedef struct node {
            int num;
            struct list_head node;
    }tNode, *ptNode;
    
    ptNode ptTmp;
    tNode NODE;
    struct list_head *glist;
    
    void stack_print(void)
    {
            int i, inum;
    
            struct list_head *ptlisthead;
    
            for (i = 0; i < 5; i++) {
                    scanf("%d", &inum);
                    ptTmp = (ptNode)malloc(sizeof(struct node));
                    if (NULL == ptTmp) {
                            printf("malloc error
    ");
                            return;
                    }
                    ptTmp->num = inum;
                    list_add(&(ptTmp->node), glist);
            }
            printf("stack out:
    ");
            for (i = 0; i < 5; i++) {
                    ptlisthead = (glist->next);
                    ptTmp = (ptNode)list_entry(ptlisthead, struct node, node);
                    list_del(ptlisthead);
                    printf("%d
    ", ptTmp->num);
                    free(ptTmp);
            }
    
    }
    void queue_print(void)
    {
            int i, inum;
            struct list_head *ptlisthead;
    
            for (i = 0; i < 5; i++) {
                    scanf("%d", &inum);
                    ptTmp = (ptNode)malloc(sizeof(struct node));
                    if (NULL == ptTmp) {
                            printf("malloc error
    ");
                            return;
                    }
                    ptTmp->num = inum;
                    list_add_tail(&(ptTmp->node), glist);
            }
    printf(
    "queue out: "); for (i = 0; i < 5; i++) { ptlisthead = (glist->next); ptTmp = (ptNode)list_entry(ptlisthead, struct node, node); list_del(ptlisthead); printf("%d ", ptTmp->num); free(ptTmp); } } int main(int argc, char **argv) { glist = (struct list_head *)malloc(sizeof(struct list_head));
    if (NULL == glist)
    return -1; INIT_LIST_HEAD(glist); stack_print();
    printf(
    " enter 5 int for queue "); queue_print(); free(glist);
    return 0; }

    编译生成可执行文件a.out。执行结果为:

    [root@localhost]# ./a.out
    1
    2
    3
    4
    5
    stack out:
    5
    4
    3
    2
    1

    enter 5 int for queue
    1
    2
    3
    4
    5
    queue out:
    1
    2
    3
    4
    5

  • 相关阅读:
    F版本SpringCloud1—大白话为啥要有微服务?啥是微服务?SpringCloud为什么有那么多组件?
    Java已五年1—二本物理到前端实习生到Java程序员「回忆贴」
    SpringBoot图文教程17—上手就会 RestTemplate 使用指南「Get Post」「设置请求头」
    SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」
    SpringBoot图文教程14—SpringBoot集成EasyExcel「上」
    SpringBoot图文教程12—SpringData Jpa的基本使用
    SpringBoot图文教程11—从此不写mapper文件「SpringBoot集成MybatisPlus」
    SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
    SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
    SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」
  • 原文地址:https://www.cnblogs.com/samdyhc/p/9300443.html
Copyright © 2020-2023  润新知