我有以下两个测试文件:
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)
那么如果我们使用上述两种方法来达到相同的结果,结果有什么真正的区别吗?
CTRL+C 是中断信号。它将停止该命令。
CTRL+D是文件结尾或exit(). 当您输入CTRL+时D,它因文件结尾而退出命令。如果你在 shell 中输入CTRL+ ,什么也不会发生。C但是,如果您输入CTRl+ D,它将从大多数系统中当前的 Shell 中退出。
当cat命令运行时,终端处于规范输入模式。简而言之,这意味着终端的线路规则正在处理线路编辑,并响应为终端配置的所有特殊字符(可通过stty命令查看和设置)。
该cat命令只是read()从其标准输入 ing 直到read()调用返回读取的零字节,这是命中文件末尾的 POSIX 约定。
终端并没有真正的“终点”。但存在read()终端设备返回零字节的情况。当线路规则接收到“EOF”特殊字符时,无论当时配置的是read()什么,它都会返回编辑缓冲区中的任何内容。如果编辑缓冲区为空,则返回从 读取的零字节read(),从而导致cat退出。
cat也退出以响应其默认操作是终止进程的信号。线路规程还生成响应特殊字符的信号。“INTR”和“QUIT”特殊字符导致INT和QUIT信号被发送到前台进程(组),该cat进程将是/包含该进程。这些信号的默认操作是终止cat进程。
这导致了可观察到的差异:
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+D和Ctrl+C完全取决于你的 shell 使用的输入编辑库(libedit、readline 或 ZLE)以及该编辑库的配置方式(使用键绑定等)。
| 归档时间: |
|
| 查看次数: |
12233 次 |
| 最近记录: |