热门标签 | 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,比较简单,查阅一下便知道!

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


推荐阅读
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 深入解析Unity3D游戏开发中的音频播放技术
    在游戏开发中,音频播放是提升玩家沉浸感的关键因素之一。本文将探讨如何在Unity3D中高效地管理和播放不同类型的游戏音频,包括背景音乐和效果音效,并介绍实现这些功能的具体步骤。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
  • 本文探讨了一种常见的C++面试题目——实现自己的String类。通过此过程,不仅能够检验开发者对C++基础知识的掌握程度,还能加深对其高级特性的理解。文章详细介绍了如何实现基本的功能,如构造函数、析构函数、拷贝构造函数及赋值运算符重载等。 ... [详细]
  • 随着Linux操作系统的广泛使用,确保用户账户及系统安全变得尤为重要。用户密码的复杂性直接关系到系统的整体安全性。本文将详细介绍如何在CentOS服务器上自定义密码规则,以增强系统的安全性。 ... [详细]
  • 默认情况下,Git 使用 Nano 编辑器进行提交信息的编辑,但如果您更喜欢使用 Vim,可以通过简单的配置更改来实现这一变化。本文将指导您如何通过修改全局配置文件来设置 Vim 作为默认的 Git 提交编辑器。 ... [详细]
  • 本文探讨了使用普通生成函数和指数生成函数解决组合与排列问题的方法,特别是在处理特定路径计数问题时的应用。文章通过详细分析和代码实现,展示了如何高效地计算在给定条件下不相邻相同元素的排列数量。 ... [详细]
  • 在Notepad++中配置Markdown语法高亮及实时预览功能
    本文详细介绍了如何在Notepad++中配置Markdown语法高亮和实时预览功能,包括必要的插件安装和设置步骤。 ... [详细]
  • 探讨如何在映射文件中处理重复的属性字段,以避免数据操作时出现错误。 ... [详细]
  • 为何Compose与Swarm之后仍有Kubernetes的诞生?
    探讨在已有Compose和Swarm的情况下,Kubernetes是如何以其独特的设计理念和技术优势脱颖而出,成为容器编排领域的领航者。 ... [详细]
  • 3DSMAX制作超现实的体育馆模型
    这篇教程是向脚本之家的朋友介绍3DSMAX制作超现实的体育馆模型方法,教程制作出来的体育馆模型非常地不错,不过教程有点难度,需要有一定基础的朋友学习,推荐到脚本之家,喜欢的朋友可 ... [详细]
  • 本文介绍了如何在AngularJS应用中使用ng-repeat指令创建可单独点击选中的列表项,并详细描述了实现这一功能的具体步骤和代码示例。 ... [详细]
  • 在项目冲刺的最后一天,团队专注于软件用户界面的细节优化,包括调整控件布局和字体设置,以确保界面的简洁性和用户友好性。 ... [详细]
  • JavaScript 页面卸载事件详解 (onunload)
    当用户从页面离开时(如关闭页面或刷新页面),会触发 onunload 事件,此时可以执行预设的脚本。需要注意的是,不同的浏览器对 onunload 事件的支持程度可能有所不同。 ... [详细]
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社区 版权所有