C语言实现Linux系统的守护进程创建

      大家好,我是练习编程时长两年半的昆工第一ikun,今天我们来分享一下进程的有关知识,并且用c语言来创建一个Linux系统的守护进程。


目录

一、进程相关接口函数

1、创建子进程 -- fork

(1)函数原型

(2) 父子进程:

2、结束进程 -- exit() / _exit()

3、进程回收 -- wait 、waitpid

4、exec函数族

二、守护进程


 

一、进程相关接口函数

1、创建子进程 -- fork

(1)函数原型

#include 
       #include 
​
       pid_t fork(void);

 返回值:
           成功创建一个新的子进程,父进程返回子进程的PID号,子进程返回0
           失败父进程返回-1,没有子进程被创建

(2) 父子进程:

一个进程通过fork函数创建一个新的进程,原本进程称为新进程的父进程,新的进程称为原进程的子进程

子进程会继承父进程中几乎所有数据。

①、如果父进程优先于子进程结束:

子进程称为孤儿进程,由前台进程变为后台进程,统一由init进程收养;

②、如果子进程先于父进程结束,且父进程没有回收子进程资源

子进程变成僵尸进程(僵尸态)

一般来说,如果子进程先于父进程结束,子进程应该统一由父进程回收

子进程在fork语句的下一条指令开始执行

2、结束进程 -- exit() / _exit()

  #include 
​
   void exit(int status);
   参数:
        status:表示进程退出的状态


   #include 
​
   void _exit(int status); 

注意: exit函数调用后会刷新所有缓冲区,_exit函数不会刷新

3、进程回收 -- wait 、waitpid

  #include 
   #include 
​
   pid_t wait(int *wstatus);    
   参数:
        wstatus:进程结束时,状态信息的首地址
   
   返回值:
        成功返回结束子进程的pid号,失败返回-1
        
        如果想要得到子进程结束的状态信息,可以用以下宏来得到:
        
        WIFEXITED(wstatus) -- 判断一个子进程是否是正常退出,正常退出为真,非正常退出为假
        WEXITSTATUS(wstatus)  -- 返回子进程结束的返回值
        WIFSIGNALED(wstatus) --  判断是否被信号终止
        WTERMSIG(wstatus) -- 打印终止进程信号的编号
----------------------------------------------------------------------------------
​
    pid_t waitpid(pid_t pid, int *wstatus, int options);
    
    参数:
        pid:进程号, -1表示接收任意子进程
        wstatus:进程结束时,状态信息的首地址
        options:
                0 -- 以阻塞方式等待子进程结束
                WNOHANG  -- 以非阻塞方式等待子进程结束

4、exec函数族

  
 #include 
   
   l:list列表
   v: argv
   p: PATH环境变量
   
   int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);
   
   参数:
        pathname:执行程序的文件名(包含路径)
        arg:执行程序的命令行参数,命令行参数列表以NULL结尾
   返回值:
        失败返回-1;
 -----------------------------------------------------------------------------  
   int execlp(const char *file, const char *arg, .../* (char  *) NULL */);  
   参数:
        file:程序名
   
   添加环境变量:
    在~/.bashrc中添加命令:
        export PATH=$PATH:/home/hqyj/class/220703_IO/day4
        配置完成之后,需要用以下指令让配置生效:
            source ~/.bashrc
--------------------------------------------------------------------------------


   int execv(const char *pathname, char *const argv[]);
   int execvp(const char *file, char *const argv[]);

二、守护进程

守护进程跟终端无关,负责在后台周期性的处理某些事件或者等待某些事件响应

1、进程组:当用户运行一个进程时,就相当于创建了一个进程组,跟该进程具有亲缘关系的所有进程都属于该进程组 ​

2、会话:当用户打开一个终端时,就创建了一个会话,一个会话由一个或者多个进程组组成,一旦终端关闭,该会话中所有进程组中的进程全部结束

3、守护进程的创建流程:

①、创建子进程,父进程退出
    fork();

②、让子进程脱离原本会话
   setsid();

③、修改当前工作路径 -- 非必要
   chdir("/tmp");

④、重设文件权限掩码 -- 非必要
   umask(0);

⑤、删除进程中所有的文件描述符
   int i = 0;
   for(i = 0; i < getdtabelsize; i++)
   {
       close(i);
   }

while(1)
{
   周期性需要执行的事件;
}


​4、创建一个守护进程,在time.log日志文件中每隔1s,记录当前时间;

按照创建守护进程的流程,我们可以很容易创建一个守护进程,代码如下:

#include 
#include 
#include 
#include 
#include 
#include 

void init_daemon();
int main(int argc, char *argv[])
{
    struct tm *t = NULL;
    time_t now;              

    init_daemon();      

    while(1)                                         
    {
        FILE *fp = fopen("/tmp/time.log", "a+");
        if(fp == NULL)
        {
            perror("fopen");
            exit(0);
        }
        time(&now);
        t = localtime(&now);
        fprintf(fp, "%d年%d月%d日%d:%d:%d\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
        sleep(1);
        fflush(fp);
        fclose(fp);
    }
    return 0;
}

void init_daemon()      //创建守护进程
{
    pid_t pid = fork();      //创建子进程
    if(pid < 0)              
    {
        perror("fork");
        exit(0);
    }
    if(pid > 0)             //父进程退出
    {
        exit(0);
    }

    setsid();               //让子进程脱离原本会话

    chdir("/tmp");          //修改当前工作路径

    umask(0);               //重设文件权限掩码
    int i = 0;
    for(i = 0; i < getdtablesize(); i++)
    {
        close(i);
    }
    return;

} 

运行程序,结果如下: 

 

 

C语言实现Linux系统的守护进程创建_第1张图片

 

你可能感兴趣的:(linux,c语言,运维)