码迷,mamicode.com
首页 > 系统相关 > 详细

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

时间:2015-07-27 14:36:54      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

守候进程

启动方式:

  •   在系统启动时由/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

标签:

原文地址:http://www.cnblogs.com/dplearning/p/4679925.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!