链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表、双向链表和循环链表等。
下面代码是链表的两种实现方式,其中方式一就是按照数据结构书中对链表的实现过程,而方式二是根据linux内核中关于链表的实现。两者的最大区别是方式一中数据是存储在链表结构中的,而方式二中,是在数据结构中包含链表结构的。个人更倾向于第二种实现方法。
链表在内核中的使用例子,在驱动层我们可以建立一个链表实现数据的收发:比如当出现硬件中断时,我们将接收到的数据存储在链表中,并唤醒一个等待队列;而应用层通过阻塞的方式调用ioctl,当链表为空时,则进行睡眠操作,当出现一个唤醒操作时则读取链表中存在的消息,并返回给应用层,让应用层再进行相应的处理。这是链表在驱动层中的一个应用例子。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include<signal.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
typedef int pri_spin_t;
pri_spin_t spin_flag = 1;
#define MAX_READ_ENTRY 10
typedef struct _listp
{
struct _listp *next;
struct _listp *prev;
int data;
}LISTP;
void pri_spin_lock(pri_spin_t *flag)
{
while(1)
{
if(*flag)
{
*flag = 0;
return;
}
}
}
void pri_spin_unlock(pri_spin_t *flag)
{
*flag = 1;
}
void init_list_head(LISTP *listp)
{
listp->next = listp;
listp->prev = listp;
}
void list_add(LISTP *list_head, LISTP *listp)
{
list_head->next->prev = listp;
listp->next = list_head->next;
listp->prev = list_head;
list_head->next = listp;
}
void list_add_tail(LISTP *list_head, LISTP *listp)
{
list_head->prev->next = listp;
listp->prev = list_head->prev;
listp->next=list_head;
list_head->prev = listp;
}
int list_is_empty(LISTP *list_head)
{
return (list_head->next == list_head);
}
void list_del(LISTP *listp)
{
LISTP *prev;
LISTP *next;
prev = listp->prev;
next = listp->next;
prev->next = next;
next->prev = prev;
listp->next = listp;
listp->prev = listp;
}
void free_list(LISTP *list_head)
{
LISTP *pos = NULL;
pos = list_head->next;
while(pos != list_head)
{
list_del(pos);
free(pos);
pos = list_head->next;
printf("free\n");
}
if((list_head->next == list_head->prev)&&(list_head->next == list_head))
{
printf("list empty\n");
}
list_head->next = NULL;
list_head->prev = NULL;
free(list_head);
}
int add_data(int data, LISTP *list_head)
{
LISTP *listp = NULL;
listp = (LISTP *)malloc(sizeof(LISTP));
if(listp == NULL)
{
printf("%s:Can not get memory\n", __FUNCTION__);
return -1;
}
listp->data = data;
list_add(list_head, listp);
}
int add_data_tail(int data, LISTP *list_head)
{
LISTP *listp = NULL;
listp = (LISTP *)malloc(sizeof(LISTP));
if(listp == NULL)
{
printf("%s:Can not get memory\n", __FUNCTION__);
return -1;
}
listp->data = data;
list_add_tail(list_head, listp);
}
void print_data(LISTP *list_head)
{
int data;
LISTP *pos;
if(list_is_empty(list_head))
{
printf("list head is empty\n");
return;
}
for(pos = list_head->next; pos != list_head;pos = pos->next)
{
if(pos)
{
if(pos->next == list_head)
printf("%d\n", pos->data);
else
printf("%d\t", pos->data);
}
}
}
void read_data(LISTP *list_head, int num)
{
int data;
LISTP *entry;
if(list_is_empty(list_head))
{
printf("list head is empty\n");
return;
}
if(num > MAX_READ_ENTRY)
{
num = MAX_READ_ENTRY;
}
printf("READ MESSAGE IS:\n");
for(entry = list_head->next; (entry != list_head)&&(num > 0); entry = list_head->next)
{
printf("%d\t", entry->data);
list_del(entry);
entry->next = NULL;
entry->prev = NULL;
free(entry);
num--;
printf("\n");
}
void *send_message_pth1(void *arg)
{
int i = 0;
while(1)
{
pri_spin_lock(&spin_flag);
add_data_tail(i, (LISTP *)arg);
printf("-----IN SEND_MESSAGE_PTHREAD 1-----\n");
pri_spin_unlock(&spin_flag);
i++;
sleep(2);
}
}
void *send_message_pth2(void *arg)
{
int i = 0;
while(1)
{
pri_spin_lock(&spin_flag);
add_data_tail(i, (LISTP *)arg);
printf("-----IN SEND_MESSAGE_PTHREAD 2-----\n");
pri_spin_unlock(&spin_flag);
i++;
sleep(2);
}
}
void *print_message_pth(void *arg)
{
while(1)
{
pri_spin_lock(&spin_flag);
printf("-----IN PRINT_MESSAGE_PTHREAD-----\n");
print_data((LISTP *)arg);
pri_spin_unlock(&spin_flag);
sleep(2);
}
}
void *read_message_pth(void *arg)
{
int num = 5;
while(1)
{
pri_spin_lock(&spin_flag);
printf("-----IN READ_MESSAGE_PTH-----\n");
read_data((LISTP *)arg, num);
pri_spin_unlock(&spin_flag);
sleep(6);
}
}
int main()
{
int i = 0;
LISTP *list_head = NULL;
pthread_t pth1;
pthread_t pth2;
pthread_t pth3;
pthread_t pth4;
list_head = (LISTP *)malloc(sizeof(LISTP));
if(list_head == NULL)
{
printf("Can not get memory\n");
return -1;
}
init_list_head(list_head);
/*store data into list_head*/
for(i = 0; i < 10; i ++)
{
pri_spin_lock(&spin_flag);
add_data_tail(i, list_head);
pri_spin_unlock(&spin_flag);
}
if(pthread_create(&pth1, NULL, (void *)send_message_pth1, list_head))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth2, NULL, (void *)send_message_pth2, list_head))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth3, NULL, (void *)print_message_pth, list_head))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth4, NULL, (void *)read_message_pth, list_head))
{
printf("create pthread failed\n");
return -1;
}
while(1);
return 0;
}
方式二:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include<signal.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
typedef int pri_spin_t;
#define MAX_READ_ENTRY 10
#define GET_ADDR_BY_OFFSET(ptr, type, member) ((type *)((char *)ptr - (uint32_t)(&(((type *)0)->member))))
typedef struct _listp
{
struct _listp *next;
struct _listp *prev;
}LISTP;
typedef struct _list_msg
{
int data;
LISTP list;
}LIST_MSG;
typedef struct _module_struct
{
LISTP list_head;
pri_spin_t spin_flag;
}MODULE_STRUCT;
void pri_spin_lock(pri_spin_t *flag)
{
while(1)
{
if(*flag)
{
*flag = 0;
return;
}
}
}
void pri_spin_unlock(pri_spin_t *flag)
{
*flag = 1;
}
void init_list_head(LISTP *listp)
{
listp->next = listp;
listp->prev = listp;
}
void list_add(LISTP *list_head, LISTP *listp)
{
list_head->next->prev = listp;
listp->next = list_head->next;
listp->prev = list_head;
list_head->next = listp;
}
void list_add_tail(LISTP *list_head, LISTP *listp)
{
list_head->prev->next = listp;
listp->prev = list_head->prev;
listp->next=list_head;
list_head->prev = listp;
}
int list_is_empty(LISTP *list_head)
{
return (list_head->next == list_head);
}
void list_del(LISTP *listp)
{
LISTP *prev;
LISTP *next;
prev = listp->prev;
next = listp->next;
prev->next = next;
next->prev = prev;
listp->next = listp;
listp->prev = listp;
}
void free_list(LISTP *list_head)
{
LISTP *pos = NULL;
pos = list_head->next;
while(pos != list_head)
{
list_del(pos);
free(pos);
pos = list_head->next;
printf("free\n");
}
if((list_head->next == list_head->prev)&&(list_head->next == list_head))
{
printf("list empty\n");
}
list_head->next = NULL;
list_head->prev = NULL;
free(list_head);
}
int add_data(int data, LISTP *list_head)
{
LIST_MSG *list_message = NULL;
list_message = (LIST_MSG *)malloc(sizeof(LIST_MSG));
if(list_message == NULL)
{
printf("%s:Can not get memory\n", __FUNCTION__);
return -1;
}
init_list_head(&(list_message->list));
list_message->data = data;
list_add(list_head, &(list_message->list));
return 0;
}
int add_data_tail(int data, LISTP *list_head)
{
LIST_MSG *list_message = NULL;
list_message = (LIST_MSG *)malloc(sizeof(LIST_MSG));
if(list_message == NULL)
{
printf("%s:Can not get memory\n", __FUNCTION__);
return -1;
}
init_list_head(&(list_message->list));
list_message->data = data;
list_add_tail(list_head, &(list_message->list));
return 0;
}
void print_data(LISTP *list_head)
{
int data;
LISTP *pos;
LIST_MSG *message;
if(list_is_empty(list_head))
{
printf("list head is empty\n");
return;
}
for(pos = list_head->next; pos != list_head;pos = pos->next)
{
if(pos)
{
message = GET_ADDR_BY_OFFSET(pos, LIST_MSG, list);
if(message)
{
printf("%d\t", message->data);
}
}
}
printf("\n");
}
void read_data(LISTP *list_head, int num)
{
int data;
LISTP *entry;
LIST_MSG *message;
if(list_is_empty(list_head))
{
printf("list head is empty\n");
return;
}
if(num > MAX_READ_ENTRY)
{
num = MAX_READ_ENTRY;
}
printf("READ MESSAGE IS:\n");
for(entry = list_head->next; (entry != list_head)&&(num > 0); entry = list_head->next)
{
message = GET_ADDR_BY_OFFSET(entry, LIST_MSG, list);
if(message)
{
printf("%d\t", message->data);
list_del(&(message->list));
free(message);
num--;
}
}
printf("\n");
}
void *send_message_pth1(void *arg)
{
int i = 0;
MODULE_STRUCT *main_data;
main_data = (MODULE_STRUCT *)arg;
while(1)
{
pri_spin_lock(&(main_data->spin_flag));
add_data_tail(i, &(main_data->list_head));
printf("-----IN SEND_MESSAGE_PTHREAD 1-----\n");
pri_spin_unlock(&(main_data->spin_flag));
i++;
sleep(2);
}
}
void *send_message_pth2(void *arg)
{
int i = 0;
MODULE_STRUCT *main_data;
main_data = (MODULE_STRUCT *)arg;
while(1)
{
pri_spin_lock(&(main_data->spin_flag));
add_data_tail(i, &(main_data->list_head));
printf("-----IN SEND_MESSAGE_PTHREAD 2-----\n");
pri_spin_unlock(&(main_data->spin_flag));
i++;
sleep(2);
}
}
void *print_message_pth(void *arg)
{
MODULE_STRUCT *main_data;
main_data = (MODULE_STRUCT *)arg;
while(1)
{
pri_spin_lock(&(main_data->spin_flag));
printf("-----IN PRINT_MESSAGE_PTHREAD-----\n");
print_data(&(main_data->list_head));
pri_spin_unlock(&(main_data->spin_flag));
sleep(2);
}
}
void *read_message_pth(void *arg)
{
int num = 5;
MODULE_STRUCT *main_data;
main_data = (MODULE_STRUCT *)arg;
while(1)
{
pri_spin_lock(&(main_data->spin_flag));
printf("-----IN READ_MESSAGE_PTH-----\n");
read_data(&(main_data->list_head), num);
pri_spin_unlock(&(main_data->spin_flag));
sleep(3);
}
}
int main()
{
int i = 0;
MODULE_STRUCT main_data;
pthread_t pth1;
pthread_t pth2;
pthread_t pth3;
pthread_t pth4;
main_data.spin_flag = 1;
init_list_head(&(main_data.list_head));
for(i = 0; i < 10; i ++)
{
pri_spin_lock(&(main_data.spin_flag));
add_data_tail(i, &(main_data.list_head));
pri_spin_unlock(&(main_data.spin_flag));
}
if(pthread_create(&pth1, NULL, (void *)send_message_pth1, (void *)&main_data))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth2, NULL, (void *)send_message_pth2, (void *)&main_data))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth3, NULL, (void *)print_message_pth, (void *)&main_data))
{
printf("create pthread failed\n");
return -1;
}
if(pthread_create(&pth4, NULL, (void *)read_message_pth, (void *)&main_data))
{
printf("create pthread failed\n");
return -1;
}
while(1);
return 0;
}