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

原文地址:https://www.cnblogs.com/samdyhc/p/9300443.html