Chinaunix首页 | 论坛 | 博客

分类: LINUX

2012-11-29 21:30:23

    在 Linux 内核中处处可见链表,可见链表的用处非常大。对于该项目也是一样的,我们需要将目录下所有的 mp3 文件串成一个链表,并通过逐一遍历来播放歌曲。有人喜欢使用传统的链表,将节点和具体的结构体绑定,个人认为这种方式移植性不好,Linux 内核中有一套很不错的链表机制,它的链表节点与具体的结构体无关系,既然如此我们何不仿照内核,来个依葫芦画瓢。
    内核里面的链表功能比较强,考虑到我们的项目并不是特别复杂,因此选择适当性地删减。我们将其实现放入 list.h 中:
/**************************************************************/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H

struct list_head {
    struct list_head *next, *prev;
};

static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}


/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}


#define list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)



#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({            \
    const struct list_head * __mptr = (ptr);    \
    (type *)((char *)__mptr - offsetof(type, member)); })

/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:    the type of the struct this is embedded in.
 * @member:    the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

#endif

/**************************************************************/

    有了链表,现在就可以通过它将所有的歌曲串在一起。这里我们为每个歌曲定义一个结构体 struct song,里面包含歌曲名 name 和链表节点 list。
struct song {
    char name[40];
    struct list_head list;
};
    在看具体的代码之前,我们先看两个关于目录操作的函数:
    DIR *opendir(const char *name); 
    The opendir() function opens a directory stream corresponding to the directory name, and returns a pointer to the directory stream. The stream is positioned at the first entry in the directory.
    struct dirent *readdir(DIR *dir);
    Returns the name of the next entry in the directory. The entries are returned in the order in which they are stored by the filesystem.
 
                       ——忠于梦想 勇于实践    linux_xpj@opencores.org

阅读(1781) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

skyfox_lai2012-11-30 14:44:28