守护进程(setsid、getpgrp、setpgid、getpgid)以及系统日志(openlog、syslog、closelog)

守护进程:精灵进程

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

特点:

1.脱离控制终端

2.会话的leader

3.进程组的leader

=============================

系统日志:

[root]# cd /var/log/    系统日志

主日志文件:messages

syslogd服务----权限分离:每个用户将要提交的日志提交给syslogd服务,syslogd将日志写入系统日志

#include <syslog.h>
/********************************
 * 功能:   为进程与syslogd服务建立连接
 * 参数:   ident:给出的字段,
            option:特殊要求LOG_PID.....
            facility:消息来源:LOG_DAEMON.....
 ********************************/
void openlog(const char *ident, int option, int facility);

/********************************
 * 功能:   提交内容
 * 参数:   priority:级别:LOG_INFO.....
            format:提交的内容(变参)
 ********************************/
void syslog(int priority, const char *format, ...);

/********************************
 * 功能:   断开进程与syslogd服务的连接
 *******************************/
void closelog(void);

=============================

[root]# ps axj  查看父子进程
tty:?脱离控制终端
SID PID PGID 相同
PPID:1

=============================

setsid:

#include <unistd.h>
/************************
 *功能:创建一个新的对话并设置进程组ID:如果当前调用它的进程不是进程组leader的情况下
 *返回值:成功返回进程ID,失败返回-1并设置errno
 * *********************/
pid_t setsid(void);

=============================

getpgrp:

/***********************
 *功能:获取进程组ID
 *返回值:成功返回进程组ID,失败返回-1并设置errno
 * *********************/
int getpgrp(void);

=============================

/*****************************
 * 功能:设置进程组ID
 * 参数:pid进程ID
 *       pgid进程组ID
 ****************************/
int setpgid(pid_t pid, pid_t pgid);

/**************************
 * 功能:获取进程GID
 * 参数:进程ID
 * ***********************/
pid_t getpgid(pid_t pid);

=============================

eg:

/***********************
 *功能:创建守护进程
 *      添加系统日志
 * ********************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>

//守护进程创建后不断向FNAME中写入数字
#define  FNAME "/tmp/out"

static int daemonize(void )
{
    pid_t pid ;
    int fd ;
    int i ;
    //1.创建进程
    pid = fork();
    if(pid < 0)
        return -1;
    //2.子进程
    if(pid == 0)
    {
        //脱离控制终端 读写形式打开一个设备
        fd = open("/dev/null",O_RDWR);
        if(fd < 0)
            return -1 ;
        //重定向:将fd重定向到0 ,1 ,2
        dup2(fd , 0 );
        dup2(fd , 1 );
        dup2(fd , 2 );
        if(fd > 2)
            close(fd);

        //守护进程产生
        setsid();
        //当前的工作路径为根目录,如果是挂载的文件卸载可能回busy
        chdir("/");
        //在程序中不会产生文件的情况下
        umask(0);
        return 0 ;
    }
    else//2.父进程
        exit(0);
}

int main()
{
    FILE *fp ;
    int i ;
    //0.建立系统日志
    openlog("mydeamon",LOG_PID,LOG_DAEMON);

    //1.创建守护进程
    if(daemonize())
    {
        syslog(LOG_ERR ,"deamonize() failed !");
        exit(1);
    }
    else
    {
        syslog(LOG_INFO,"deamonize() success !");
    }
    //===========守护进程工作==============
    //2.以写的方式打开文件
    fp = fopen(FNAME , "w");
    if(fp == NULL)
    {
        syslog(LOG_ERR,"fopen()%s",strerror(errno));
        exit(1);
    }
    syslog(LOG_INFO ,"%s was opened",FNAME);
    //3.不断写入i的值eg:1 2 3 4 ......
    for(i = 0 ;; i++)
    {
        fprintf(fp,"%d
",i);
        //文件全缓冲模式,要加刷新
        syslog(LOG_DEBUG , "%d is printed ",i);
        fflush(fp);
        sleep(1);
    }
  //执行不到 fclose(fp); closelog(); exit(
0); }

[root]# ./demon

[root]# ps axj 查看deamon进程状态

[root]# tail -f /tmp/out 动态查看文件内数值的变化

[root]# kill pid号   杀死进程

[root]# tail /var/log/messages 查看系统日志

原文地址:https://www.cnblogs.com/muzihuan/p/5292811.html