什么是守护进程?
    守护进程就是通常所说的Daemon进程,它是Linux中的后台服务程序。

它是一个生存期较长的进程,通常独立于终端而且周期性的运行某种须要的任务以及有时候会等待一些将会发生的事情。守护进程经常会在系统启动的时候開始运行,在系统关闭的时候关闭,它实现了linux系统中的非常多系统级的服务。

    还有一方面Daemon不受终端的影响,不会由于某个终端的关闭而关闭。所以,假设你希望你的进程不会由于用户或者终端的变化而变化。那么你就必需要知道怎么把你的进程设置为守护进程(也就是所说的Daemon进程了)。

编写守护进程事实上没有看似那么的复杂,就是完毕下面五步骤就可以创建出一个Daemon进程,
创建守护进程的5个步骤:

(1)创建子进程,父进程退出  。

这一步就是要在外表看来让子进程与终端脱离。这个时候原先的子进程就会变为孤儿进程,那么孤儿进程就会被init进程进行收养了。


(2)在子进程中创建的新会话setsid() : 调用者不能是组长进程],这一步是创建守护进程最重要的一步了,尽管实现很大的简单。可是意义很的重大。

先介绍下setsid()函数的作用:

    setsid()函数用于创建一个新的会话,并担任该会话组的组长,调用setsid()有以下3个作用:
    (1)让进程拜托原会话的控制
    (2)让进程拜托原进程组的控制
    (3)让进程拜托原控制终端的控制
    那么接下来我们就会非常清楚的知道我们为什么要去运行setsid()函数了,由于在第一步我们创建进程的时候。子进程全盘复制了父进程的会话期,进程组,和控制终端等。

尽管父进程退出了。但原先的会话期。进程组和控制终端没有变。因此还不是真正意义上的独立了。而setsid()函数可以让进程全然的独立出来,从而脱离全部其他进程的控制哦。


(3)改变进程的工作文件夹到"/" ; 改变工作文件夹的函数时chdir();

(4)重设文件掩码,通常使用的方法是 umask(0) ; 文件权限掩码(通经常使用8进制表示)的作用是屏蔽文件权限中的相应位。 

(5)关闭不须要的文件描写叙述符号 。通常关闭的是[0,1,2,3]   
    同文件权限掩码一样。用fork()函数新建的子进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远不会被守护进程訪问。但它们一样占用系统资源,并且还可能导致所在的文件系统无法被卸载。

特别是守护进程和终端无关,所以指向终端设备的标准输入,标准输出和标准错误流,已经失去了存在的价值。应当被关闭。通常的做法例如以下:

        int  num;
        num  =  getdtablesize(); //获取当前进程文件描写叙述符表的大小
        for(i = 0;i < num ;i++)
        {    
            close( i );
        }


    经过上述的五大步骤。一个简单的守护进程就建立起来了。

大致的流程见下图:

 

好了。大致的思想了解之后,接下来的事情就简单的多了,无非就是代码的实现的问题了;

以下以守护进程为出发点列举一个样例,希望能够具体的了解下,看看守护进程是怎样实现时间日志的



#include <head.h>

#define daemo_mode 0
#define nomal_mode 1 int daemo() //5步创建守护进程
{
pid_t pid;
pid = fork();
if(pid < 0)
{
fprintf(stderr,"File to fork\n",strerror(errno));
exit(EXIT_FAILURE);
}
if(pid > 0)
exit(EXIT_FAILURE); if(setsid() < 0)
{
perror("File to setsid");
exit(EXIT_FAILURE);
}
chdir("/");
umask(0);
close(0);
close(1);
close(2);
return 0;
} int get_line(FILE *fp)
{
int line;
char *tmp;
char buf[4096];
while(1)
{
tmp = fgets(buf,sizeof(buf),fp);
if(tmp == NULL)
break;
if(buf[strlen(tmp) - 1] == '\n')
line++;
}
return line;
} int do_nomal(const char *filename)
{
FILE * fp;
time_t t;
struct tm *ptm;
int line = 0; fp = fopen(filename,"a+"); if(fp == NULL)
{
fprintf(stderr,"File to fopen\n",strerror(errno));
exit(EXIT_FAILURE);
} line = get_line(fp); while(1)
{
++line;
time(&t); //The realization of time
ptm = localtime(&t); sleep(1);
fflush(fp);
fprintf(fp,"%d-%d-%d",(1900+ptm->tm_year),(1+ptm->tm_mon),ptm->tm_mday);
fprintf(fp,"%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
}
return 0;
}
// ./a.out log 0/1
int main(int argc, const char *argv[])
{
if(argc < 3)
{
fprintf(stderr,"Usage : %s argv[1] argv[2]\n",argv[0]);
exit(EXIT_FAILURE);
}
int mode = atoi(argv[2]);
switch(mode)
{
case daemo_mode:
daemo();
break;
case nomal_mode:
break;
default:
printf("Unknow mode \n");
goto next;
}
do_nomal(argv[1]); next:
return 0;
}



最新文章

  1. JQuery UI dialog 弹窗实例及参数说明
  2. SVN 文件解锁
  3. Core Animation一些Demo总结 (动态切换图片、大转盘、图片折叠、进度条等动画效果)
  4. BZOJ4389 : ZYB and Trees
  5. charles 常用设置
  6. 使用NodeJS将XML解析成JSON及性能比较
  7. redis的数据类型
  8. hdu 4937 Lucky Number
  9. Windows命令行command的Shell命令详细解析和语法
  10. rtp传输音视频(纯c代码)
  11. IOS开发中一些受用的编码和调试方法积累
  12. poj3728 倍增法lca 好题!
  13. gpg签名用法
  14. 【Miktex】使用教程以及数学符号整理总结
  15. day3之文件操作
  16. 高并发第十二弹:并发容器J.U.C -- Executor组件FutureTask、ForkJoin
  17. xhEditor在线编辑器使用实例
  18. Cocoa Touch(六):App运行机制 NSRunLoop, KVC, KVO, Notification, ARC
  19. 子串查询(二维前缀数组) 2018&quot;百度之星&quot;程序设计大赛 - 资格赛
  20. Extjs5.0 学习之路【结构篇】

热门文章

  1. centos 6.5搭建Samba
  2. JavaScript笔记(6)
  3. Deepin for Linux 下串口调试交换机
  4. springboot 前后端分离开发解决跨域访问
  5. Spring MVC源码——Servlet WebApplicationContext
  6. 华为OJ平台试题 ——数组:整形数组合并
  7. 停止复制代理后AWT缓存组的行为
  8. 验证list的底层数据结构
  9. OpenLayers3基础教程——OL3之Popup
  10. Icomparer和Icomparable集合排序