在 Linux 系統編程中,檢測網卡(網路介面)的連線狀態是常見需求。傳統做法需打開 Socket、呼叫 ioctl 並解析 ifreq 結構,程式碼繁瑣且易出錯。本文介紹一種更精簡的方法:利用 getifaddrs() 函數一次性獲取所有介面資訊,輕鬆判斷網卡是否啟用、纜線是否連接。
getifaddrs() 會填充一個 struct ifaddrs 鏈表,每個節點包含介面名稱、位址族、旗標(flags)等資訊。我們只需遍歷鏈表,找到目標介面並檢查其 ifa_flags 中的 IFF_UP(介面啟用)與 IFF_RUNNING(實體連線)兩個旗標即可。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <ifaddrs.h>
int c_ifaddrs_netlink_status(const char *if_name) {
struct ifaddrs *ifa = NULL, *ifList;
if (getifaddrs(&ifList) < 0) {
return -1;
}
for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
if (strcmp(ifa->ifa_name, if_name) == 0) {
if (!(ifa->ifa_flags & IFF_UP)) {
printf("DEVICE_DOWN\r\n");
freeifaddrs(ifList);
return 1;
}
if (!(ifa->ifa_flags & IFF_RUNNING)) {
printf("DEVICE_UNPLUGGED\r\n");
freeifaddrs(ifList);
return 2;
}
printf("DEVICE_LINKED\r\n");
freeifaddrs(ifList);
return 3;
}
}
}
fprintf(stderr, "DEVICE_NONE\r\n");
freeifaddrs(ifList);
return 0;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: %s <ethname>\r\n", argv[0]);
return -1;
}
int status = c_ifaddrs_netlink_status(argv[1]);
fprintf(stderr, "c_ifaddrs_netlink_status if_status = %d\n", status);
return 0;
}
getifaddrs(&ifList) 動態分配記憶體,使用完畢必須呼叫 freeifaddrs() 釋放。sa_family == AF_INET 的節點,避免干擾。IFF_UP 未置位 → 介面被管理員關閉(DEVICE_DOWN)。IFF_RUNNING 未置位 → 纜線未插或無載波(DEVICE_UNPLUGGED)。DEVICE_LINKED)。DEVICE_NONE 並回傳 0。$ gcc -o net_check net_check.c
$ ./net_check eth0
DEVICE_LINKED
c_ifaddrs_netlink_status if_status = 3
ioctl,程式碼行數減少 50% 以上。這個精簡版實現非常適合嵌入式裝置、網路監控工具或系統管理腳本中快速檢測網卡鏈路狀態。