守护进程编程要点

守护进程,脱离于终端,可避免被任何的终端信号所打断,常用于服务器程序。我们用ssh远程登录,可能做的事情就是启动某个程序,如果不是守护进程,在我们退出终端时,进程立刻被杀死了,因为由终端启动的进程是tty的子进程。可用cron或nohup来启动。另外的启动方式有1.在系统启动时由启动脚本启动,通常放在/etc/rc.d/.2.利用inetd超级服务器启动,如telnet等。
守护进程编程要点
1.屏蔽一些有关控制终端的信号。signal(SIGTTOU,SIG_IGN);
2.让子进程在后台运行,父进程退出。
    if(pid=fork()) exit(0);
3.脱离控制终端和进程组setsid(),调用此函数的进程成为新的会话组长和新的进程组长,并与原来的进程组脱离关系。
4.禁止进程重新打开控制终端,进程已经成为无终端的回话组长和新的进程组长,但他可以重新申请打开一个控制终端,采用的办法是再次创建一个子进程,并让父进程退出。
5.关闭打开的文件描述符包括标准输入输出,以节省资源。
#define NOFILE 256
for(i=0;i<NOFILE;i++) close(i);
6.写日志的话需要改变当前工作目录,如chdir("/tmp");
7.重设文件创建掩码umask(0);
8.处理SIGCHLD信号,对于某些需要在请求到来时让子进程处理的一种方式是父进程等待子进程结束,但增加父进程的负担,影响并发性能。另一种简单方式是将子进程退出的SIGCHLD的操作设为SIG_IGN方式,让系统帮助回收僵死进程资源。signal(SIGCHLD,SIG_IGN)

一下是一个简单的守护进程示例:

#include<unistd.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/syslog.h>
#include<sys/param.h>//包含NOFILE的宏定义
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
int init_daemon(const char *pname,int facility){
    int pid;
    int i;
    signal(SIGTTOU,SIG_IGN);//处理可能的终端信号
    signal(SIGTTIN,SIG_IGN);
    signal(SIGTSTP,SIG_IGN);
    signal(SIGHUP,SIG_IGN);

    if(pid==fork()) exit(0);
    else if(pid<0){
        perror("fork");
        exit(-1);
    }
    setsid();//设置新会话组长,新进程组长,脱离终端
    if(pid=fork()) exit(0);//子进程不能再申请终端
    else if(pid<0){
        perror("fork");
        exit(-1);
    }
    for(i=0;i<NOFILE;i++) close(i);
    open("/dev/null",O_RDONLY);
    open("/dev/null",O_RDWR);//描述符0,1,2都定向到null
    open("/dev/null",O_RDWR);
    chdir("/tmp");//修改主目录    umask(0);//重置文件掩码    signal(SIGCHLD,SIG_IGN);    openlog(pname,LOG_PID,facility);    //与守护进程建立联系,加上进程号,文件名    return ;
}
int main(int argc,char*argv[]){
    FILE* fp;
    time_t ticks;
    init_daemon(argv[0],LOG_KERN);
    while(1){
        sleep(1);
        ticks=time(0);//time(NULL);
        syslog(LOG_INFO,"%s",(char*)asctime(localtime(&ticks)));
    }
}

在日志中记录当时的本地时间,可以通过cat /var/log/syslog |grep 进程id 来查看。

在Linux中专门提供了一个函数来完成这个daemon化的过程,这个函数的原型如下

int daemon (int __nochdir, int __noclose);

如果__nochdir的值为0,则将切换工作目录为根目录;如果__noclose为0,则将标准输入,输出和标准错误都重定向到/dev /null。

经过这个函数调用后的程序将运行在后台,成为一个daemon程序,而linux下大多的服务都是以此方式运行的。

我们来看一个简单的例子。例如编写例子程序test.c

#include <unistd.h>#include <stdio.h> int do_sth(){    return 0;}int main(){    daemon(0,0);    while ( 1 )    {        do_sth();        sleep(1);    }}

编译并运行

$ gcc -o test test.c$ ./test

程序进入了后台,通过ps查看进程情况,可以看到进程的父进程id为1,即init进程

用lsof查看test进程所打开的文件,可以看到文件描述符0,1,2都被重定向到/dev/null

并且能够看到,进程的当前工作目录(cwd)为根目录/,daemon函数已经帮我们完成了daemon化的过程,接下来我们只需要关注于程序功能 的实现了。

时间: 2024-10-10 21:38:58

守护进程编程要点的相关文章

linux 守护进程编程

概述: Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立于控制终端.通常周期的执行某种任务. 守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的任何终端信息所打断. 由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个终端,这个终端就称为这些进程的控制终端. 当控制终端被关闭时,相应的进程都会自动关闭.但是守护进程却能突破这种限制,它被执行开始运转,直到整

《网络编程》守护进程

前言 守护进程是在后台运行并独立于所有终端控制的进程.守护进程没有控制终端源于它们通常是由系统初始化脚本启动,但是也有可能从某个终端由用户在 shell 提示符下键入命令行启动,这种启动方式的守护进程必须亲自脱离与控制终端的关联,从而避免与作业控制.终端会话管理.终端产生信号等发生任何不期望的交互,也可以避免在后台运行的守护进程非预期地输出到终端.有关作业控制.终端控制的内容可参考文章<作业控制.终端控制 和 守护进程> 由于守护进程没有控制终端,当守护进程出错时,必须通过某种输出函数输出错误

Unix环境高级编程(十三)守护进程

守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数服务器都是用守护进程实现的,例如inetd守护进程. 1.守护进程的特征 用ps命令察看一些常用的系统守护进程,看一下他们和几个概念:进程组.控制终端和会话有什么联系.执行: ps –axj ,结果如下所示: 从结果可以看出守护进程没有控制终端,其终端名设置为?,终端前台进程组ID设置为-1,ini

Linux系统开发7 进程关系,守护进程

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发7  进程关系守护进程 终端 网络终端 Linux PCB结构体信息 进程组 修改子进程.父进程的组ID 会话组 设置一个会话脱离控制终端 生成一个新的会话 守护进程 守护进程模板 获取当前系统时间  终端 在UNIX系统中用户通过终端登录系统后得到一个Shell进程这个终端成为Shell进 程的控制终端Controlling Terminal在讲进程时讲过控制终端是保存在PCB

守护进程

为什么要引入守护进程:   因为它生存期长,它独立于控制终端.会话周期(下文有解释)执行任务:   由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个终端,这个终端就称为这些进程的 控制终端.当控制终端被关闭时,相应的进程都会自动关闭.但是守护进程却能突破这种限制,它被执行开始运转,直到整个系统关闭时才退出. 守护进程的特性: 1> 守护进程最重要的特性是后台运行. 2> 其次,守护进程必须与其运行前的环境隔离开来.这些环境包括未关闭的文件描述

Daemon守护进程

Daemon守护进程 在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程,都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭. 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进程.Linux的大多数服务器就是用守护进程实现的.比如,Internet服务器inetd,Web服务器httpd等.同时,守护进程完成许多系统任务,比

ASIO例子中的,守护进程初始化

// daemon.cpp // 该例子演示结合ASIO和POSIX标准系统的fork系统调用,产生一个守护进程. //时间服务器? // Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.t

2进程之间的关系:进程组,会话,守护进程

 1进程组 一个或过个进程的集合,进程组ID是一个正整数.用来获得当前进程组ID的函数. pid_t getpgid(pid_t pid) pid_t getpgrp(void) 获得父子进程进程组 运行结果: 组长进程标识:其进程组ID=其进程ID 组长进程可以创建一个进程组,创建该进程组中的进程,然后终止,只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关. 进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组) 一个进程可以为自己或子进程设置进程组ID i

Linux进程实践(5) --守护进程

概述 守护进程是在需要在后台长期运行不受终端控制的进程,通常情况下守护进程在系统启动时自动运行,在服务器关闭的时候自动关闭:守护进程的名称通常以d结尾,比如sshd.xinetd.crond.atd等. 守护进程编程规则 调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0) 调用fork(),创建新进程,它会是将来的守护进程 然后使父进程exit,保证子进程不是进程组组长 调用setsid创建新的会话 会话:是一个或者多个进程组的集合,通常一个会话开始与用户登录,终止于用户退出.在此期