网络子系统12_邻居子系统垃圾回收

//	邻居子系统垃圾回收机制:
//		1.异步回收机制:通过定时器,定期检测邻居缓存使用的内存阈值
//		2.同步回收机制:无法分配新neighbour实例时,同步回收内存。

//	同步,异步回收机制的区别:
//		1.同步回收比异步回收更加严格:
//			1.1 回收的数量:同步回收遍历每一个bucket;
//				异步回收接着上次清理的bucket开始,只清理一个bucket
//			1.2 回收的条件:同步回收视没有被引用,非静态配置的邻居项均视为可回收项;
//				异步回收见下3.1
//		2.回收时机不同:
//			2.1 同步回收在分配新邻居项失败时,进行;异步回收定期进行
//		3.任务不同:
//			3.1异步回收机制负责随机化neigh_parms->reachable_time

//	异步回收机制:
//		1.每300HZ随机化邻居协议参数的reachable_time
//		2.使用tbl->hash_chain_gc记录下次gc清理的bucket
//		3.遍历需要清理的bucket
//			3.1 选择合适的清理对象:
//				3.1.1 非用户配置的永久邻居项,没有定时器在运行的邻居项
//				3.1.2 没有被其他子系统引用
//				3.1.3 solicitation请求失败,或者在一段时间内没有被使用过
//			3.2 标记邻居项为dead,释放邻居项
//		4.更新下次gc的到期时间
1.1 static void neigh_periodic_timer(unsigned long arg)
{
	struct neigh_table *tbl = (struct neigh_table *)arg;
	struct neighbour *n, **np;
	unsigned long expire, now = jiffies;
	//在协议锁的保护下清理
	write_lock(&tbl->lock);

	//每300HZ随机化邻居参数的reachable_time
	if (time_after(now, tbl->last_rand + 300 * HZ)) {
		struct neigh_parms *p;
		tbl->last_rand = now;//上次更新随机范围的时间戳
		for (p = &tbl->parms; p; p = p->next)//与邻居协议相关的调整参数保存在tbl->parms链表中
			p->reachable_time =
				neigh_rand_reach_time(p->base_reachable_time);
	}
	//tbl->hash_chain_gc用于记录当前gc运行的bucket链表头
	np = &tbl->hash_buckets[tbl->hash_chain_gc];
	//更新下次gc运行的bucket链表头号
	tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
	while ((n = *np) != NULL) {
		unsigned int state;

		write_lock(&n->lock);
		//当前neighbour的状态
		state = n->nud_state;
		//永久配置,或者运行了定时器的邻居项不是合适的清理对象
		if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
			write_unlock(&n->lock);
			goto next_elt;
		}

		//邻居项上一次使用的时间在其上一次可达性确认之前
		if (time_before(n->used, n->confirmed))
			n->used = n->confirmed;//上一次使用时间为上一次确认时间

		if (atomic_read(&n->refcnt) == 1 &&//只有hash表引用此邻居项
		    (state == NUD_FAILED ||//该邻居项solicitation请求失败,邻居项为不可达
		     time_after(now, n->used + n->parms->gc_staletime))) {//或者邻居项已近一段时间没有被使用过
			*np = n->next;
			n->dead = 1;//标记该邻居项将被删除,不在使用
			write_unlock(&n->lock);
			neigh_release(n);//递减当前引用计数,释放邻居项
			continue;
		}
		//解锁neighbour
		write_unlock(&n->lock);

next_elt:
		np = &n->next;
	}
	//计算下一次到期时间 expire = (base_reachable_time/2)/(bucket size)
	expire = tbl->parms.base_reachable_time >> 1;
	expire /= (tbl->hash_mask + 1);
	if (!expire)
		expire = 1;
	//更新gc到期时间
 	mod_timer(&tbl->gc_timer, now + expire);
	write_unlock(&tbl->lock);
}

//	同步回收机制:
//		1.遍历每个bucket
//			1.1 如果邻居项非静态配置,并且没有被其他子系统引用,释放邻居项
//		2.更新neigh_forced_gc时间戳
1.2 static int neigh_forced_gc(struct neigh_table *tbl)
{
	int shrunk = 0;
	int i;

	//在协议表锁的保护下,清理
	write_lock_bh(&tbl->lock);
	//遍历每一个bucket
	for (i = 0; i <= tbl->hash_mask; i++) {
		struct neighbour *n, **np;
		np = &tbl->hash_buckets[i];
		while ((n = *np) != NULL) {
			//获取neighbour的锁
			write_lock(&n->lock);
			//邻居项没有被其他子系统引用
			if (atomic_read(&n->refcnt) == 1 &&
			    !(n->nud_state & NUD_PERMANENT)) {//并且l2地址并非静态配置
				*np	= n->next;
				n->dead = 1;//标记当前neighbour将被删除,不在使用
				shrunk	= 1;
				write_unlock(&n->lock);
				neigh_release(n);
				continue;
			}
			write_unlock(&n->lock);
			np = &n->next;//下一个
		}
	}
	//更新neigh_forced_gc时间戳
	tbl->last_flush = jiffies;

	write_unlock_bh(&tbl->lock);

	return shrunk;//返回是否有neighbour被释放
}
时间: 2025-01-20 10:06:02

网络子系统12_邻居子系统垃圾回收的相关文章

网络子系统71_路由缓存垃圾回收

// 同步回收机制 // 返回值: // 0,达到回收目标 // 1,没有达到回收目标 // 注:ip_rt_gc_min_interval = HZ/2 // ip_rt_gc_timeout = RT_GC_TIMEOUT = 300HZ // ip_rt_gc_elasticity = 8*(rt_hash_mask+1)(正常情况下) // ip_rt_gc_elasticity = 1(当绑定缓存到邻居子系统失败时) // 平衡点,gc目标数的动态调整: // 1.当前缓存个数 < 安

网络子系统14_邻居子系统通用接口

//创建一个新的邻居项 //参考 深入理解linux网络技术内幕 // 1.邻居子系统为具体的邻居协议,提供通用的功能接口 // 2.系统中所有的邻居协议被链接在neigh_tables链表中 // 3.neigh_table代表一个具体的邻居协议 // 4.具体邻居协议在运行时的行为,可以通过struct neigh_parms调节, // neigh_params与设备关联,每个邻居协议neigh_table提供一个默认的neigh_params. //注册一个邻居协议到系统中 // 1.与

网络子系统74_邻居子系统结构图

// 1.系统所有邻居协议控制块通过neigh_tables链接在一起. // 2.neigh_table->hash_mask 默认初始化为1,表示每个邻居协议有两个bucket. // 3.net_device->ip_ptr->arp_params调整其上运行的arp协议行为.                                                                    //参考 深入理解linux网络技术内幕

网络子系统13_邻居子系统状态机

// 参考深入理解linux网络技术内幕 // 头文件net/neighbour.h //一个solicitation请求已发出,但是还没有收到应答,在这个状态下,不适用任何硬件地址 #define NUD_INCOMPLETE 0x01 //该邻居是可到达的 #define NUD_REACHABLE 0x02 //缓存中包含此邻居项,但是该地址已有一段时间没有被确认了,上一次确认时间由 //neighbour->confirmed成员指出,当下一次有封包要到达这个邻居时,要启动可到达性确认,

网络子系统15_arp邻居项初始化

// 初始化struct neighbour // 当邻居子系统新创一个neighbour时,邻居子系统调用特定协议的初始化函数,初始化邻居项. // 调用路径:neigh_create->arp_constructor // 函数主要任务: // 1.设置邻居项的地址类型,a,b,c,d // 2.使用与此邻居项关联的接口设备的neigh_param作为该邻居项调整邻居协议的参数. // 3.根据与此邻居项关联的接口设备的信息,初始化邻居项的状态,以及ops // 3.1 驱动没有提供填充l2

网络子系统61_路由子系统初始化

// 路由缓存内存量指定办法: // 1.通过启动参数rhash_entries指定hash表bucket个数 // 2.根据物理内存页数确定使用的内存量 // 根据物理页数分配缓存内存: // 1.goal目标内存页数=总页数/(2**(26-PAGE_SHIFT)) // 2.最接近goal内存页数的order,用于从伙伴系统中分配 // 3.rt_hash_mask=order页可容纳的bucket数 // 4.对齐rt_hash_mask到2的幂次 // 5.从伙伴系统中分配order页

网络子系统30_桥接子系统通用接口

// 添加网桥设备 // 参数: // name,需要全局唯一 // 调用路径:socket ioctl->br_add_bridge // 函数主要任务: // 1.创建一个新的网络设备 // 2.初始化网络设备的通用字段以及网桥设备的字段 // 3.向系统注册网络设备 1.1 int br_add_bridge(const char *name) { struct net_device *dev;//net_bridge->dev int ret; dev = new_bridge_dev

CLR探索系列-GC中的Card table和Brick Table(垃圾回收系列)

在CLR的垃圾回收子系统中,Card Table和Brick Table是两个比较有意思的表. 在GC的过程中,一个Heap在运行了一段时间以后,已经分配的空间就会越来越大.在进行了一次局部代或者是完全的垃圾回收以后,就会涉及到一个GC堆的类似碎片整理的概念.整理优化一次GC Heap.同时,这种机制保证了譬如一个IIS Server在长时间的运行过程中的稳定性并且优化了其内存管理. 这样的好处是显而易见的,但是采用这种解决方案带来的问题也很容易想到:譬如一个存在于GC Heap里面的"Smal

简单理解Java的垃圾回收机制与finalize方法的作用_java

垃圾回收器要回收对象的时候,首先要调用这个类的finalize方法(你可以 写程序验证这个结论),一般的纯Java编写的Class不需要重新覆盖这个方法,因为Object已经实现了一个默认的,除非我们要实现特殊的功能(这 里面涉及到很多东西,比如对象空间树等内容). 不过用Java以外的代码编写的Class(比如JNI,C++的new方法分配的内存),垃圾回收器并不能对这些部分进行正确的回收,这时就需要我们覆盖默认的方法来实现对这部分内存的正确释放和回收(比如C++需要delete). 总之,f