glibc 中队列的使用方法

今天看 DPDK 源码时,发现它使用了 glibc 中提供的队列 API,这些 API 包含在 头文件中,易于使用。
今天看了下 man 手册,记录下如何使用这些 API 。

第一种队列是 singly-linked lists。单向链表,插入操作只支持向头部插入,所以通常用来实现 LIFO(后进先出队列)。

第二种队列是 singly-linked tail queues。单向链表,新增了向尾部的插入操作,所以通常用来实现 FIFO(先进先出队列)。

第三种是 lists 。双向链表,插入操作只支持向头部插入。支持双向遍历。

第四种是 tail queues。双向链表,插入操作支持向头部和尾部的插入。支持双向遍历。

下面以 singly-linked lists 为例,介绍如何使用这些 API。

首先要定义一个结构体,例子中使用的结构体名称为 “entry” ,里面除了包含自定义的数据成员(val)外,还必须包含使用 SLIST_ENTRY(TYPE) 定义的一个成员。TYPE 必须是结构体名称 “entry”,成员名称为“entries”可以任意取名。这样我们这个数据结构就能够使用链表 API 管理了。如下所示:

struct entry {
    /* 数据 */
    int val;
    SLIST_ENTRY(entry) entries;     /* Singly-linked List. */
}

接着使用 SLIST_HEAD(HEADNAME, TYPE) 定义一个作为链表头部的新结构体,HEADNAME 是新结构体名称,TYPE 是我们自定义的结构体名称。如下所示,例子中使用的新结构体名称为“slisthead”:

SLIST_HEAD(slisthead, entry);

然后定义一个链表头部变量,并初始化:

struct slisthead head = SLIST_HEAD_INITIALIZER(head);
SLIST_INIT(&head);

接下来就可以使用 API 将数据插入到链表了,具体请看下面的个例子。

singly-linked lists

#include 
#include 
#include 

int main(int argc, char **argv)
{
     SLIST_HEAD(slisthead, entry) head = SLIST_HEAD_INITIALIZER(head);
     struct slisthead *headp;                /* Singly-linked List head. */
     struct entry {
             int val;
             SLIST_ENTRY(entry) entries;     /* Singly-linked List. */
     } *n1, *n2, *n3, *np;

     SLIST_INIT(&head);                      /* Initialize the list. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     SLIST_INSERT_HEAD(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     SLIST_INSERT_AFTER(n1, n2, entries);

     SLIST_FOREACH(np, &head, entries) {     /* Forward traversal. */
        printf("val = %d\n", np->val);
     }
     
     SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
     free(n2);

     n3 = SLIST_FIRST(&head);
     SLIST_REMOVE_HEAD(&head, entries);      /* Deletion from the head. */
     free(n3);
                                             

     while (!SLIST_EMPTY(&head)) {           /* List Deletion. */
             n1 = SLIST_FIRST(&head);
             SLIST_REMOVE_HEAD(&head, entries);
             free(n1);
     }
}

singly-linked tail queues

#include 
#include 
#include 

int main(int argc, char **argv)
{
     STAILQ_HEAD(stailhead, entry) head = STAILQ_HEAD_INITIALIZER(head);
     struct stailhead *headp;                /* Singly-linked tail queue head. */
     struct entry {
             int val;
             STAILQ_ENTRY(entry) entries;    /* Tail queue. */
     } *n1, *n2, *n3, *np;

     STAILQ_INIT(&head);                     /* Initialize the queue. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     STAILQ_INSERT_HEAD(&head, n1, entries);

     n1 = malloc(sizeof(struct entry));      /* Insert at the tail. */
     STAILQ_INSERT_TAIL(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     STAILQ_INSERT_AFTER(&head, n1, n2, entries);
                                             /* Deletion. */
     STAILQ_REMOVE(&head, n2, entry, entries);
     free(n2);
                                             /* Deletion from the head. */
     n3 = STAILQ_FIRST(&head);
     STAILQ_REMOVE_HEAD(&head, entries);
     free(n3);
                                             /* Forward traversal. */
     STAILQ_FOREACH(np, &head, entries) {
            printf("val = %d\n", np->val);
     }
                                             /* TailQ Deletion. */
     while (!STAILQ_EMPTY(&head)) {
             n1 = STAILQ_FIRST(&head);
             STAILQ_REMOVE_HEAD(&head, entries);
             free(n1);
     }
                                             /* Faster TailQ Deletion. */
     n1 = STAILQ_FIRST(&head);
     while (n1 != NULL) {
             n2 = STAILQ_NEXT(n1, entries);
             free(n1);
             n1 = n2;
     }
     STAILQ_INIT(&head);

}

lists

#include 
#include 
#include 

int main(int argc, char **argv)
{
     LIST_HEAD(listhead, entry) head =
         LIST_HEAD_INITIALIZER(head);
     struct listhead *headp;                 /* List head. */
     struct entry {
             int val;
             LIST_ENTRY(entry) entries;      /* List. */
     } *n1, *n2, *n3, *np, *np_temp;

     LIST_INIT(&head);                       /* Initialize the list. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     LIST_INSERT_HEAD(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     LIST_INSERT_AFTER(n1, n2, entries);

     n3 = malloc(sizeof(struct entry));      /* Insert before. */
     LIST_INSERT_BEFORE(n2, n3, entries);

     LIST_REMOVE(n2, entries);               /* Deletion. */
     free(n2);
                                             /* Forward traversal. */
     LIST_FOREACH(np, &head, entries) {
             printf("val = %d\n", np->val);
     }

     while (!LIST_EMPTY(&head)) {            /* List Deletion. */
             n1 = LIST_FIRST(&head);
             LIST_REMOVE(n1, entries);
             free(n1);
     }

     n1 = LIST_FIRST(&head);                 /* Faster List Deletion. */
     while (n1 != NULL) {
             n2 = LIST_NEXT(n1, entries);
             free(n1);
             n1 = n2;
     }
     LIST_INIT(&head);
}

tail queues

#include 
#include 
#include 

int main(int argc, char **argv)
{
     TAILQ_HEAD(tailhead, entry) head = TAILQ_HEAD_INITIALIZER(head);
     struct tailhead *headp;                 /* Tail queue head. */
     struct entry {
             int val;
             TAILQ_ENTRY(entry) entries;     /* Tail queue. */
     } *n1, *n2, *n3, *np;

     TAILQ_INIT(&head);                      /* Initialize the queue. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     n1->val = 1;
     TAILQ_INSERT_HEAD(&head, n1, entries);

     n1 = malloc(sizeof(struct entry));      /* Insert at the tail. */
     n1->val = 2;
     TAILQ_INSERT_TAIL(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     n2->val = 3;
     TAILQ_INSERT_AFTER(&head, n1, n2, entries);

     n3 = malloc(sizeof(struct entry));      /* Insert before. */
     n3->val = 4;
     TAILQ_INSERT_BEFORE(n2, n3, entries);

     TAILQ_REMOVE(&head, n2, entries);       /* Deletion. */
     free(n2);
                                             /* Forward traversal. */
     TAILQ_FOREACH(np, &head, entries) {
             printf("val = %d\n", np->val);
     }
                                             /* Reverse traversal. */
     TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries) {
             printf("val = %d\n", np->val);
     }
                                             /* TailQ Deletion. */
     while (!TAILQ_EMPTY(&head)) {
             n1 = TAILQ_FIRST(&head);
             TAILQ_REMOVE(&head, n1, entries);
             free(n1);
     }
                                             /* Faster TailQ Deletion. */
     n1 = TAILQ_FIRST(&head);
     while (n1 != NULL) {
             n2 = TAILQ_NEXT(n1, entries);
             free(n1);
             n1 = n2;
     }

     TAILQ_INIT(&head);
}

你可能感兴趣的:(Linux系统管理)