写一个检测网线是否被拔出的守护进程(嵌入式设备上)
2019-07-12 16:36发布
生成海报
/*
博主注明:
编译环境: Ubuntu 10.4 编译器:arm-linux-gcc
硬件环境:i.mx28 嵌入式linux版本 2.6.15
介绍:
参考ethtool工具源代码,发现在对网卡的ioctl操作中,可以读出网卡的状态
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//由于嵌入式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
");
return -1;
}
if(sigaction(SIGTTIN, &sa, NULL) < 0)
{
printf("can't ignore SIGTTIN
");
return -1;
}
if(sigaction(SIGTSTP, &sa, NULL) < 0)
{
printf("can't ignore SIGTSTP
");
return -1;
}
if(sigaction(SIGHUP, &sa, NULL) < 0)
{
printf("can't ignore SIGHUP
");
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
");
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;
}
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮