写一个检测网线是否被拔出的守护进程(嵌入式设备上)

/*

        博主注明:

               编译环境: 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;
}



你可能感兴趣的:(thread,struct,socket,null,嵌入式,Signal)