linux单向循环链表源码分析(基于linux1.2.13)

extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
{
	unsigned long flags;

#ifdef DEBUG
	if (wait->next) {
		unsigned long pc;
		__asm__ __volatile__("call 1f\n"
			"1:\tpopl %0":"=r" (pc));
		printk("add_wait_queue (%08x): wait->next = %08x\n",pc,(unsigned long) wait->next);
	}
#endif
	save_flags(flags);
	cli();
	// 队列为空,头指针指向待插入的节点wait,末节点的next指针指向自己
	if (!*p) {
		wait->next = wait;
		*p = wait;
	} else {
		/* 
			在第一个节点后面插入节点,形成单向循环链表 thanks to zym.
			插入第二个节点的时候,是在第一个节点后面插入,后面在插入的时候,
			是在第一个第二个节点中间插入,然后是从第一第三个直接插入,如此类推
			*p指向第一个节点,(*p)->next指向第一个节点的下一个,插入第二个节点的时候,
			第一个节点的下一个节点是自己。wait->next即新节点的next指向第一个节点的下一个节点,
			(*p)->next = wait;即第一个节点的next指针指向新加入的节点。
			传统的头插法只能形成单链表,不能循环,因为循环需要拿尾指针的next指向第一个
			节点,但是随着链表的变成,无法找到尾节点。
			p -> head -> null
			p -> head -> node1
							   next
							|------->
			p -> head -> node1 		node2
							<-------
								next	
								next		next
							|------->   |------->
			p -> head -> node1 		node3    node2
							<------------------
								next
			测试代码
			#include <stdio.h>
			struct wait_queue {
				int task;
				struct wait_queue * next;
			};
			void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
			{

				if (!*p) {
					//printf("%d", 1);
					wait->next = wait;
					*p = wait;
				} else {
					
					// 头插法,形成单向链表
					wait->next = (*p)->next;
					(*p)->next = wait;
					//printf("%d", wait->next == *p);
				}
			}
			int main()
			{
				struct wait_queue wait = { 1, NULL };
				struct wait_queue wait1 = { 2, NULL };
				struct wait_queue wait2 = { 3, NULL };
				struct wait_queue * head = NULL;
				add_wait_queue(&head, &wait);
				add_wait_queue(&head, &wait1);
				add_wait_queue(&head, &wait2);
				int c = 5;
				while(c--) {
					printf("%d", head->task);
					head = head->next;
				}
			}
		*/
		wait->next = (*p)->next;
		(*p)->next = wait;
	}
	restore_flags(flags);
}

extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
{
	unsigned long flags;
	struct wait_queue * tmp;
#ifdef DEBUG
	unsigned long ok = 0;
#endif

	save_flags(flags);
	cli();
	// 删除的是第一个节点并且只有一个节点了则头指针指向NULL
	if ((*p == wait) &&
#ifdef DEBUG
	    (ok = 1) &&
#endif
	    ((*p = wait->next) == wait)) {
		*p = NULL;
	} else {
		// 从自己开始遍历单向循环链表,找到next指向自己的,然后更新指针
		tmp = wait;
		while (tmp->next != wait) {
			tmp = tmp->next;
#ifdef DEBUG
			if (tmp == *p)
				ok = 1;
#endif
		}
		tmp->next = wait->next;
	}
	wait->next = NULL;
	restore_flags(flags);
#ifdef DEBUG
	if (!ok) {
		printk("removed wait_queue not on list.\n");
		printk("list = %08x, queue = %08x\n",(unsigned long) p, (unsigned long) wait);
		__asm__("call 1f\n1:\tpopl %0":"=r" (ok));
		printk("eip = %08x\n",ok);
	}
#endif
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值