进程,会话,守护进程

会话

在Linux中,会话(session)是一组相关联的进程的集合,它们可以接收相同的信号,并且通常由一个领导进程来控制。会话中的所有进程都共享同一个控制终端(controlling terminal),这个终端通常是会话的首个进程(也就是会话期领导者进程)打开的终端。

当用户登录到系统时,通常会启动一个新的会话。会话期领导者进程通常是登录shell,它负责启动其他进程并创建新的进程组和会话。如果会话期领导者进程退出,那么整个会话将结束并且该会话中的所有进程都将收到 SIGHUP 信号(默认行为是终止进程)。

会话还有一个与之相关的概念:作业(job)。作业是指在同一会话中的一组相关进程。在交互式shell中,通常可以使用前台作业(foreground job)和后台作业(background job)来管理正在运行的进程。

proc1|proc2 &

这个命令是Linux下的一个管道(pipe)和后台运行(background)的组合操作。

将两个进程proc1和proc2通过管道连接起来,使得proc1的输出可以传递给proc2进行处理。在命令结尾处添加“&”符号表示让整个命令在后台运行,即不阻塞当前shell终端,并且可以同时在该终端中输入其他命令。

具体来说,当执行该命令时,shell会首先创建一个新的子进程来执行proc1和proc2的管道操作,然后立即返回到shell提示符下等待输入新命令。由于该命令在后台运行,因此控制权立即被交还给用户,而不必等待命令执行完毕。至于管道操作的结果,则会显示在标准输出中或者被重定向到其他文件中,具体取决于命令的具体形式。

需要注意的是,如果在后台运行的命令产生了输出,那么它们的输出可能会与用户输入的其他命令的输出混合在一起,因此需要小心处理。此外,也可以使用jobs命令查看当前正在后台运行的任务的状态,并且可以使用fg或bg命令将前台作业切换到后台或反之。

$proc3|proc4|proc5

这个命令看起来是在使用三个进程:proc3、proc4和proc5。

这个命令可能使用了竖杠符号“|”,在基于Unix的操作系统中,“|”符号通常表示管道。管道允许将一个进程的输出作为另一个进程的输入。

根据这个假设,这个命令将 proc3 的输出通过管道传递给 proc4,然后将 proc4 的输出通过管道传递给 proc5。这可以用于链接命令并执行更复杂的操作。

在这里插入图片描述
会话的一些特征

在Linux系统中,会话通常指一个用户与系统交互的过程。Linux的会话具有以下一些特征:

  1. 登录:会话开始于用户登录系统之后,在终端或者远程终端运行shell程序。

  2. 进程组和作业控制:在一个会话内,多个进程可以组成进程组,而进程组又可以被分为不同的作业。Linux提供了作业控制机制,允许用户对作业进行管理。

  3. 控制终端:一个会话通常与一个控制终端相关联。控制终端是用户输入和输出的接口,也是信号传递的媒介。

  4. 会话和进程的关系:在Linux中,每个进程都属于一个会话,而会话又包含了多个进程。当父进程创建一个子进程时,子进程会自动成为父进程所在会话的成员。

  5. 信号:在Linux系统中,进程间通信主要依靠信号。在一个会话中,进程可以向会话内其他进程发送信号,以实现相应的交互。

  6. 生命周期:一个会话的生命周期从用户登录开始,到用户退出系统结束。在此期间会话中的进程可以执行各种操作,并且可能会产生不同的事件和状态。

守护进程

守护进程(daemon)是在后台运行的一种特殊类型的进程,它们通常在系统启动时启动,并在系统关闭时终止。守护进程不与任何控制终端相连,因此它们不能从终端接收输入或向终端输出数据。

守护进程通常被用来执行一些需要在后台长时间运行的任务,例如网络服务、系统监控、日志记录等。它们可以周期性地执行一些任务,或者根据需要启动和停止其他进程。

一个好的守护进程应该有以下几个特点:

能够在后台默默地工作,不会占用用户的交互式控制终端。

能够自我管理并保证稳定性,能够处理各种异常情况,如资源不足、网络中断等。

能够记录所有重要事件以及错误信息,便于管理员进行故障排除和系统调试。

能够按需启动、停止或重启其他进程,实现某些功能,如更新配置文件、重新加载模块等。

总之,守护进程是Linux/Unix操作系统中非常重要的一部分,它们可以为系统提供各种服务和支持,保持系统安全、稳定和高效运行。
要创建守护进程,一般需要按照以下步骤进行:

  1. 创建一个子进程,并使父进程退出。这可以通过调用fork()系统调用来实现。

  2. 子进程调用setsid()系统调用创建一个新的会话并成为新会话的领导进程,从而脱离当前控制终端和进程组的关系。

  3. 将工作目录切换到根目录,以使守护进程不再依赖于任何文件系统。

  4. 关闭所有文件描述符,包括标准输入、标准输出和标准错误输出,避免干扰其他进程或收到不必要的信息。

  5. 重新打开标准输入、标准输出和标准错误输出,将它们指向/dev/null设备,以确保所有输出都被丢弃,不会对其他程序产生影响。

  6. 在守护进程中执行需要的任务,例如接受网络请求、执行系统监控等。

下面是一个简单的创建守护进程的代码示例:

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

int main() {
    pid_t pid;
    int fd;

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

    // 2. 子进程创建新会话并成为领导进程
    if (setsid() < 0) {
        perror("setsid error");
        exit(1);
    }

    // 3. 切换工作目录到根目录
    if (chdir("/") < 0) {
        perror("chdir error");
        exit(1);
    }

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

    // 5. 重新打开标准输入输出并重定向到/dev/null
    fd = open("/dev/null", O_RDWR, 0);
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    if (fd > STDERR_FILENO) {
        close(fd);
    }

    // 6. 在守护进程中执行任务
    while (1) {
        // do something...
    }

    return 0;
}

这个例子中,我们创建了一个子进程,并调用setsid()系统调用将其设置为新会话的领导进程。然后,我们切换当前工作目录到根目录以避免依赖于任何文件系统。接着,我们关闭所有文件描述符,包括标准输入、标准输出和标准错误输出,避免干扰其他进程或收到不必要的信息。最后,我们重新打开标准输入、标准输出和标准错误输出,并将它们重定向到/dev/null设备,以确保所有输出都被丢弃,不会对其他程序产生影响。最后,在守护进程中执行需要的任务,例如接受网络请求、执行系统监控等。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不好,商鞅要跑

谢谢咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值