/*
博主注明:
编译环境: Ubuntu 10.4 编译器:arm-linux-gcc
硬件环境:i.mx28 嵌入式linux版本 2.6.15
介绍:
参考ethtool工具源代码,发现在对网卡的ioctl操作中,可以读出网卡的状态
*/
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/file.h> #include <netinet/in.h> #include <linux/if.h> #include <string.h> #include <sys/types.h> #include <arpa/inet.h> #include <sys/ioctl.h> //由于嵌入式linux貌似没有对ethtool_value这个结*构体的定义,但在非嵌入式的版本里是有的,所以直接抄过来= =... struct ethtool_value { int cmd; int data; }; //以下两个宏和ioctl有关,从网卡里获取网线的状态的关键就在这里 #define ETHTOOL_GLINK 0x0000000a #define SIOCETHTOOL 0x8946 #define UNCONNECT 0 #define CONNECT 1 int main(int argc, char **argv) { int i, fd, fd2, fdtablesize, sock, last, ret; pid_t pid; struct sigaction sa; struct ifreq ifr; struct ethtool_value edata; edata.cmd = ETHTOOL_GLINK; edata.data = 0; //以下是产生一个守*护进程的方法,具体注解就不再赘述,之前的博文里有详解 umask(0); sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; //shutdown some signal if(sigaction(SIGTTOU, &sa, NULL) < 0) { printf("can't ignore SIGTTOU\n"); return -1; } if(sigaction(SIGTTIN, &sa, NULL) < 0) { printf("can't ignore SIGTTIN\n"); return -1; } if(sigaction(SIGTSTP, &sa, NULL) < 0) { printf("can't ignore SIGTSTP\n"); return -1; } if(sigaction(SIGHUP, &sa, NULL) < 0) { printf("can't ignore SIGHUP\n"); return -1; } //terminate the father thread first if(fork() != 0) { exit(1); } if(setsid() < 0) { exit(1); } //terminate the father thread second if(fork() != 0) { exit(1); } //change work dir to root if(chdir("/") == -1) { exit(1); } //shutdown some fds for(fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) { close(fd); } if(sigaction(SIGCHLD, &sa, NULL)) { printf("can't ignore SIGCHLD\n"); return -1; } //access a socket sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock == -1) { return -1; } //这里是将要查询的端口名拷贝到指定位置 strcpy(ifr.ifr_name, "eth0"); ifr.ifr_data = (char *)&edata; //获取状态 ioctl(sock, SIOCETHTOOL, &ifr); last = edata.data; //不断的读取网卡的状态 while(1) { //偶尔也让它休息一下^_^ sleep(1); ioctl(sock, SIOCETHTOOL, &ifr); //如果状态没有改变,就跳过,直接执行下一次查询 if(edata.data == last) { continue; } else { if(last == UNCONNECT) //如果网线被插上了 { //打开一个子进程,在里面调用一个脚本 if(fork() == 0) { // pid = getpid(); ret = execl("/data/work/ma_to_mt.sh", "master", NULL); if(ret < 0) { exit(1); } // return 0; //这里没有必要使用return 因为execl执行了就不会返回了 } last = CONNECT; //把状态改为已连接 } else if(last == CONNECT) //如果断开了网线 { if(fork() == 0) //开一个子进程,运行另一个脚本 { // pid = getpid(); ret = execl("/data/work/mt_to_ma.sh", "managed", NULL); if(ret < 0) { exit(1); } } last = UNCONNECT; //状态改为已断开 } } waitpid(-1, NULL ,0); //这个回收子进程的动作貌似也是没必要的= =.... } return 0; }