Chinaunix首页 | 论坛 | 博客
  • 博客访问: 415623
  • 博文数量: 54
  • 博客积分: 1186
  • 博客等级: 少尉
  • 技术积分: 668
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-11 04:57
文章分类

全部博文(54)

文章存档

2013年(1)

2012年(6)

2011年(47)

我的朋友

分类: C/C++

2011-05-07 14:18:00

相信随着Linux的普及,大家都在写不少Linux下的程序了,尤其是一些服务端程序慢慢地都转到Linux下了吧。大家必然碰到问题是如何让自己的进程成为守护进程,在系统启动的时候运行,并且永远是后台进程。下面就写一个这样的程序了。源代码如下:
//////////////////////////////init_daemon.c 开始///////////////////////////////////////////
#include
#include
#include
#include
#include

/*********************************************************************
*filename: init_daemon.c
*purpose: 产生后台进程
*wrote by: zhoulifa() 周立发()
*date time:2006-03-10 01:00:00
*Thanks to: 北京工业大学 小胡(本文摘自)
*Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途
*                         但请遵循GPL
*********************************************************************/

void init_daemon(void)
{
  int pid;
  int i;

  if(pid=fork())
    exit(0);//是父进程,结束父进程
  else if(pid< 0)
    exit(1);//fork失败,退出

  //是第一子进程,后台继续执行
  setsid();//第一子进程成为新的会话组长和进程组长
  //并与控制终端分离
  if(pid=fork())
    exit(0);//是第一子进程,结束第一子进程
  else if(pid< 0)
    exit(1);//fork失败,退出
  //是第二子进程,继续
  //第二子进程不再是会话组长

  for(i=0;i< NOFILE;++i)//关闭打开的文件描述符
    close(i);
  chdir("/tmp");//改变工作目录到/tmp
  umask(0);//重设文件创建掩模
  return;
}
//////////////////////////////init_daemon.c 结束///////////////////////////////////////////

上面这是个通用的函数,可以让你的程序成为后台守护进程。
下面是一个测试程序:
//////////////////////////////daemontest.c 开始///////////////////////////////////////////
#include
#include

/*********************************************************************
*filename: daemontest.c
*purpose: 测试后台进程
*wrote by: zhoulifa() 周立发()
*date time:2006-03-10 01:09:00
*Thanks to: 北京工业大学 小胡(本文参考了其文章)
*Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途
*                         但请遵循GPL
*********************************************************************/

void init_daemon(void);//守护进程初始化函数
void signal_reload(int signal)
{
  /*当收到SIGUSR1信号时程序重新导入所有参数*/
  FILE *fp;
  time_t t;
  if((fp=fopen("test.log","a")) >=0)
  {
    t=time(0);
    fprintf(fp,"I received signal(%d), reload all parameters at %s\n", signal, asctime(localtime(&t)) );
    fclose(fp);
  }
  /*重新导入参数*/
}

void signal_handle(int signal)
{
  /*当收到SIGUSR2信号时程序退出*/
  FILE *fp;
  time_t t;
  if((fp=fopen("test.log","a")) >=0)
  {
    t=time(0);
    fprintf(fp,"I received signal(%d), exit at %s\n", signal, asctime(localtime(&t)) );
    fclose(fp);
  }
  exit(0);
}

int main(int argc, char ** argv)
{
  FILE *fp;
  time_t t;
  init_daemon();//初始化为Daemon

  signal(SIGCHLD, SIG_IGN);/*忽略子进程退出信号,若在此之后又产生了子进程,
                             如果不处理此信号,将在子进程退出后产生僵尸进程*/
  signal(SIGUSR1, signal_reload);/*处理SIGUSR1信号,可以定义此信号为重导参数信号*/
  signal(SIGUSR2, signal_handle);/*处理SIGUSR2信号,可以定义此信号为退出信号*/
  while(1)//每隔一分钟向test.log报告运行状态
  {
    /*这是各位程序的主体部分,所以的工作在下面完成,比如http服务、FTP服务等*/
    sleep(60);//睡眠一分钟
    if((fp=fopen("test.log","a")) >=0)/*注意,由于在init_daemon里面已经把路径切换到了/tmp,因此此文件是/tmp/test.log*/
    {
      t=time(0);
      fprintf(fp,"I'm here at %s\n",asctime(localtime(&t)) );
      fclose(fp);
    }
  }
}
//////////////////////////////daemontest.c 结束///////////////////////////////////////////
编译时使用命令进行联合编译:
gcc init_daemon.c daemontest.c
产生了一个程序比如叫a.out

你就可以运行此程序了./a.out了。

如果想要此程序在系统启动时自动运行,你可以在/etc/rc.d/rc.local里面用su命令加上一行,比如:
su - Jacky -c "/bin/a.out"
这个命令将以Jacky用户身份运行/bin/a.out程序

linux: ps -ef

unix : ps –axj

程序运行过程中如果你修改了程序的参数,则必然希望程序重新导入参数,那么你可以用ps命令查看程序的进程号:
ps -ef|grep a.out
然后用kill命令向程序发参数,比如:
kill -s SIGUSR1 11422

同理,如果想要终止程序,则向程序发SIGUSR2信号:
kill -s SIGUSR2 11422

以上代码在CentOS下测试通过。

本文转自
阅读(1257) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

liuqiang_mail2013-10-29 11:41:54

按照你的方法试了一遍,不错,确实可以,但是感觉很麻烦。如果需要创建后台进程,为什么不直接用daemon( 0, 0 );?这样有简单有使用,博主的方法很麻烦啊