我试图了解为什么 .xsession 文件期望最后一个进程位于前台,否则它应该停止 X11 会话。
我有一个小的独立脚本。当我运行它时,它立即退出,因为“less”只是在后台。
$ ls -l total 4
-rwxr-xr-x 1 user user 17 Feb 28 21:17 a
-rw-r--r-- 1 user user 0 Feb 28 20:22 b
$ cat a
less b &
echo $!
我了解“较少”工具主要在前台交互。我不知道它是如何实现的,但我想它意识到它不再在前台运行,并且无法获取输入或向用户显示一些输出,因此运行不再有用,因此它退出。或者到底发生了什么?
当您将“窗口管理器”置于后台时,为什么它会退出?它是否退出是因为它不在前台运行并且无法通过 X 服务器获取任何键盘/鼠标输入并且它不再有用所以它退出?
答案1
这实际上是两种完全不同的现象。
less
它本身不会检查它是否在后台(这是与终端交互的程序的典型情况)。内核中的通用终端驱动程序会跟踪进程 1 中的进程。前景。只能有一个前台进程(更准确地说是一个进程组)。 shell 进行系统调用(tcsetpgrp
) 当fg
使用内置函数将进程置于前台时。该系统调用使指定进程成为前台进程。
当进程尝试从终端²读取数据时,如果它不在前台,终端驱动程序会向进程发送 SIGTTIN 信号。默认情况下,此信号会挂起进程(如 SIGSTOP)。类似地,尝试写入其控制终端的后台进程会收到 SIGTTOU。大多数 shell 通常会在发生这种情况时显示一条消息[1] + suspended (tty output) less myfile
。
有关终端的更多信息,请参见终端的说明通用终端接口在 POSIX 标准中。 (这本书读起来并不容易。它比大多数用户甚至更多程序员需要了解的内容要多得多。)
窗口管理器不与终端交互,因此终端中的后台和前台进程的概念不适用于它。发生的情况是,当 X 会话终止时,X 服务器 3 也会终止。调用窗口管理器的脚本告诉我们在会话中要做什么。如果将窗口管理器置于后台并让会话脚本退出而不等待窗口管理器,则会导致会话比您预期的更早结束。
¹什么进程组,实际上(例如管道),但我们不需要在这里深入讨论这一细节。
²只针对其控制终端实际上。
³ GUI 的后端部分,执行从应用程序绘制窗口、读取输入等命令
答案2
不要求窗口管理器位于前台、后台或处于任何类型的作业控制之下。如果您不愿意,您甚至不必运行窗口管理器!
唯一重要的是,当.xsession
脚本终止时,会话也就结束了。如果.xsession
终止,则 X 服务器本身终止,并且仍与其连接的任何进程都将被强制终止。
因此,.xsession
通常构建脚本,以便脚本运行的最后一件事是与会话相关的某种长时间运行的进程。它可以是窗口管理器,也可以是会话管理器(在现代精美的桌面环境下更典型)。该进程要么运行exec
,以便替换正在运行的 shell .xsession
,要么作为前台进程运行,以便 shell 等待它。无论哪种方式,当该进程退出时,会话就会结束。
您的示例 shell 脚本less
在后台启动,然后立即退出。它不等待后台进程。无论是否less
退出,它都会退出。less
可能会继续在后台运行,但无论启动你的 shell 脚本,都不会注意到这一点。.xsession
以相同方式构建的脚本也会出现相同的问题。