閱讀本文前,請先學習下面幾篇文章
《搞懂進程組、會話、控制終端關系,才能明白守護進程干嘛的?》
《安卓如何設置開機自動啟動某個程序?ramdisk + init.rc給你搞定》
一、usb網卡應該如何實現?
前文講了如何利用開源軟件ifplugd實現監測網口狀態變化,
ifplugd的確可以實現監測網卡的狀態,并執行相應腳本,
但是有個前提,就是網口已經注冊到系統中,即用ifconfig -a能查看到
如何是usb網卡這種設備,在插入usb口之后網口設備才會注冊,
使用過程中可能隨時會拔掉usb網卡,
那么這種情況下,要想設置usb網卡,那么就就需要修改ifplugd程序。
為了方便大家理解,本文給大家講解如何自己實現一個簡化的程序ethcheck,
可以實現自動監測網卡是否存在
rk3568所有網口:
rk3568_r:/system # ifconfig -a lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope: Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 dummy0 Link encap:Ethernet HWaddr fa:85:6c:74:1b:7d inet6 addr: fe80::f885:6cff:fe74:1b7d/64 Scope: Link UP BROADCAST RUNNING NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:560 sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 ip6tnl0 Link encap:UNSPEC NOARP MTU:1452 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 eth1 Link encap:Ethernet HWaddr 5a:53:63:cf:dd:0b Driver rk_gmac-dwmac UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 Interrupt:51 ip_vti0 Link encap:UNSPEC NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 eth0 Link encap:Ethernet HWaddr 5e:53:63:cf:dd:0b Driver rk_gmac-dwmac UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0 Interrupt:38 ip6_vti0 Link encap:UNSPEC NOARP MTU:1364 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 TX bytes:0
二、程序設計
0.程序框圖
1. 設置程序為守護進程
因為該程序最終要在后臺執行,并且常駐內存,所以必須將該進程設置為守護進程
關于守護進程的內容,請參考下面文章:
《搞懂進程組、會話、控制終端關系,才能明白守護進程干嘛的?》
參考代碼如下:
void init_daemon(void){ int pid; int i; if(pid=fork()) exit(0);//是父進程,結束父進程? else if(pid< 0) exit(1);//fork失敗,退出? //是第一子進程,后臺繼續執行? setsid();//第一子進程成為新的會話組長和進程組長?//并與控制終端分離? chdir("/tmp");//改變工作目錄到/tmp? umask(0);//重設文件創建掩模? for(i=0;i< NOFILE;++i)//關閉打開的文件描述符? close(i); return;}
2. 確認制定網口是否存在?
要確認指定網口是否存在,主要通過/proc/net/dev
目錄下是否有該網口信息:
peng@ubuntu:~$ cat /proc/net/devInter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 26163 292 0 0 0 0 0 0 26163 292 0 0 0 0 0 0 eth0: 285444708 243273 0 0 0 0 0 0 91828270 88660 0 0 0 0 0 0
如何用C語言實現檢測指定網口,可以參考下面文章:
參考代碼:
static char * interface_name_cut (char *buf, char **name){ char *stat; /* Skip white space. Line will include header spaces. */ while (*buf == ' ') buf++; *name = buf; /* Cut interface name. */ stat = strrchr (buf, ':'); *stat++ = '\0'; return stat;}/*return value:1 exist 0:no*/ int check_interface_fromproc(char *interface){ FILE *fp; char buf[PROCBUFSIZ]; struct interface *ifp; char *name; /* Open /proc/net/dev. */ fp = fopen (_PATH_PROC_NET_DEV, "r"); if (fp == NULL) { printf("open proc file error\n"); return -1; } /* Drop header lines. */ fgets (buf, PROCBUFSIZ, fp); fgets (buf, PROCBUFSIZ, fp); /* Only allocate interface structure. Other jobs will be done in if_ioctl.c. */ while (fgets (buf, PROCBUFSIZ, fp) != NULL) { interface_name_cut (buf, &name); if(strcmp(interface,name)==0) return 1; } fclose(fp); return 0;}
3. 指定網口不存在
如果檢測網口不存在,則需要休眠,然后繼續監測/proc/net/dev
文件。
4. 如果指定網口存在
則獲取該網口的IP地址,然后比較是否是指定的IP地址
網卡IP地址的獲取,主要通過系統調用ioctl()
的 SIOCGIFADDR
命令實現
關于如何用c語言操作網卡,擦靠下面文章
參考代碼如下:
int getLocalIp(const char *eth, char *ip) { struct ifreq ifr; struct sockaddr_in sin; int fd; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) { close(fd); return -1; } memcpy(&sin, &ifr.ifr_addr, sizeof(sin)); snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr)); close(fd); return 0;}
讀取的ip地址存放在參數ip
指向的內存中。
5. ip地址相同
如果網卡地址與指定的ip地址相同,那么不需要修改地址,休眠一段時間(根據實際操作的頻率設置時間), 然后再監測網口是否存在
6. IP地址不相同
如果ip地址不相同,則需要修改ip地址,
執行我們提前設置好的腳本if.sh即可
#!/bin/bashIPADDR=192.168.40.8ETHPORT=eth1echo "ethcheck set" $ETHPORT $IPADDRecho $#echo $0echo $1echo $2if [ $# -eq 2 ];then if [ $1 = $ETHPORT ];then echo $ETHPORT if [ $2 = "up" ];then ifconfig $ETHPORT $IPADDR sleep 1 ip rule add from all lookup main pref 9000 sleep 1 echo 1 > /proc/sys/net/ipv4/ip_forward iptables -F echo "set" $ETHPORT "done" elif [ $2 = "down" ];then echo "down" elif [ $2 = "disable" ];then echo "disable" elif [ $2 = "error" ];then echo "error" fi fifi
7. 設置為開機啟動
要實現開機就自動運行ifplugd,可以參考下面文章:
《安卓如何設置開機自動啟動某個程序?ramdisk + init.rc給你搞定》
資料獲取
完整代碼,點贊留言,后臺回復:eth
更多嵌入式Linux知識,請關注up主,添加我的vx!