如何写一个简单的守护(精灵)进程原型

这里首先假设读者知道守护进程的大概概念,下面我们直接看程序。

//****************

环境,OS = Ubuntu 10.4 编译器 = gcc 4.5.2

******************//

[plain] view plain copy print ?
  1. int main(int argc, char **argv) 
  2.  
  3.  
  4.    //因为下面要关掉某些信号,所以需要 
  5.  
  6.     struct sigaction sa; 
  7.  
  8.    int i, fd, fdtablesize; 
  9.  
  10.      
  11.  
  12.    //上来第一件事,调用umask将文件模式创建屏蔽字设置为0,为的是防止守护进程可能不具有对文件读写的权限 
  13.  
  14.     umask(0); 
  15.  
  16. //设置信号处理函数,SIG_IGN为忽略信号 
  17.  
  18.   sa.sa_handler = SIG_IGN; 
  19.  
  20. //sa.sa_mask这个成员的清零,一定要使用sigemtpy函数 
  21.  
  22. sigemptyset(&sa.sa_mask); 
  23.  
  24. sa.sa_flags = 0; 
  25.  
  26. //对以下几种信号做忽略处理 
  27.  
  28. sigaction(SIGTTOU, &sa, NULL); 
  29.  
  30. sigaction(SIGTTIN, &sa, NULL); 
  31.  
  32. sigaction(SIGTSTP, &sa, NULL); 
  33.  
  34. sigaction(SIGUP, &sa, NULL); 
  35.  
  36.   
  37.  
  38. //关闭父进程,使子进程成为孤儿进程,从而被init收养 
  39.  
  40. if(fork() != 0) 
  41.  
  42.  
  43.        exit(1); 
  44.  
  45. }    
  46.  
  47. //创建一个新会话 
  48.  
  49. if(setsid() < 0) 
  50.  
  51.  
  52.      exit(1); 
  53.  
  54.  
  55. //第二次退出父进程 
  56.  
  57. if(fork() != 0) 
  58.  
  59.  
  60.        exit(1); 
  61.  
  62.  
  63. //改变工作路径到root,防止出现工作目录被卸载的情况 
  64.  
  65. if(chidr("/") == -1) 
  66.  
  67.  
  68.       exit(1); 
  69.  
  70.  
  71. //关闭打开的文件描述符,包括标准输入输出和标准出错 
  72.  
  73. for(fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) 
  74.  
  75.  
  76.       close(fd); 
  77.  
  78.  
  79. //再次关掉信号 
  80.  
  81. sigaction(SIGCHLD, &sa, NULL); 
  82.  
  83. //进入一个死循环让守护进程常驻内存 
  84.  
  85. while(1) 
  86.  
  87.  
  88.       //do somthing 
  89.  
  90.        sleep(1); 
  91.  
  92.  
  93. //至此就完成了对一个守护进程的初始化 
  94.  
  95. return 0; 
  96.  

 

转自:http://blog.csdn.net/ti_tantbx/article/details/7019619

/*

        博主注明:

               编译环境: Ubuntu 10.4    编译器:arm-linux-gcc

               硬件环境:i.mx28  嵌入式linux版本 2.6.15

               介绍:

                             参考ethtool工具源代码,发现在对网卡的ioctl操作中,可以读出网卡的状态

*/


[plain] view plain copy print ?
  1. #include <stdio.h> 
  2. #include <unistd.h> 
  3. #include <stdlib.h> 
  4. #include <signal.h> 
  5. #include <sys/file.h> 
  6. #include <netinet/in.h> 
  7. #include <linux/if.h> 
  8. #include <string.h> 
  9. #include <sys/types.h> 
  10. #include <arpa/inet.h> 
  11. #include <sys/ioctl.h> 
  12.  
  13.   
  14.  
  15. //由于嵌入式linux貌似没有对ethtool_value这个结*构体的定义,但在非嵌入式的版本里是有的,所以直接抄过来= =... 
  16. struct ethtool_value { 
  17.     int cmd; 
  18.     int data; 
  19. }; 
  20.  
  21.   
  22.  
  23. //以下两个宏和ioctl有关,从网卡里获取网线的状态的关键就在这里 
  24. #define ETHTOOL_GLINK        0x0000000a 
  25. #define SIOCETHTOOL            0x8946 
  26. #define UNCONNECT                0 
  27. #define CONNECT                    1 
  28.  
  29. int main(int argc, char **argv) 
  30.     int i, fd, fd2, fdtablesize, sock, last, ret; 
  31.     pid_t pid; 
  32.  
  33.  
  34.     struct sigaction sa; 
  35.     struct ifreq ifr; 
  36.     struct ethtool_value edata; 
  37.  
  38.  
  39.     edata.cmd = ETHTOOL_GLINK; 
  40.     edata.data = 0; 
  41.     
  42. //以下是产生一个守*护进程的方法,具体注解就不再赘述,之前的博文里有详解 
  43.     umask(0); 
  44.     sa.sa_handler = SIG_IGN; 
  45.     sigemptyset(&sa.sa_mask); 
  46.     sa.sa_flags = 0; 
  47.  
  48.  
  49.     //shutdown some signal 
  50.     if(sigaction(SIGTTOU, &sa, NULL) < 0) 
  51.     { 
  52.         printf("can't ignore SIGTTOU\n"); 
  53.         return -1; 
  54.     } 
  55.     
  56.     if(sigaction(SIGTTIN, &sa, NULL) < 0) 
  57.     { 
  58.         printf("can't ignore SIGTTIN\n"); 
  59.         return -1; 
  60.     } 
  61.     
  62.     if(sigaction(SIGTSTP, &sa, NULL) < 0) 
  63.     { 
  64.         printf("can't ignore SIGTSTP\n"); 
  65.         return -1; 
  66.     } 
  67.     
  68.     if(sigaction(SIGHUP, &sa, NULL) < 0) 
  69.     { 
  70.         printf("can't ignore SIGHUP\n"); 
  71.         return -1; 
  72.     } 
  73.     
  74.     //terminate the father thread first 
  75.     if(fork() != 0) 
  76.     { 
  77.         exit(1); 
  78.     } 
  79.     if(setsid() < 0) 
  80.     { 
  81.         exit(1); 
  82.     } 
  83.     //terminate the father thread second 
  84.     if(fork() != 0) 
  85.     { 
  86.         exit(1); 
  87.     } 
  88.     //change work dir to root 
  89.     if(chdir("/") == -1) 
  90.     { 
  91.         exit(1); 
  92.     } 
  93.     //shutdown some fds 
  94.     for(fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) 
  95.     { 
  96.         close(fd); 
  97.     } 
  98.     if(sigaction(SIGCHLD, &sa, NULL)) 
  99.     { 
  100.         printf("can't ignore SIGCHLD\n"); 
  101.         return -1; 
  102.     } 
  103.  
  104.     //access a socket 
  105.     sock = socket(AF_INET, SOCK_DGRAM, 0); 
  106.     if(sock == -1) 
  107.     { 
  108.         return -1; 
  109.     } 
  110.  
  111. //这里是将要查询的端口名拷贝到指定位置 
  112.     strcpy(ifr.ifr_name, "eth0"); 
  113.     ifr.ifr_data = (char *)&edata; 
  114.  
  115. //获取状态 
  116.     ioctl(sock, SIOCETHTOOL, &ifr);    
  117.     last = edata.data; 
  118.  
  119. //不断的读取网卡的状态 
  120.     while(1) 
  121.     { 
  122.  
  123. //偶尔也让它休息一下^_^ 
  124.  
  125.         sleep(1); 
  126.         ioctl(sock, SIOCETHTOOL, &ifr); 
  127.  
  128.  
  129. //如果状态没有改变,就跳过,直接执行下一次查询 
  130.         if(edata.data == last) 
  131.         { 
  132.             continue; 
  133.         } 
  134.         else 
  135.         { 
  136.             if(last == UNCONNECT)   //如果网线被插上了 
  137.             { 
  138.                 //打开一个子进程,在里面调用一个脚本 
  139.                 if(fork() == 0) 
  140.                 { 
  141.                 //  pid = getpid(); 
  142.                     ret = execl("/data/work/ma_to_mt.sh", "master", NULL); 
  143.                     if(ret < 0) 
  144.                     { 
  145.                         exit(1); 
  146.                     } 
  147.          //          return 0;  //这里没有必要使用return  因为execl执行了就不会返回了      
  148.                 } 
  149.                 last = CONNECT;  //把状态改为已连接 
  150.             } 
  151.             else if(last == CONNECT)   //如果断开了网线 
  152.             { 
  153.                 if(fork() == 0)         //开一个子进程,运行另一个脚本 
  154.                 { 
  155.          //           pid = getpid(); 
  156. ret = execl("/data/work/mt_to_ma.sh", "managed", NULL);
  157.                     if(ret < 0) 
  158.                     { 
  159.                         exit(1); 
  160.                     } 
  161.                 } 
  162.                 last = UNCONNECT;    //状态改为已断开 
  163.             } 
  164.             
  165.         }    
  166.         waitpid(-1, NULL ,0);     //这个回收子进程的动作貌似也是没必要的= =.... 
  167.     } 
  168.     return 0; 
  169. }

转自:http://blog.csdn.net/ti_tantbx/article/details/7019605

你可能感兴趣的:(如何写一个简单的守护(精灵)进程原型)