寫一個檢測網線是否被拔出的守護進程(嵌入式設備上)

#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;
}
 

 

 

  1. #include <linux/sockios.h> 
  2. #include <sys/socket.h>  
  3. #include <sys/ioctl.h>  
  4. #include <linux/if.h>  
  5. #include <string.h>  
  6. #include <stdio.h>  
  7. #include <stdlib.h>  
  8. #include <unistd.h>  
  9.   
  10. #define ETHTOOL_GLINK        0x0000000a /* Get link status (ethtool_value) */  
  11.   
  12. typedef enum { IFSTATUS_UP, IFSTATUS_DOWN, IFSTATUS_ERR } interface_status_t;  
  13.   
  14. typedef signed int u32;  
  15.   
  16. /* for passing single values */  
  17. struct ethtool_value  
  18. {  
  19.     u32    cmd;  
  20.     u32    data;  
  21. };  
  22.   
  23. interface_status_t interface_detect_beat_ethtool(int fd, char *iface)  
  24. {  
  25.     struct ifreq ifr;  
  26.     struct ethtool_value edata;  
  27.      
  28.     memset(&ifr, 0, sizeof(ifr));  
  29.     strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);  
  30.   
  31.     edata.cmd = ETHTOOL_GLINK;  
  32.     ifr.ifr_data = (caddr_t) &edata;  
  33.   
  34.     if (ioctl(fd, SIOCETHTOOL, &ifr) == -1)  
  35.     {  
  36.         perror("ETHTOOL_GLINK failed ");  
  37.         return IFSTATUS_ERR;  
  38.     }  
  39.   
  40.     return edata.data ? IFSTATUS_UP : IFSTATUS_DOWN;  
  41. }  
  42.   
  43. int main (int argc, char *argv[])  
  44. {  
  45.     FILE *fp;  
  46.     interface_status_t status;  
  47.     char buf[512] = {'\0'};  
  48.     char hw_name[10] = {'\0'};  
  49.     char *token = NULL;  
  50.   
  51.     /* 獲取網卡名稱 */  
  52.     if ((fp = fopen("/proc/net/dev", "r")) != NULL)  
  53.     {  
  54.         while (fgets(buf, sizeof(buf), fp) != NULL)  
  55.         {  
  56.             if(strstr(buf, "eth") != NULL)  
  57.             {         
  58.                 token = strtok(buf, ":");  
  59.                 while (*token == ' ') ++token;  
  60.                 strncpy(hw_name, token, strlen(token));  
  61.             }  
  62.         }  
  63.     }  
  64.     fclose(fp);  
  65. //方法一:查看一個文件文件,相對來說比較簡單  
  66. #if 1  
  67.     char carrier_path[512] = {'\0'};  
  68.       
  69.     memset(buf, 0, sizeof(buf));   
  70.     snprintf(carrier_path, sizeof(carrier_path), "/sys/class/net/%s/carrier", hw_name);  
  71.     if ((fp = fopen(carrier_path, "r")) != NULL)  
  72.     {  
  73.         while (fgets(buf, sizeof(buf), fp) != NULL)  
  74.         {  
  75.             if (buf[0] == '0')  
  76.             {  
  77.                 status = IFSTATUS_DOWN;  
  78.             }  
  79.             else  
  80.             {  
  81.                 status = IFSTATUS_UP;  
  82.             }  
  83.         }  
  84.     }  
  85.     else  
  86.     {  
  87.         perror("Open carrier ");  
  88.     }  
  89.     fclose(fp);  
  90. #endif  
  91.   
  92. //方法二:用函數吧!有點複雜,但是也是一種有效的辦法  
  93. #if 1  
  94.     int fd;  
  95.       
  96.     if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  97.     {  
  98.         perror("socket ");  
  99.         exit(0);  
  100.     }  
  101.     status = interface_detect_beat_ethtool(fd, hw_name);  
  102.     close(fd);  
  103. #endif  
  104.   
  105.     switch (status)  
  106.     {  
  107.         case IFSTATUS_UP:  
  108.             printf("%s : link up\n", hw_name);  
  109.             break;  
  110.           
  111.         case IFSTATUS_DOWN:  
  112.             printf("%s : link down\n", hw_name);  
  113.             break;  
  114.           
  115.         default:  
  116.             printf("Detect Error\n");  
  117.             break;  
  118.     }  
  119.   
  120.     return 0;  

注:第一種方法適用於2.6內核以後的版本,第二中方法適用於2.4及以前的版本,2.4及之前的版本沒有/sys/class/net/%s/carrier這個目錄

 

 

  1. #include <unistd.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4. #include <string.h>  
  5.   
  6. int GetNetStat( )  
  7. {  
  8.     char    buffer[BUFSIZ];  
  9.     FILE    *read_fp;  
  10.     int        chars_read;  
  11.     int        ret;  
  12.      
  13.     memset( buffer, 0, BUFSIZ );  
  14.     read_fp = popen("ifconfig eth0 | grep RUNNING", "r");  
  15.     if ( read_fp != NULL )  
  16.     {  
  17.         chars_read = fread(buffer, sizeof(char), BUFSIZ-1, read_fp);  
  18.         if (chars_read > 0)  
  19.         {  
  20.             ret = 1;  
  21.         }  
  22.         else  
  23.         {  
  24.             ret = -1;  
  25.         }  
  26.         pclose(read_fp);  
  27.     }  
  28.     else  
  29.     {  
  30.         ret = -1;  
  31.     }  
  32.   
  33.     return ret;  
  34. }  
  35.   
  36.   
  37. int main()  
  38. {  
  39.     int i=0;  
  40.     i = GetNetStat();  
  41.     printf( "\nNetStat = %d\n", i );  
  42.     return 0;  
  43. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章