热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

探究守护进程及其错误日志处理

守护进程也是通常所说的deamon进程,他是linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务,或者等待处理某些发生的事件编写守护进程

守护进程也是通常所说的deamon进程,他是linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务,或者等待处理某些发生的事件

编写守护进程的步骤:

1.创建子进程,父进程退出。

这儿有一个问题,由于父进程先于子进程退出,会造成子进程没有父进程,从而变成一个孤儿进程,在linux中,每当系统发现一个孤儿进程,就会自动由1号进程(init进程)收养,这样原来的子进程就变成init进程的子进程了

其实现代码如下:

pid=fork();

if(pid>0)

{

exit(0);//父进程退出

}

2.在子进程中创建新会话

这儿有一个进程组与会话期的概念

进程组:一个或多个进程的集合,进程组由进程组id来唯一标识

会话期:会话期是一个或多个进程组的集合,会话期的第一个进程称为会话组长

函数setsid()用于创建一个新的会话,并担任会话组组长,其功能如下

1.让进程摆脱原会话的控制

2.让进程摆脱原进程组的控制

3.让进程拜托原控制终端的控制

pid_t setsid(void)

成功返回改进程组id,失败返回-1;

3.改变当当前工作目录chdir();

由于使用fork创建的子进程继承了父进程的当前工作目录,由于在进程运行过程中,当前目录所在的文件系统是不能卸载的,这对以后使用造成了诸多麻烦,通常的做法是让“/”作为当前守护进程的当前工作目录

4.重设文件权限掩码umask(0)

把文件权限设置为0,可以增强该守护进程的灵活性

5.关闭文件描述符

同文件掩码一样,用fork函数新建的子进程会从父进程那里继承一些打开的文件,这些被打开的文件可能永远不会被守护进程访问,但一样占用资源,而且还可能导致所在的文件系统无法卸载

int num;

num=getdtablesize();//获取当前进程文件描述符大小

for(int i=0;i

{

close(i);

}

实例如下:

void deamon_mode(FILE *fp)
{
  pid_t pid;

  pid = fork();
  if(pid <0){
    perror("Fail to fork");
    exit(EXIT_FAILURE);
  }

  if(pid > 0){
    exit(EXIT_SUCCESS);
  }

  //创建新会话
  if(setsid() <0){
    perror("Fail to fork");
    exit(EXIT_FAILURE);
  }

//重设文件掩码
umask(0);

//改变进程的工作目录
chdir("/");

//关闭不需要的文件描述符
close(0);
close(1);
close(2);

//重定向
dup2(fp->_fileno,0);
dup2(fp->_fileno,1);
dup2(fp->_fileno,2);

return;
}

//a.out 0(非守护进程) log.txt
//a..out 1(守护进程 ) log.txt
int main(int argc, const char *argv[])
{
  int fd;
  FILE *log_fp;
  int mode;

  if(argc <3){
    fprintf(stderr,"Usage : %s !\n",argv[0]);
    exit(EXIT_FAILURE);
  }

  mode = atoi(argv[1]);
  if(mode){
    log_fp = fopen(argv[2],"a");
    if(log_fp == NULL){
    fprintf(stderr,"Fail to open %s : %s!\n",argv[2],strerror(errno));
    exit(EXIT_FAILURE);
  }
  deamon_mode(log_fp);
}else{
  log_fp = stderr;
}

fd = open("test",O_WRONLY | O_TRUNC | O_CREAT,0666);
if(fd <0){
  fprintf(log_fp,"Fail to open %s : %s!\n","test",strerror(errno));
  exit(EXIT_FAILURE);
}

  fprintf(log_fp,"open success!\n");
  fflush(log_fp);

  while(1)
  ;

  return 0;
}

以上主要实现一个打印日志的一个功能,如果是守护进程则,通过守护进程打印日志到log.txt,否则非守护进程,打印到屏幕

可能这儿有一个重定向dup2


首先看看man手册

技术分享图片


dup 和 dup2 都可以用来复制一个现存的文件描述符。经常用来重新定向进程的 STDIN, STDOUT, STDERR。
int dup ( int filedes ) ; 
函数返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝,若出错则返回 -1。由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。这函数返回的新文件描述符与参数 filedes 共享同一个文件数据结构。

int dup2( int filedes, int filedes2 ) 同样,函数返回一个新的文件描述符,若出错则返回 -1。与 dup 不同的是,dup2 可以用 filedes2 参数指定新描述符的数值。如果 filedes2 已经打开,则先将其关闭。如若 filedes 等于 filedes2 , 则 dup2 返回 filedes2 , 而不关闭它。同样,返回的新文件描述符与参数 filedes 共享同一个文件数据结构。

int main(int argc, const char *argv[])
{
  FILE *fp;


  fp = fopen(argv[1],"a");


  close(0);
  close(1);
  close(2);


#if 1
  dup2(fp->_fileno,0);
  dup2(fp->_fileno,1);
  dup2(fp->_fileno,2);
#endif


printf("default hello !\n");
fprintf(stdout,"stdout hello !\n");
fprintf(stderr,"stderr hello !\n");
fflush(stdout);
while(1)
;
return 0;
}

编译并运行 a.out log.txt

查看 cat log.txt

技术分享图片

可见本应该输出到控制终端的输出到了log.txt

其实对应的日志处理还有几个比较常用:

openlog/syslog/closelog,比较简单,查阅一下便知道!

探究守护进程及其错误日志处理


推荐阅读
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
author-avatar
囬憶啲伈情_542_256_427
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有