awakeBird Back-end Dev Engineer

Linux基础(六)作业控制与Deamon进程

2018-12-22

该系列文章为《Linux/Unix系统编程手册》的学习笔记,由于该书太过冗长,属于工具书的类别,这里对书中的一些核心内容加以提炼和整理。 书中的编程练习这里不做展示和说明。

概念

  • 进程组:一组相关进程的集合。作业即进程组。
  • 进程组ID:PGID,创建进程组的进程为进程组首进程,这个进程的PID为进程组ID,子进程会继承父进程的进程组ID。
  • 会话:一组进程组的集合。
  • 会话ID:SID,创建会话的进程为会话首进程,其PID为会话ID,子进程会继承父进程的会话ID。
  • 控制终端:会话首进程首次打开一个的终端设备,一个终端设备最多可以成为一个一个会话的控制终端,拥有控制终端的进程可以通过一个特殊的设备文件/dev/tty获取控制终端的文件描述符。
  • 前台进程组:在任意时刻,会话中的一个进程组会成为终端的前台进程组,其余进程组为后台进程组。只有前台进程组中的进程才能从终端中读取输入,在控制中端中键入字符产生的信号也只会发给前台进程组中的进程。
  • 终端控制进程:建立控制终端后,会话的首进程成为该终端的控制进程。
  • shell:具有特殊用途的程序,用于读取用户输入的命令以执行相应的程序响应命令,又称为命令解释器。
  • 登陆shell:用户登陆系统时,由系统创建用于运行shell的进程。

当登陆一台Linux服务器后,登陆shell成为登陆会话的首进程和终端的控制进程,后续执行的每一个命令都会导致一个或多个进程创建,shell会把这些进程放在一个新进程组中,这些进程组都是进程会话的一部分。

与作业控制相关的信号:

  • SIGINT:终端中断,键入CTRL+C字符生成。
  • SIGQUIT:终端退出,键入CTRL+\生成。
  • SIGSTP:中断挂起,键入CTRL+Z生成。
  • SIGHUP:当控制进程断开与终端的连接时内核会向控制进程发送此信号。
  • SIGTTIN:后台进程组尝试从终端读取字符串时会受到此信号,默认停止作业。
  • SIGTTOU:后台进程组尝试向设置了TOSTOP(终端输出停止)标识的终端输出内容时收到此信号,默认停止作业。

进程组与会话行为

进程组

int setpgid(pid_t pid, pid_t pgid);

setpgid系统调用用于将进程id为pid的进程的进程组id变更为pgid

  • pid若为0则会将该值替换为当前进程的pid。
  • pgid若为0会以pid的值创建新的进程组,并将pid进程设置为进程组首进程。

改变进程组id存在限制:

  • pid仅可以指定当前进程及其子进程。
  • pid指定的进程不能使会话首进程。
  • 子进程如果已经执行了exec,则不能被修改进程组id了。
  • pgid仅可以指定相同会话内的pgid,创建的新进程组也属于当前会话。

会话

pid_t setsid(void);

setsid系统调用将会创建新会话:

  • 调用进程将成为会话首进程以及会话中新进程组的首进程。
  • 调用进程没有控制终端。之前与控制终端的连接会被断开。

限制:

  • 进程组首进程不能创建新会话。避免该限制的方法为fork出一个子进程并让父进程终止,之后由子进程调用setsid,由于子进程会继承父进程的PGID,因此子进程不可能是进程组首进程。

只有会话首进程能够打开终端设备并建立控制终端,之后次进程成为终端的控制进程,若控制进程终止:

  • 会话中的所有进程会失去与终端的关联关系。
  • 终端可以被其他会话的首进程控制。
  • 内核会向前台进程组的所有成员发送SIGHUP信号。

大多数会话的首进程都是shell,shell为SIGHUP信号设置了信号处理程序,会关闭shell并向由这个shell创建的所有进程组成员发送SIGHUP信号

作业控制

作业控制是shell的特性,允许在一个shell上同时执行多个命令(即作业/进程组),其中一个命令在前台运行,其余命令在后台运行。作业可以被停止或恢复运行以及在前后台之间来回切换。

➜  ~ sleep 3 &
[1] 10428

在命令后加&可使进程组在后台运行,同时shell上会显示两个数字,方框内的数字为shell赋予每个作业的作业号num,后面的数字为执行命令的进程id或管道内最后一个进程的进程id。

作业控制命令

在shell的作业控制中用%num来引用某个作业

  • jobs:列出所有的后台作业
  • fg %num:将某个后台作业移动到前台
  • Type Ctrl+Z:键入Ctrl+Z挂起字符会向前台进程组发送SIGTSTP信号停止前台进程组。
  • bg %num:向某个作业发送SIGCONT信号恢复执行
  • stty tostop:设置TOSTOP(终端输出停止)标识

Daemon进程

概述

Deamon进程应具备以下特征:

  • 生命周期很长:一般会在系统启动时创建并一直运行到系统关闭。
  • 在后台运行并且不拥有控制终端:终端缺失保证内核永远无法为Deamon进程生成终端相关信号,如SIGINT、SIGTSTP和SIGHUP。

Linux常用Deamon进程:

  • cron:定时任务。
  • sshd:安全shell,允许远程主机使用安全通信协议登录系统。
  • httpd:http服务器deamon。
  • inetd:Internet超级服务器deamon,监听指定TCP/IP端口上的网络连接并启动响应服务器程序处理这些链接。

创建流程

  1. 执行fork(),之后父进程退出,子进程继续运行。(防止进程为进程组首进程,确保其可以创建会话)
  2. 调用setsid()开启新会话。(使进程断开所有控制终端)
  3. 第二次调用fork(),父进程退出,子进程继续运行。(防止进程为会话首进程,确保其不会控制任何终端)
  4. 清除进程的umask。 (确保拥有创建文件和目录的权限)
  5. 将进程的工作目录修改为根目录(/)。(确保当前工作目录无法被卸载)
  6. 关闭从父进程继承的打开的文件描述符,关闭指向终端的0、1、2文件描述符。
  7. 打开/dev/null,并使用dup2将0、1、2文件描述符指向这个设备。(确保在0、1、2上的io库函数不会失败,也防止使用这些文件描述符打开其他的文件)

重新初始化Deamon

由于Deamon永远不会建立控制终端,因此不会收到SIGHUP信号,Deamon可以选择为SIGHUP信号建立信号处理函数来重新初始化自身

syslog

Deamon程序编写的一个问题是如何显示错误信息,Linux提供了一个集中日志工具,系统中的所有应用程序都可以使用这个工具来记录日志信息。syslog包含两个组件:

  • syslogd deamon:从两个不同的源接收日志,一个UNIX domain socket/dev/log,保存本地产生的消息;另一个Internet domain socket(UNP端口514),保存通过TCP/IP发送的消息。
  • syslog(3) 函数:供进程调用来记录消息,会使用传入的参数以标准格式构建一条消息,将其写入/dev/logsocket供syslogd读取。

由syslogd处理的消息包括两个特性:

  • facility:指定了消息产生的程序类型
  • level:指定了消息的严重程度(优先级)

syslogd根据这两个特性,以及配置文件/etc/syslog.conf中的指令将消息传递到几个目录中的一个或多个:

  • 终端或虚拟控制台
  • 磁盘文件
  • FIFO
  • 一个或多个登陆过的用户
  • 位于另一个系统上的通过TCP/IP网络连接的进程

API

void openlog(const char *ident, int log_options, int facility);

openlog()会建立一个到系统日志的连接,调用是可选的,如果没有建立连接,在调用syslog()时会使用默认设置建立连接。

  • ident为一个指向字符串的指针,syslog()输出的每个消息都会包含这个字符串。
  • facility的默认值为LOG_USER,表示用户进程生成的消息。
void syslog(int priority, const char *format, ...);

syslog()会记录一条日志消息。

  • priorityfacilitylevel的OR值,如果省略这个参数,会采用前一个openlog()调用中指定的facility值,如果没有调用或没有facility参数时会设置为LOG_USER
  • format参数是一个格式字符串。在调用syslog时如果使用参数传入字符串需要在前面先指定%s参数,如syslog(priority, %s, user_string),而不应该是syslog(priority, user_string)
void closelog(void);

closelog()会关闭到系统日志的连接并释放分配给/dev/logsocket的文件描述符。deamon进程通常缺失这个调用。

int setlogmask(int mask_priority);

setlogmask()会设置一个掩码,所有level不在这个掩码中的消息都会被过滤。有两个宏可以将level替换为mask_priority参数,分别是LOG_MASKLOG_UPTO

配置文件

/etc/syslog.conf配置文件控制了syslogd deamon的行为,配置规则如下

facility.level    action

下面是一个例子,表示所有level为err或者更高级别的消息被发送到/dev/tty10控制台设备上。

*.err    /dev/tty10

在修改配置文件后需要发送SIGHUP信号来初始化syslogd。

$ killall -HUP syslogd

(End)


Comments

Content