【linux高级程序设计】(第八章)进程管理与程序开发 5

守候进程

启动方式:

  •   在系统启动时由/etc/rd.d目录下的启动脚本启动
  •   利用inetd超级服务器启动
  •   有cron命令定时启动,以及在终端用nohup命令启动

 

守护进程编程要点

(1)屏蔽有关控制终端操作的信号,防止守护进程正常启动之前,控制终端受到干扰退出或挂起。

for(i = 1; i <= 31; i++)

    signal(SIGTTOU, SIG_IGN); //忽略所有可以忽略的信号,STGSTOP和SIGKILL不能忽略

(2)在后台运行,为了避免挂起控制终端。方法在进程中创建子进程,并使父进程终止。

if(pid = fork())

    exit(0);      //父进程结束,子进程继续

(3)脱离控制终端和进程组。用setsid()使子进程成为新的会话组长,彻底脱离从父进程继承下来的控制终端的影响

setsid();

(4)禁止进程重新打开控制终端。只有会话组长能够打开终端,再创建一个子进程,并让父进程退出,这样子进程就不是会话组长了。

if(pid = fork())

    exit(0);      //父进程结束,子进程继续

(5)关闭打开的文件描述符。一般,不需要从父进程那继承来的文件描述符。

#define NOFILE 256  //不同系统有不同限制

for(i = 0; i < NOFILE; i++)   //关闭打开的文件描述符

    close(i);

(6)改变当前工作目录。进程活动时,其工作目录所在的文件系统不能卸载。故需要将守候进程的工作目录改变到合适的目录

chdir("/tem");

(7)重设文件创建掩码。防止修改守护进程所创建文件的存储权限

umask(0);

(8)处理SIGCHLD信号(子进程退出信号)。让系统帮助回收僵死进程资源

signal(SIGCHLD, SIG_IGN);

 

守候进程两种写日志信息的方式

(1)进程直接与日志文件建立联系,即open一个文件,然后write写文件

(2)使用日志守候进程syslogd

 

void openlog (__const char *__ident, int __option, int __facility):打开当前程序与日志守候进程之间的联系。

  参数1:要向每个消息加入的字符串,一般为当前进程名

  参数2:描述已打开选项

  参数3:消息类型,决定将消息写入那个日志文件中

void closelog(void):关闭与日志守候进程的联系

void syslog (int __pri, __const char * __fmt, ...) :写一条日志信息

  参数1:决定日志级别 0系统不可用,1必须立刻报告的 2冲突 3错误 4警告 5普通担忧特殊标识 6消息 7调度级

  参数2:日志输出格式,类似printf的第二个参数

int setlogmask (int __mask) :设置当前进程syslog()函数输出消息的默认优先级

 

守候进程例子

#include<unistd.h>

#include<signal.h>

#include<fcntl.h>

#include<sys/syslog.h>

#include<sys/param.h>

#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(EXIT_SUCCESS);

    else if(pid < 0)

    {

        perror("fork");

        exit(EXIT_FAILURE);

    }

    setsid(); //设置新会话组长

    if(pid = fork())  //创建子进程,父进程退出

        exit(EXIT_SUCCESS);

    else if(pid < 0)

    {

        perror("fork");

        exit(EXIT_FAILURE);

    }

    for(i = 0; i < NOFILE; ++i)     //关闭父进程打开的文件描述符

        close(i);

    open("/dev/null", O_RDONLY);  //对标准输入输出全部重定向到/dev/null

    open("/dev/null", O_RDWR);

    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(NULL); //获取当前时间

        syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //写日志信息

    }

}

可以看到,守候进程在后台运行

运行后我找不到日志写哪了?

还有很奇怪的一点,之后每次我用ps aux|grep Daemon_exp 进程号都会加2 ?

【linux高级程序设计】(第八章)进程管理与程序开发 5

你可能感兴趣的:(linux)