• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > linux tun/tap设备的实现(kennel 3.10)

linux tun/tap设备的实现(kennel 3.10)

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了tun/tap,tun/tap网卡未开启,tun/tap网卡驱动,tun/tap驱动,tun/tap网卡驱动下载等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

linux tun/tap设备的实现(kennel 3.10)


linux tun/tap设备的实现(kennel 3.10)

——lvyilong316(转载请注明出处)

什么是tun/tap?

TUN/TAP虚拟网络设备为用户空间程序提供了网络数据包的发送和接收能力。他既可以当做点对点设备(TUN),也可以当做以太网设备(TAP)。实际上,不仅Linux支持TUN/TAP虚拟网络设备,其他UNIX也是支持的,他们之间只有少许差别。

TUN/TAP虚拟网络设备的原理比较简单,他在Linux内核中添加了一个TUN/TAP虚拟网络设备的驱动程序和一个与之相关连的字符设备/dev/net/tun,字符设备tun作为用户空间和内核空间交换数据的接口。当内核将数据包发送到虚拟网络设备时,数据包被保存在设备相关的一个队列中,直到用户空间程序通过打开的字符设备tun的描述符读取时,它才会被拷贝到用户空间的缓冲区中,其效果就相当于,数据包直接发送到了用户空间。通过系统调用write发送数据包时其原理与此类似。

值得注意的是:一次read系统调用,有且只有一个数据包被传送到用户空间,并且当用户空间的缓冲区比较小时,数据包将被截断,剩余部分将永久地消失,write系统调用与read类似,每次只发送一个数据包。所以在编写此类程序的时候,请用足够大的缓冲区,直接调用系统调用read/write,避免采用C语言的带缓存的IO函数。

TUN/TAP是一类虚拟网卡的驱动。网卡驱动很好理解,就是netdev+driver,最后将数据包通过这些驱动发送出去,netdev可以参考内核或者OVS代码,基本使用的就是几个钩子函数。

虚拟网卡就是没有物理设备的网卡,那么他的驱动就是需要开发人员自己编写。一般虚拟网卡用于实现物理网卡不愿意做的事情,例如tunnel封装(用于vpn,openvpn( http://openvpn.sourceforge.net)和Vtun( http://vtun.sourceforge.net)),多个物理网卡的聚合等。一般使用虚拟网卡的方式与使用物理网卡一样,在协议栈中通过回调函数call到虚拟网卡的API,经过虚拟网卡处理之后的数据包再由协议栈发送出去。

tun/tap的使用

linux2.4内核之后代码默认编译tun、tap驱动,使用的时候只需要将模块加载即可(modprobe tun,mknod /dev/net/tun c 10 200)。运行tun、tap设备之后,会在内核空间添加一个杂项设备(miscdevice,类比字符设备、块设备等)/dev/net/tun,实质上是主设备号10的字符设备。从功能上看,tun设备驱动主要应该包括两个部分,一是虚拟网卡驱动,其实就是虚拟网卡中对skb进行封装解封装等操作;二是字符设备驱动,用于内核空间与用户空间的交互。

源代码在/drivers/net/tun.c中,与其他netdev类似,tun这个netdev也提供open、close、read、write等API。在分析TUN/TAP驱动实现前,我们先看下如何使用。使用tun/tap设备的示例程序(摘自openvpn开源项目http://openvpn.sourceforge.net,tun.c文件)


  1. int open_tun (const char *dev, char *actual, int size)
  2. {
  3. struct ifreq ifr;
  4. int fd;
  5. char *device = "/dev/net/tun";
  6. if ((fd = open (device, O_RDWR)) < 0) //创建描述符
  7. msg (M_ERR, "Cannot open TUN/TAP dev %s", device);
  8. memset (&ifr, 0, sizeof (ifr));
  9. ifr.ifr_flags = IFF_NO_PI;
  10. if (!strncmp (dev, "tun", 3)) {
  11. ifr.ifr_flags |= IFF_TUN;
  12. }
  13. else if (!strncmp (dev, "tap", 3)) {
  14. ifr.ifr_flags |= IFF_TAP;
  15. }
  16. else {
  17. msg (M_FATAL, "I don't recognize device %s as a TUN or TAP device",dev);
  18. }
  19. if (strlen (dev) > 3) /* unit number specified? */
  20. strncpy (ifr.ifr_name, dev, IFNAMSIZ);
  21. if (ioctl (fd, TUNSETIFF, (void *) &ifr) < 0) //打开虚拟网卡
  22. msg (M_ERR, "Cannot ioctl TUNSETIFF %s", dev);
  23. set_nonblock (fd);
  24. msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
  25. strncpynt (actual, ifr.ifr_name, size);
  26. return fd;
  27. }


调用上述函数后,就可以在shell命令行下使用ifconfig 命令配置虚拟网卡了:

ifconfigdevname10.0.0.1 up

route add -net 10.0.0.2 netmask255.255.255.255 devdevname

配置好虚拟网卡地址后,就可以通过生成的字符设备描述符,在程序中使用read和write函数就可以读取或者发送给虚拟的网卡数据了。

tun/tap的实现

tun/tap设备驱动的开始也是init函数,其中主要调用了misc_register注册了一个miscdev设备。


  1. static int __init tun_init(void)
  2. {
  3. /*……*/
  4. ret = misc_register(&tun_miscdev);
  5. /*……*/
  6. }


而tun_miscdev得定义如下:


  1. static struct miscdevice tun_miscdev = {
  2. .minor = TUN_MINOR,
  3. .name = "tun",
  4. .nodename = "net/tun",
  5. .fops = &tun_fops,
  6. }


注册完这个设备之后将在系统中生成一个“/dev/net/tun”文件,同字符设备类似,当应用程序使用open系统调用打开这个文件时,将生成file文件对象,而其file_operations将指向tun_fops。


  1. static const struct file_operations tun_fops = {
  2. .owner= THIS_MODULE,
  3. .llseek = no_llseek,
  4. .read = do_sync_read,
  5. .aio_read = tun_chr_aio_read,
  6. .write = do_sync_write,
  7. .aio_write = tun_chr_aio_write,
  8. .poll= tun_chr_poll,
  9. .unlocked_ioctl= tun_chr_ioctl,
  10. #ifdef CONFIG_COMPAT
  11. .compat_ioctl = tun_chr_compat_ioctl,
  12. #endif
  13. .open= tun_chr_open,
  14. .release = tun_chr_close,
  15. .fasync = tun_chr_fasync
  16. };


下面我们以应用层使用的步骤来分析内核的对应实现。应用层首先调用open打开“/dev/net/tun”,这将最终调用tun_fops的open函数,即tun_chr_open。

l tun_chr_open


  1. static int tun_chr_open(struct inode *inode, struct file * file)
  2. {
  3. struct tun_file *tfile;

  4. DBG1(KERN_INFO, "tunX: tun_chr_open\n");

  5. /*分配并初始化struct tun_file结构*/
  6. tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL,
  7. &tun_proto);
  8. if (!tfile)
  9. return -ENOMEM;
  10. rcu_assign_pointer(tfile->tun, NULL);
  11. tfile->net = get_net(current->nsproxy->net_ns);
  12. tfile->flags = 0;

  13. rcu_assign_pointer(tfile->socket.wq, &tfile->wq);
  14. init_waitqueue_head(&tfile->wq.wait);

  15. tfile->socket.file = file;
  16. /*设置struct tun_file的socket成员ops*/
  17. tfile->socket.ops = &tun_socket_ops;

  18. sock_init_data(&tfile->socket, &tfile->sk);
  19. sk_change_net(&tfile->sk, tfile->net);

  20. tfile->sk.sk_write_space = tun_sock_write_space;
  21. tfile->sk.sk_sndbuf = INT_MAX;
  22. /*将struct tun_file作为file的私有字段,而file就是每次应用调用open打开/dev/net/tun生成的*/
  23. file->private_data = tfile;
  24. set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
  25. INIT_LIST_HEAD(&tfile->next);

  26. sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);

  27. return 0;
  28. }


经过这个函数后,整个数据结构的关系就如下图所示。注意这里的struct file结构就是每次应用调用open打开/dev/net/tun生成的。

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • linux tun/tap设备的实现(kennel 3.10)

相关文章

  • 2017-05-26android中的回调请求的个人理解,android回调
  • 2017-05-26Android定位&amp;地图&amp;导航——基于百度地图移动获取位置和自动定位,android定位城市
  • 2017-05-26在Windows下快速搭建React Native Android开发环境
  • 2017-05-26VS2015墙内创建ionic2 【利用nrm更换源,完美!】,vs2015ionic2
  • 2017-05-26修改Android系统关机动画,android关机动画
  • 2017-05-26源码解析Android中AsyncTask的工作原理
  • 2017-05-26Android中使用ExpandableListView实现好友分组,expandablelistview
  • 2017-05-26Android开发:内存机制分析——堆和栈
  • 2017-05-26菜单(Menu)的三中创建方式——Android开发之路2,menuandroid
  • 2017-05-26Android的Kotlin秘方(I):OnGlobalLayoutListener,

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android开发9:网络访问&amp;Web服务开发,android开发9访问
    • android中的回调请求的个人理解,android回调
    • 8.1.2 Android中的13种Drawable小结 Part 2
    • Android--向SD卡读写数据
    • 首页3--界面上拉下拉的回弹效果,3--拉下
    • Android中Intent在Activity之间传递对象[Serializable或Parcelable]
    • Android学习笔记(30):选项卡TabHost浅析
    • 浅谈Windows下SVN在Android Studio中的配置和基本使用,svnandroid
    • dspam运维记录
    • 解析Service之你需要了解的一些东东,解析Service之东东

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有