You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ioctl创建TAP设备异常:程序执行成功但无设备生成求助

TAP设备创建成功但无法找到的问题排查与修复

问题描述

提供的C代码执行后提示创建成功,但系统中找不到对应的TAP设备tap99。代码如下:

#include <fcntl.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    struct ifreq ifr;
    int fd = open("/dev/net/tun", O_RDWR);
    if(fd < 0) 
    {
        perror("open tun fail");
        return -1;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_UP;
    // set tap device name
    strncpy(ifr.ifr_name, "tap99", IFNAMSIZ);
    if(ioctl(fd, TUNSETIFF, (void*)(&ifr)) < 0)
    {
        perror("ioctl fail");
        close(fd);
        return -1;
    }
    printf("TAP device %s created successfully\n", ifr.ifr_name);
    close(fd);
    return 0;
}

已完成的排查步骤:

  • 内核对TUN/TAP支持正常:
    [root@Qwons c_test]# lsmod | grep tun
    tun                    49152  2
    [root@Qwons c_test]# lsmod | grep tap
    tap                    28672  0
    [root@Qwons c_test]# ll /dev/net/tun
    total 0
    crw-rw-rw- 1 root root 10, 200 Dec 23 23:38 tun
    
  • 执行程序后,ip和ifconfig均无法找到tap99:
    [root@Qwons c_test]# ./modify
    TAP device tap99 created successfully
    [qwons@Qwons c_test]$ ip link set tap99 up
    Cannot find device "tap99"
    [qwons@Qwons c_test]$ ifconfig | grep tap99
    [qwons@Qwons c_test]$ 
    

原因分析

核心问题是程序创建TAP设备后立刻关闭了文件描述符。Linux的TUN/TAP设备与文件描述符强绑定,当对应的fd被关闭时,内核会自动销毁该TAP设备,因此程序退出后设备直接消失,自然无法通过系统命令查到。

另外,代码中的IFF_UP标志无实际作用——设备创建后未完成激活流程,且fd关闭后设备直接销毁,该标志不会生效。

修复方法

有两种常用的修复思路:

方法1:保持文件描述符打开,维持程序运行

修改代码,在设备创建成功后不立即关闭fd,通过让程序持续运行(如等待信号、死循环或业务逻辑)来保留TAP设备:

#include <fcntl.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    struct ifreq ifr;
    int fd = open("/dev/net/tun", O_RDWR);
    if(fd < 0) 
    {
        perror("open tun fail");
        return -1;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI; // 移除IFF_UP,后续用ip命令手动激活
    strncpy(ifr.ifr_name, "tap99", IFNAMSIZ);
    if(ioctl(fd, TUNSETIFF, (void*)(&ifr)) < 0)
    {
        perror("ioctl fail");
        close(fd);
        return -1;
    }
    printf("TAP device %s created successfully. Keep running to maintain device...\n", ifr.ifr_name);
    
    // 保持程序运行,等待任意信号终止(如Ctrl+C)
    pause();
    
    close(fd);
    return 0;
}

编译运行后,打开新终端即可用ip link show tap99看到设备,还能执行ip link set tap99 up激活设备。

方法2:创建持久化TAP设备

如果需要设备在程序退出后依然存在,可通过TUNSETPERSIST ioctl命令设置持久化属性,这样即使关闭fd,设备也不会被销毁:

#include <fcntl.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    struct ifreq ifr;
    int fd = open("/dev/net/tun", O_RDWR);
    if(fd < 0) 
    {
        perror("open tun fail");
        return -1;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    strncpy(ifr.ifr_name, "tap99", IFNAMSIZ);
    if(ioctl(fd, TUNSETIFF, (void*)(&ifr)) < 0)
    {
        perror("ioctl fail");
        close(fd);
        return -1;
    }
    
    // 设置持久化,需root权限执行
    int persist = 1;
    if(ioctl(fd, TUNSETPERSIST, &persist) < 0)
    {
        perror("set persist fail");
        close(fd);
        return -1;
    }
    
    printf("Persistent TAP device %s created successfully\n", ifr.ifr_name);
    close(fd);
    return 0;
}

注意:TUNSETPERSIST需要以root权限执行,设置后设备会一直存在,直到手动执行ip link delete tap99删除。

内容的提问来源于stack exchange,提问作者Qwons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:52:18