网络子系统6_设备开启与关闭

//	网络设备开启
//	函数主要任务:
//		1.设置dev->state=__LINK_STATE_START
//		2.调用驱动程序的回调函数open
//		3.设置dev->flags |= IFF_UP表示设备开启
//		4.更新多播列表,
//		5.激活设备
//		6.通知监听器,设置dev->flags

//	设备开启之后应该具备的特征:
//		1.dev->state, 表示设备可以进行传输接收
//		2.dev->flags,表示设备已经开启
//		3.设备使用了正确的队列规则

1.1 int dev_open(struct net_device *dev)
{
	int ret = 0;

	//检查设备是否已经开启
	if (dev->flags & IFF_UP)
		return 0;

	//检查设备是否存在
	if (!netif_device_present(dev))
		return -ENODEV;
	//设置设备可以进行接收
	set_bit(__LINK_STATE_START, &dev->state);
	if (dev->open) {
		//如果驱动程序提供了open函数,则调用
		ret = dev->open(dev);
		if (ret)
			clear_bit(__LINK_STATE_START, &dev->state);
	}
	if (!ret) {
		//设置开启标志
		dev->flags |= IFF_UP;
		//加载多播地址列表
		dev_mc_upload(dev);
		//激活设备,使能传输队列
		dev_activate(dev);
		//向netdev_chain通知有设备开启
		notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
	}
	return ret;
}

//	加载设备多播地址
//	调用路径:dev_open->dev_mc_upload
//	ip地址,mac地址之间的映射,参照http://blog.csdn.net/hxg130435477/article/details/8049271
1.2 void dev_mc_upload(struct net_device *dev)
{
	spin_lock_bh(&dev->xmit_lock);
	__dev_mc_upload(dev);
	spin_unlock_bh(&dev->xmit_lock);
}

//	调用路径:dev_open->dev_mc_upload->__dev_mc_upload
//	通过驱动程序的回调函数,设置设备的l2多播地址列表
1.3 static void __dev_mc_upload(struct net_device *dev)
{
	//设备应该处于关闭状态
	if (!(dev->flags&IFF_UP))
		return;
	//设备驱动提供了设置多播地址的方法
	if (dev->set_multicast_list == NULL ||
	    !netif_device_present(dev))
		return;
	//调用设备提供的设置多播地址的方法
	dev->set_multicast_list(dev);
}

//	调用路径:dev_open->dev_activate
//	函数主要任务:
//		1.更新设备的队列规则
//			1.1 如果设备没有使用队列规则,则dev->qdisc设置为noqueue_disc,防止不正确的使用该驱动的队列规则
//			1.2 如果设备使用队列规则:
//				1.2.1 如果设置第一次被激活,则分配新的队列规则,保存在dev->qdisc_sleeping
//				1.2.2 如果设备非第一次被激活
//				1.2.3 设置dev->qdisc=dev->qdisc_sleeping
//		2.启动看门狗
1.4 void dev_activate(struct net_device *dev)
{
	//设备没有关联队列规则
	if (dev->qdisc_sleeping == &noop_qdisc) {
		struct Qdisc *qdisc;
		//设备存在传输队列
		//dev->tx_queue_len的值由设备驱动程序设置
		if (dev->tx_queue_len) {
			//创建先进先出队列
			qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops);
			if (qdisc == NULL) {
				printk(KERN_INFO "%s: activation failed\n", dev->name);
				return;
			}
			//将队列规则添加到dev的队列规则链表头
			//说明一个dev可以有多个队列规则
			write_lock_bh(&qdisc_tree_lock);
			list_add_tail(&qdisc->list, &dev->qdisc_list);
			write_unlock_bh(&qdisc_tree_lock);
		} else {
			//如果驱动程序没有提供tx_queue_len,即=0
			//设置默认的队列
			qdisc =  &noqueue_qdisc;
		}
		write_lock_bh(&qdisc_tree_lock);
		//设置dev的qdisc_sleeping
		dev->qdisc_sleeping = qdisc;
		write_unlock_bh(&qdisc_tree_lock);
	}

	spin_lock_bh(&dev->queue_lock);
	//设置qdisc_sleep到qdisc字段
	rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping);
	if (dev->qdisc != &noqueue_qdisc) {
		dev->trans_start = jiffies;
		//唤醒看门狗
		dev_watchdog_up(dev);
	}
	spin_unlock_bh(&dev->queue_lock);
}

//	设备关闭
//	函数主要任务:
//		1.向netdev_chain发送消息NETDEV_GOING_DOWN
//		2.deactivate设备,
//		3.清除dev->state的__LINK_STATE_START
//		4.等待设备完成数据接收
//		5.调用驱动程序提供的关闭函数
//		6清除dev->flags中的IFF_UP
//		7.向netdev_chain发送消息NETDEV_DOWN

2.1 int dev_close(struct net_device *dev)
{
	//设备已经关闭,则直接返回
	if (!(dev->flags & IFF_UP))
		return 0;
	//向netdev_chain发送设备正在关闭消息
	notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);

	//关闭设备队列规则
	dev_deactivate(dev);

	//设置设备关闭传输
	clear_bit(__LINK_STATE_START, &dev->state);
	//内存屏障
	smp_mb__after_clear_bit();
		//设备还在接收输入流量
	while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
		//调度当前线程等待
		current->state = TASK_INTERRUPTIBLE;
		schedule_timeout(1);
	}
	//驱动提供了停止函数,则调用
	if (dev->stop)
		dev->stop(dev);

	//清除IFF_UP标志,表示设备已被关闭
	dev->flags &= ~IFF_UP;
	//通知netdev_chain已关闭消息
	notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);

	return 0;
}

//	网络设备的看门狗:
//		1.当网络设备由于被开启而激活传输时,同时激活设备驱动程序的开门狗机制。
//		2.看门狗的定时周期由驱动程序通过dev->watchdog_time指定
//		3.看门狗的定时器由驱动程序通过dev->watchdog_timer提供

//	调用路径:dev_activate->dev_watchdog_up
3.1 static void dev_watchdog_up(struct net_device *dev)
{
	//在获取dev->xmit_lock传输锁时设置看门狗定时器
	spin_lock_bh(&dev->xmit_lock);
	__netdev_watchdog_up(dev);
	spin_unlock_bh(&dev->xmit_lock);
}

// 调用路径dev_activate->dev_watchdog_up->__netdev_watchdog_up
void __netdev_watchdog_up(struct net_device *dev)
{
	if (dev->tx_timeout) {
		if (dev->watchdog_timeo <= 0)//设备驱动没有设置看门狗的到期时间
			dev->watchdog_timeo = 5*HZ;
		if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
			dev_hold(dev);
	}
}
时间: 2024-10-06 07:22:58

网络子系统6_设备开启与关闭的相关文章

网络子系统26_设备传输的开启和关闭

// 1.由设备驱动程序开启和关闭设备的传输功能 // 2.下边这些函数在驱动程序提供的open,close中被调用 // 开启设备的传输 1.1 static inline void netif_start_queue(struct net_device *dev) { clear_bit(__LINK_STATE_XOFF, &dev->state); } // 关闭设备传输 1.2 static inline void netif_stop_queue(struct net_devic

网络子系统5_设备队列规则

// 1.设备描述符与队列规则相关的字段: // 1.1 dev->tx_queue_len 指示驱动程序规则队列的队列长度,在注册设备时使用,通知核心是否为设备提供队列规则机制. // 1.1.1 不适用队列规则=0 // 1.1.2 使用队列规则>0 // 1.2 dev->qdisc,执行设备传输时,qdisc_run,dev_queue_xmit始终通过该字段获取设备当前使用的队列规则. // 1.3 dev->qdisc_sleep, 保存设备具备传输能力时,使用的设备队

网络子系统64_设备ip地址配置

// 相同子网: // 掩码相同,网络地址相同 // 为设备配置ip地址 // 函数主要任务: // 1.合理性检查: // 1.1 相同子网内该地址没有被添加过 // 1.2 相同子网内的地址scope应该相同 // 2.将ifa插入到in_device->ifa_list中 // 3.通知netlink,inetaddr_chain 新地址的加入 // 注:地址在in_device->ifa_list中的排列: // 1.主地址:插入的如果为主地址,则按照scope从大到小的顺序排列 //

Windows 10下开启已经关闭的无线功能

1. 我们在windows 10系统任务栏找到 无线连接图标,然后我们点击 Wlan按钮,然后就会打开无线列表界面: 然后我们会看到有两种模式了,我们点击它即可打开了 2. 当然还一种办法就是点击 网络设置按钮,在弹出的页面上,将无线功能打开即如下图所示: 开启无线功能非常的简单只要在系统右上角点击网络图标就可以进行开启或关闭了,这个希望对各位有帮助.

网络子系统32_网桥设备的开启与关闭

// 开启网桥设备 // 调用路径dev_open->br_dev_open // 函数主要任务: // 1.开启传输队列 // 2.使能网桥 1.1 static int br_dev_open(struct net_device *dev) { //开启的传输功能,清除dev->state的__LINK_STATE_XOFF标志 netif_start_queue(dev); br_stp_enable_bridge(dev->priv);//使能网桥 return 0; } //

手机QQ登陆设备保护开启与关闭方法

设备开启 1.进入新版的QQ以后依次点击[设置]---[登陆设备保护] 2.开启保护后可以保护你QQ账户的安全,在未验证的手机或电脑上登陆QQ,需要何手机短信验证一下或扫一扫才可以正常登陆.点击[开启保护] 3.此时手机会收到一条短信,验证码框中会自动抓取到手机短信中的验证码.如果抓取不到则需要手动输入验证码.点击[确定] 4.出现以如下图所示的界面则说明已开通了手机QQ登陆设备保护. 设备关闭 1.进入新版的QQ以后依次点击[设置]---[登陆设备保护] 2.进入登陆设备保护界面,点击[关闭保

tplink路由器访客网络如何定时开启或关闭?

访客网络是路由器专门为来访客人提供的无线信号,支持定时开启或关闭.比如,您需要在某个时间段举办家庭聚会,则可以设置这个时间段开放访客网络给客人使用,其他时间则处于关闭状态,从而有效保障网络安全. 本文介绍访客网络定时开启或关闭的设置方法. 打开浏览器并清空地址栏,输入路由器管理地址tplogin.cn,填写管理员密码并登录界面: 注意:管理员密码是首次使用路由器时设置的密码,如忘记,请复位路由器并重新设置. 点击界面下方的 应用管理 > 已安装应用,进入 访客网络,如下图:   开启访客网络,设

网络子系统27_桥接子系统初始化

//桥接子系统以模块的形式提供 //函数主要任务: // 1.转发数据库slab缓存 // 2.向socket的ioctl添加回调函数 // 3.在netif_receive_skb中路径上添加回调函数 // 4.向netdev_chain注册监听块 1.1 static int __init br_init(void) { //转发数据库初始化 br_fdb_init(); //桥接子系统中有关netfilter的初始化 ... //向socket的ioctl注册回调函数,处理对网桥的io命令

网络子系统69_路由表辅助程序

// 关闭设备上的ip协议 // 函数主要任务: // 1.删除与设备相关的路由信息 // 2.刷新路由缓存 // 3.通知邻居子系统,与该设备有关的邻居项失效 1.1 static void fib_disable_ip(struct net_device *dev, int force) { if (fib_sync_down(0, dev, force)) fib_flush(); rt_cache_flush(0); arp_ifdown(dev); } // 设备状态改变/删除ip,标