首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言 Linux 網卡狀態檢測:getifaddrs 高級接口實現

     編輯:關於C

Linux 下檢測網卡鏈路狀態(UP/DOWN、插拔、連接),傳統 ioctl(SIOCGIFFLAGS) 需手動構造 ifreq、遍歷接口。現代 getifaddrs() 直接返回鏈表,代碼量減半,可移植性更強。本文給出生產級實現。

核心 API:getifaddrs

#include 
int getifaddrs(struct ifaddrs **ifap);
void freeifaddrs(struct ifaddrs *ifap);

struct ifaddrs {
    struct ifaddrs *ifa_next;
    char *ifa_name;          // 接口名(eth0, lo...)
    unsigned int ifa_flags;  // IFF_UP, IFF_RUNNING, IFF_LOOPBACK...
    struct sockaddr *ifa_addr;      // 地址
    struct sockaddr *ifa_netmask;   // 掩碼
    struct sockaddr *ifa_broadaddr; // 廣播
    struct sockaddr *ifa_dstaddr;   // 目標地址
    void *ifa_data;                 // 驅動私有數據
};

狀態判斷邏輯

  • IFF_UP:管理狀態 UP(ip link set up)。
  • IFF_RUNNING:物理鏈路載波檢測(網線插好/無線關聯)。
  • IFF_LOWER_UP(內核 2.6.31+):物理層面 UP,更準確。
  • 組合判斷:
    • !UP → 管理員關閉 (DOWN)
    • UP && !RUNNING → 網線未插/無線未連 (UNPLUGGED)
    • UP && RUNNING → 正常連接 (LINKED)

完整檢測函數

#include 
#include 
#include 
#include 
#include 
#include 

int check_link_status(const char *ifname) {
    struct ifaddrs *ifa, *iflist;
    if (getifaddrs(&iflist) < 0) {
        perror("getifaddrs");
        return -1;
    }

    for (ifa = iflist; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family != AF_INET) continue; // 僅看 IPv4 接口
        if (strcmp(ifa->ifa_name, ifname) != 0) continue;

        unsigned flags = ifa->ifa_flags;
        if (!(flags & IFF_UP)) {
            printf("DEVICE_DOWN\n");
            freeifaddrs(iflist);
            return 1;
        }
        if (!(flags & IFF_RUNNING)) {
            printf("DEVICE_UNPLUGGED\n");
            freeifaddrs(iflist);
            return 2;
        }
        printf("DEVICE_LINKED\n");
        freeifaddrs(iflist);
        return 3;
    }

    fprintf(stderr, "DEVICE_NOT_FOUND: %s\n", ifname);
    freeifaddrs(iflist);
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <接口名>\n", argv[0]);
        return 1;
    }
    int ret = check_link_status(argv[1]);
    fprintf(stderr, "狀態碼: %d\n", ret);
    return ret == 3 ? 0 : 1;
}

編譯運行

gcc check_link.c -o check_link
./check_link eth0
# 輸出示例:
# DEVICE_LINKED
# 狀態碼: 3

優勢對比

維度ioctl + SIOCGIFFLAGSgetifaddrs
代碼行數~40~25
多地址支持需多次 ioctl單次遍歷鏈表
IPv6 支持額外處理原生支持
可移植性Linux/BSD 差異大POSIX.1-2001 標準
性能系統調用多單次系統調用

注意事項

  • 需 root 權限或 CAP_NET_ADMIN 讀取接口旗標。
  • 虛擬接口(docker0, veth, lo)同樣適用,可過濾 IFF_LOOPBACK。
  • 內核 < 2.6.31 無 IFF_LOWER_UP,用 IFF_RUNNING 替代。
  • 嵌入式系統可能無 ifaddrs.h,需回退 ioctl 方案。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved