在 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
阅读(1825) | 评论(1) | 转发(0) |