当前位置: 首页 > news >正文

三亚房产网站开发学校特色网站建设情况

三亚房产网站开发,学校特色网站建设情况,做邮箱网站,app开发入门基础教程struct ifreq ifr; ifr.ifr_flags | IFF_TAP | IFF_NO_PI; ioctl(fd, TUNSETIFF, (void *)&ifr); 上面的代码的意思是设置网卡信息,并将tun驱动设置为TAP模式。在TAP模式下,在用户空间下调用open打开/dev/net/tun驱动文件,发送(调用send函…

 

struct ifreq ifr;
ifr.ifr_flags |= IFF_TAP | IFF_NO_PI;
ioctl(fd, TUNSETIFF, (void *)&ifr);

上面的代码的意思是设置网卡信息,并将tun驱动设置为TAP模式。在TAP模式下,在用户空间下调用open打开/dev/net/tun驱动文件,发送(调用send函数)的和接收(调用read函数)到的,都是以太包。

以上面代码为切入点,来看下内核的处理逻辑。

tun驱动的ioctl对应的是tun_chr_ioctl。

一  tun_chr_ioctl

在tun_chr_ioctl中调用了__tun_chr_ioctl。

static long __tun_chr_ioctl(struct file *file, unsigned int cmd,unsigned long arg, int ifreq_len)
{struct tun_file *tfile = file->private_data;struct tun_struct *tun;void __user* argp = (void __user*)arg;struct ifreq ifr;// 将用户空间的数据,拷贝到ifr中if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == SOCK_IOC_TYPE) {if (copy_from_user(&ifr, argp, ifreq_len))return -EFAULT;} else {memset(&ifr, 0, sizeof(ifr));}ret = 0;rtnl_lock();// 获取tun_struct结构,首次调用TUNSETIFF时为NULLtun = tun_get(tfile);if (cmd == TUNSETIFF) {ret = -EEXIST;if (tun)goto unlock;ifr.ifr_name[IFNAMSIZ-1] = '\0';ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr);if (ret)goto unlock;// 将ifr中的数据,拷贝到用户空间if (copy_to_user(argp, &ifr, ifreq_len))ret = -EFAULT;goto unlock;}... ...
}

在__tun_chr_ioctl中,调用tun_get获取tfile对应的tun。

tun_get相当于执行下面的操作:

struct tun_struct *tun = rcu_dereference(tfile->tun);

第一次执行时,tun为空,调用tun_set_iff。

二 tun_set_iff

tun_chr_ioctl

|- __tun_chr_ioctl

  |- tun_set_iff

调用ifconfig命令时,左侧显示的名称,即网卡名称,保存到了ifreq结构的ifr_name字段中。

 2.1 获取网卡设备

根据网卡名称(如myeth1),获取网络设备,是通过__dev_get_by_name函数来实现的。

net是网络设备空间,用来实现网络空间隔离,其dev_name_head指向一个hlist_head数组。根据传入的网卡名称,计算出该网卡设备在数组中哪个hlist_head上。最后遍历挂到此hlist_head上的所有网络设备(net_device),如果名称一致,则为所查找的网络设备。由于还未为tun驱动增加网络设备,因此__dev_get_by_name返回空。

2.2 申请网络设备

申请网络设备,是通过来实现的。

dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,NET_NAME_UNKNOWN, tun_setup, queues,queues);struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,unsigned char name_assign_type,void (*setup)(struct net_device *),unsigned int txqs, unsigned int rxqs)
{struct net_device *dev;unsigned int alloc_size;struct net_device *p;alloc_size = sizeof(struct net_device);if (sizeof_priv) {alloc_size += sizeof_priv;}p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_RETRY_MAYFAIL);setup(dev);return dev;
}

在alloc_netdev_mqs,申请的内存的大小为sizeof(struct net_device) + sizeof(struct tun_struct),即同时分配了net_device和tun_struct两个结构。申请完内存后,调用setup,即tun_setup。

2.2.1 设置网络设备

tun_chr_ioctl

|- __tun_chr_ioctl

  |- tun_set_iff

    |- alloc_netdev_mqs

      |- tun_setup

 内核申请空间时,同时申请了net_device和tun_struct,net_device的后面,紧挨者的是tun_struct。netdev_priv就是通过此方法,得到tun_struct的地址。

static void tun_setup(struct net_device *dev)
{struct tun_struct *tun = netdev_priv(dev);tun->owner = INVALID_UID;tun->group = INVALID_GID;// 设置ethtool_opsdev->ethtool_ops = &tun_ethtool_ops;dev->needs_free_netdev = true;// 设置destructordev->priv_destructor = tun_free_netdev;/* We prefer our own queue length */dev->tx_queue_len = TUN_READQ_SIZE;
}

让我们再回到tun_set_iff中。

static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
{dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,NET_NAME_UNKNOWN, tun_setup, queues,queues);err = dev_get_valid_name(net, dev, name/*tun1*/); // 将用户空间传入的name拷贝到dev->namedev_net_set(dev, net); // 设置网络空间, dev->nd_net = netdev->rtnl_link_ops = &tun_link_ops;tun = netdev_priv(dev);  // 取到对应的tun_structtun->dev = dev; // 关联tun_struct和net_devicetun_net_init(dev); // 初始化mac地址等err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI); // tfile->tun = tunerr = register_netdevice(tun->dev); // 注册网络设备
}

为了理清各个结构之间的关系,直接看下图吧:

 2.3 关联tun_file和tun_struct

前面说过,第一次调用tun_get时,返回的结果为空,因为tun_file和tun_struct还没有进行关联,两个结构是在下面进行关联的。

static int tun_attach(struct tun_struct *tun, struct file *file,
              bool skip_filter, bool napi)
{
    rcu_assign_pointer(tfile->tun, tun);
}

后面就可以调用tun_get,通过tun_file获取到tun_struct了。

2.4 注册网络设备

注册网络设备,除了调用netdev_register_kobject在sysfs中注册跟网络设备关联的项外,还调用call_netdevice_notifiers,将NETDEV_POST_INIT和NETDEV_REGISTER事件,通知到已添加到netdev_chain链表中的notifier_block;将网络设备添加到第一张图所示的链表中。

int register_netdevice(struct net_device *dev)
{ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);ret = netdev_register_kobject(dev);list_netdevice(dev); // 将dev添加到指定的hlist_head列表中ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
}static void list_netdevice(struct net_device *dev)
{struct net *net = dev_net(dev);hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
}

http://www.yayakq.cn/news/846701/

相关文章:

  • studio网站开发广州定制网站建设公司
  • phpcms建站教程泛站群
  • 做一个网站大概需要多少钱怎么登陆wordpress后台
  • 织梦网站主页合肥发布网
  • 影响网站pr的主要因素有哪些wordpress图像并排
  • 番禺龙美村做网站网站空间域名每年都得交吗
  • 深圳比较好的建站公司房地产网站开发公司电话
  • 图片手机网站建设找人做网站服务器不是自己的怎么办
  • 做招聘信息的网站有哪些内容制作成长纪念册
  • 博客网站搭建郴州网站设计较好的公司
  • 乐陵网站制作商业计划书免费word版
  • 单县网站wordpress如何更换主题
  • 网页美工设计网站拼多多网上购物商城
  • dz网站建设教程俄罗斯乌克兰为什么打仗
  • html5网站后台页面设计高端响应式网站建设
  • 沈阳网官方网站郑州网约车平台
  • iis网站伪静态网站中国建设银行龙卡网站
  • 手机网站制作相关文章福州做网站价格
  • 百度网站联盟推广建网站为什么每年都要续费
  • 宜宾网站建设88sou苏州哪家做网站好些
  • 做网站需要备案几次广州中小企业seo推广运营
  • 在别人网站做的友链_为何百度检测带后缀cnindex.asp自建网上商城
  • 网站管理后台密码忘记了湛江哪里有建网站
  • 查询网站流量的网址绍兴seo
  • 任丘住房建设局网站大连网站关键字优化
  • 网站设置二级域名好吗建设网站的费用入什么科目
  • 网站建设网页怎么排列顺序公司网络推广怎么做
  • 南京网站关键词成品网站哪个好
  • 微信小程序开发和网站开发的区别网站设计布局的重要性
  • 一个网站需要多少网页排名优化的公司