使用 Ctrl+D 和 Ctrl+C 终止 cat 命令有什么区别?

Son*_*vol 4 cat

我有以下两个测试文件:

test1 test2
Run Code Online (Sandbox Code Playgroud)

两者都是空白。现在我发出以下命令:

$ cat > test1  
Run Code Online (Sandbox Code Playgroud)

Enter

This is a test file
Run Code Online (Sandbox Code Playgroud)

Enter

Ctrl + D

$ cat > test2
Run Code Online (Sandbox Code Playgroud)

Enter

This is another test file
Run Code Online (Sandbox Code Playgroud)

Enter

^C
Run Code Online (Sandbox Code Playgroud)

Ctrl + C

$
Run Code Online (Sandbox Code Playgroud)

现在我检查两个文件的内容

$ cat test1
This is a test file
$ cat test2
This is another test file
$
Run Code Online (Sandbox Code Playgroud)

那么如果我们使用上述两种方法来达到相同的结果,结果有什么真正的区别吗?

Kau*_*yak 5

CTRL+C 是中断信号。它将停止该命令。

CTRL+D是文件结尾或exit(). 当您输入CTRL+时D,它因文件结尾而退出命令。如果你在 shell 中输入CTRL+ ,什么也不会发生。C但是,如果您输入CTRl+ D,它将从大多数系统中当前的 Shell 中退出。

  • @Sonevol 不同。CTRL+D 的工作方式类似于 EOF,而 CTRL+C 则为 intr(检查“stty -a”以了解线路规则的这些设置)。尝试“cat > foo.txt”。输入一些内容,单击 CTRL+D 并检查“foo.txt”。然后用 CTRL+C 检查它。 (3认同)

Jde*_*eBP 5

cat命令运行时,终端处于规范输入模式。简而言之,这意味着终端的线路规则正在处理线路编辑,并响应为终端配置的所有特殊字符(可通过stty命令查看和设置)。

cat命令只是read()从其标准输入 ing 直到read()调用返回读取的零字节,这是命中文件末尾的 POSIX 约定。

终端并没有真正的“终点”。但存在read()终端设备返回零字节的情况。当线路规则接收到“EOF”特殊字符时,无论当时配置的是read()什么,它都会返回编辑缓冲区中的任何内容。如果编辑缓冲区为空,则返回从 读取的零字节read(),从而导致cat退出。

cat也退出以响应其默认操作是终止进程的信号。线路规程还生成响应特殊字符的信号。“INTR”和“QUIT”特殊字符导致INTQUIT信号被发送到前台进程(组),该cat进程将是/包含该进程。这些信号的默认操作是终止cat进程。

这导致了可观察到的差异:

  • Ctrl+D只有当它是 EOT 特殊字符时才有这个动作。这通常是这种情况,但不一定是这种情况。类似地,Ctrl+ 也C只有在它是 INTR 特殊字符时才有它的作用。
  • Ctrl+D不会cat在该行当时实际上不为空时导致终止。但是,Ctrl+C会产生中断。
  • cat如果发现它指向一个文件,C 语言中的一个天真的实现将阻止缓冲区标准输出,如问题所示。理论上,如果cat由 终止,这可能导致缓冲且尚未输出的行丢失SIGINT

    实际上,BSD 和 GNU C 库实现了 C 或 C++ 语言标准中未描述的缓冲模式。重定向到文件或管道时的标准输出是智能缓冲的。它是块缓冲的;除了每当 C 库发现自己即将到达read()任何对终端设备打开的文件描述符的新行的开头时,它都会刷新标准输出。(严格来说,BSD 和 GNU C 库并没有完全实现相同的语义并且做的比这更多,但这种行为是一个常见的子集。)因此,当中断信号cat建立在这样的基础之上时,不会导致丢失缓冲输出C库。

  • 当然,如果cat是命令管道的一部分,则其他一些进程可能会cat在这些数据到达输出文件之前缓冲数据。因此,当线路规则再次发送SIGINT(默认情况下)终止管道中的所有进程时,已缓冲但尚未写入的输入数据将丢失;而终止cat与“EOF”特殊字符,通常会导致管道正常终止,所有传递到下游工艺中的数据之前,接收来自EOF指示 read()它的标准输入的。

请注意,这与交互式 shell 读取您的输入行时发生的情况几乎没有关系。当您的 shell 正在等待输入时,终端处于非规范输入模式,在这种模式下,线路规则不会对特殊字符进行任何特殊处理。你的 shell 如何处理Ctrl+DCtrl+C完全取决于你的 shell 使用的输入编辑库(libedit、readline 或 ZLE)以及该编辑库的配置方式(使用键绑定等)。

进一步阅读