linux守护进程的创建

下面的完成了这样一个功能,创建一个守护进程,每个一秒在/tmp目录下的文件peng.txt中记录当前系统时间。

一、守护进程

守护进程是linux中的后台服务进程,在系统启动时开始运行,在系统关闭时终止。Linux系统中的大多数服务进程都是由守护进程实现的。

二、创建守护进程

  • 创建子进程,父进程退出

此时,子进程变成孤儿进程,在后台运行。此时,子进程表面上脱离了终端(如bash),但是实际上却没有,因为其PGID和SID都是原来的没变。

  • 在子进程中创建新的会话

调用setsid()函数,这样,子进程的GID和sid就都等于子进程pid了,它使子进程完全独立出来,可以使用 kill –9 pid,将其杀死。

  • 改变进程的工作目录为根目录

首先要知道工作目录与当前目录的区别,工作目录默认是当前目录,比如执行函数open(“1.c”,……),时,系统会自动到默认的工作目录(即当前目录)中读取或者创建文件 1.c ,但是通过调用函数 chdir(“/tmp”),可以将工作目录变成/tmp,此后,如果再执行open(“1.c”,……),系统就回到/tmp目录下面读取或者创建文件 1.c;

其次,为什么有改变工作目录?原因是,守护进程的工作目录不可以被卸载!假如你把U盘挂载到了机器上,你没改工作目录,U盘上有一个守护进程的程序,你运行了,那么U盘所挂载的目录就是该守护进程的工作目录,假如守护进程中有写文件和读文件操作,你的U盘就没法卸载了,假如你把工作目录改成/tmp,而/tmp无法卸载,运行U盘上的守护进程后,再与U盘无关,此时你可以卸载U盘,而不会对该守护进程有什么影响,该守护进程已经在内存中了。

通常将守护进程的工作目录设置成 “/”或者“/tmp ”,可以看看/tmp 目录的权限是否够用,一般是 0777。

  • 重设文件权限掩码

将文件权限掩码设置为umask(0),这样可以增加守护进程的灵活性

  • 关闭文件描述符

因为创建子进程时,父进程已经打开了若干文件(比如stdin、stdout、stderr),而守护进程用不到这些文件,所以应该关闭。因此,守护进程已经无法使用诸如printf 、scanf、gets等等。

源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>

int main()
{
    pid_t pid;
    int i;
    FILE *fp;
    time_t t;

    if ((pid = fork()) == -1)  //创建子进程
    {
        perror("fork");
        exit(-1);
    }

    if (pid > 0) exit(0);   //pid>0是父进程,父进程退出

    setsid();         //在子进程中建立新会话,使子进程完全独立
    chdir ("/tmp");   //改变工作目录为/tmp
    umask(0);        //重设文件权限掩码
    for (i = 0; i < getdtablesize(); i++)   //关闭已经打开的文件,包括stdin、stdout和stderr,getdtablesize的返回值为固定值
        close(i);                            //注意getdtablesize()不是函数,而是一个宏定义,为常数。

    if ((fp = fopen("time.txt", "a")) == NULL)  //打开要写的文件
        exit(-1);

    while (1)
    {
        sleep(1);
        t = time(NULL);  //获取系统时间
        fprintf(fp, "%s", ctime(&t));//ctime将time转化为标准格式字符串,返回字符串首地址
        fflush(fp);  //因为是全缓存,所以为保证实时性,用该用fflush进行刷新。
    }

    return 0;
}
原文地址:https://www.cnblogs.com/pengdonglin137/p/2945049.html