守护进程的详细编写

守护进程是什么?

虽然这个问题在前两篇文章中我们已经谈论过很多次了,但是在这篇文章中我要更加清晰详细地来说这个事情:
守护进程(Daemon)也被翻译为精灵进程、是一种旨在运行于相对干净环境、不受终端影响的、常驻内存的进程,就像神话中的精灵拥有不死的特性,长期稳定提供某种功能或服务(当然你要是把电脑电给断掉之后,守护进程也会被杀死哈哈)电脑上常见的守护进程有:系统日志进程,网络管理进程等(这些进程一般来说都伴随着我们从开机到关机,我们需要它们来给我们提供长期稳定的服务)。

查看守护进程

在Unix/Linux系统中,使用 ps 命令可以看到许多以 -d 结尾的进程(Daemon),它们大多都是守护进程,例如:

ps -ef | grep '.*d$'

'.*d$' 是一个正则表达式,用于匹配以 "d" 结尾的字符串。其中 .* 是一个非常常见且强大的组合,它表示匹配任意字符(除了换行符)零次或多次。d$ 表示匹配以 "d" 结尾的字符串。

守护进程完整创建过程

守护进程在创建过程很固定,就是这样的一个套路,如果你不知理解某些步骤的话其实也没有关系,到时候把这里的固定套路模板复制粘贴即可。

1.创建子进程并让父进程退出

首先,通常会使用 fork() 创建一个子进程。父进程退出,确保守护进程不再与终端连接,避免被终端控制。

// 创建子进程
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid > 0) {
        // 父进程退出
        exit(0);
    }

2. 在子进程中创建新的会话 

// 创建新的会话
    if (setsid() == -1) {
        perror("setsid failed");
        exit(1);
    }

使用 setsid() 创建一个新的会话,并使当前进程成为会话领导进程。这样,进程就会脱离控制终端,不再与终端或控制台相连。这样做的目的是防止该进程将来收到终端的信号(例如 SIGHUP)。

3. 改变子进程当前工作目录

守护进程通常会将工作目录更改为根目录(/)。这样做的目的是防止守护进程占用任何特定的文件系统目录,避免出现不小心挂载文件系统时工作目录被占用的情况。

如果守护进程保持其工作目录指向某个特定目录,假设该目录所在的文件系统被卸载(或重新挂载),则守护进程可能会因为工作目录丢失而崩溃或出现错误。工作目录设置成根目录就不需要担心这个问题了。

 // 改变工作目录
    if (chdir("/") == -1) {
        perror("chdir failed");
        exit(1);
    }

4. 设置文件权限掩码

使用 umask() 设置文件权限掩码,通常将其设置为 0这样守护进程创建的文件权限不会受到权限掩码的限制。创建的文件的权限就等于默认的权限(touch 666,mkdir 777)

// 设置文件权限掩码
    umask(0);

关于文件权限掩码的详细介绍在本文后面专门有详细介绍

5. 关闭文件描述符

  • 关闭所有不需要的文件描述符,包括标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)。
  • 这样做的好处是:
    • 避免资源浪费: 释放不再使用的文件描述符,节省系统资源。
    • 防止意外输出: 避免守护进程的输出干扰终端或其他程序。

6.进入守护进程的主循环

守护进程进入一个无限循环,执行需要完成的任务。在主循环中,可以根据需要处理各种信号、事件或定时任务。

守护进程创建完整代码框架

int main() {
    pid_t pid;

    // 1. 创建子进程,父进程退出
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid > 0) {
        // 父进程退出
        exit(0);
    }

    // 2. 创建新的会话
    if (setsid() == -1) {
        perror("setsid failed");
        exit(1);
    }

    // 3. 改变当前工作目录
    if (chdir("/") == -1) {
        perror("chdir failed");
        exit(1);
    }

    // 4. 设置文件权限掩码
    umask(0);

    // 5. 关闭文件描述符
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // 6. 守护进程的主循环,在这里反复监听
    daemon_main();

    return 0;
}

守护进程在创建过程很固定,就是这样的一个套路,如果你不知理解某些步骤的话其实也没有关系,到时候把这里的固定套路模板复制粘贴即可。

文件权限掩码

回顾文件权限码

Linux系统中有三种基本权限:

  • 读取(r): 允许查看文件内容。
  • 写入(w): 允许修改文件内容。
  • 执行(x): 允许运行文件(如果是可执行文件)。

每个文件或目录都有三组权限:

  • 所有者(Owner): 拥有文件的人。
  • 所属组(Group): 文件所属的组。
  • 其他用户(Others): 除所有者和所属组之外的所有用户。

权限码可以用符号数字表示。

符号表示法

rwx- 分别表示读取、写入、执行和无权限。例如:

  • rw-r--r-- 表示文件所有者有读写权限,所属组有读权限,其他用户有读权限。

数字表示法

用数字 4、2、1 和 0 分别表示读取、写入、执行和无权限。然后将每组权限的数字相加,得到一个三位数的权限码。例如:

  • 644 表示文件所有者有读写权限(4+2=6),所属组有读权限(4),其他用户有读权限(4)。

可以使用 chmod 命令修改文件或目录的权限。例如:

chmod 755 myfile 将 myfile 的权限设置为所有者有读写执行权限,所属组和其他用户有读执行权限。

默认文件权限

当我们使用mkdir命令创建文件目录和touch命令创建文件的时候,并不能直接指定文件的权限。都是根据文件的默认权限来设定的。

默认权限

  • 文件: 默认权限通常是 666 (rw-rw-rw-),表示所有用户都具有读写权限。
  • 目录: 默认权限通常是 777 (rwxrwxrwx),表示所有用户都具有读写执行权限。

但是你使用touch创建文件以及使用mkdir创建目录文件后,ls -l查看发现文件权限并不是666和777,这是因为有权限掩码的存在。

注意默认的文件和目录权限(如 06660777)是由操作系统设定的,不能修改!!!!!这些默认权限是文件系统为新创建的文件和目录预定义的。

文件权限掩码(umask)是什么

权限掩码通常用一个三位八进制数表示。每一位数字的取值范围是0-7,每一位数字对应一类用户:

  • 第一位: 文件所有者(Owner)
  • 第二位: 所属组(Group)
  • 第三位: 其他用户(Others)

新创建的文件或目录的实际权限由默认权限权限掩码共同决定。

  1. 默认权限: 系统对不同类型的文件和目录有不同的默认权限设置。例如,文件默认权限通常是 666(rw-rw-rw-),目录默认权限通常是 777(rwxrwxrwx)。
  2. 权限掩码: 权限掩码中每一位为1的表示要从默认权限中去除相应的权限。

实际权限 = 默认权限 - 权限掩码

举例说明实际权限 = 默认权限 - 权限掩码

假设权限掩码为 022,新创建的文件默认权限为 666

  • 文件所有者:6 - 0 = 6 (rw-)
  • 所属组:6 - 2 = 4 (r--)
  • 其他用户:6 - 2 = 4 (r--)

因此,新创建文件的实际权限为 644 (rw-r--r--)。

权限掩码是Linux系统中一个重要的安全机制,它可以帮助我们设置更安全的默认权限,防止新创建的文件或目录默认拥有过高的权限。

无论你如何创建文件或目录,操作系统都会根据当前的 umask 和默认权限来计算最终的权限。但是请注意:

  • umask 只影响新创建的文件和目录的权限。
  • chmod 修改已经存在文件或目录的权限时,直接修改权限,不会受 umask 的影响。

文件权限掩码的查看与设置

终端中查看与设置文件权限掩码:

查看当前的 umask:

umask

设置 umask:

umask 022

 程序中设置文件权限掩码

umask() 函数用于在程序中设置进程的权限掩码

函数原型:mode_t umask(mode_t mask);

文件权限掩码的特点

umask 是进程级别的

  • umask 的设置是与当前进程相关的,而不是与文件系统的某个目录关联的
  • 一旦你在一个进程中设置了 umask,该进程及其派生的子进程(包括通过 fork() 或其他方式创建的子进程)会继承该 umask 值,直到进程修改它。
  • 不同的进程可以拥有不同的 umask 设置。
  • 子进程可以改变自己的 umask,并且这种改变只会影响子进程及其后代进程。
  • 在终端中运行某个命令或启动其他程序时,这些命令或程序会继承当前 shell 进程的 umask 设置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值