用户进程、终端和内核之间的通信

4
一个用户进程通过三个文件描述符与终端通信。在Unix中,终端被视为文件(例如/dev/tty),并且还具有文件描述符、主要号码和次要号码以供内核识别。因此,内核通过终端与用户进程通信。另一种通信方式是通过我们都知道的系统调用。
假设用户进程正在等待输入(例如:请输入两个数字:_ _)。当我们在键盘上按下12时,键盘缓冲区被填充,与键盘相关的设备驱动程序将识别它,并唤醒其等待队列中的进程。那么这些数据(即12)如何提供给用户进程呢?我猜是通过终端。
此外,如果重定向输出,例如$ ./a.out > file会发生什么?我使用了isatty()来检查该进程是否与任何终端相关联。那么内核如何与用户进程交互呢?假设我的程序需要从键盘获取一些输入。

终端本身在内核中被特殊处理。有进程组,组的前台进程获取控制台输入。您可以使用像screen这样的工具将多个程序置于前台。除了终端的性质外,我不明白您的问题有什么不同?这已经有很多重复的解答了。 - artless noise
2个回答

1
当您的程序调用输入函数时,例如:
nread = read(FILENO_STDIN, buffer, sizeof(buffer));

当进行“系统调用”时,会进入内核。这个内核函数确保您传递给它的缓冲区在程序的地址空间中,并将字符(不超过您传递的大小)从终端设备的内核缓冲区复制到您提供的缓冲区中,并返回这些字符的数量。
如果文件描述符(arg1)指向一个打开的文件,类似的事情也会发生 - 数据来自文件系统的内核缓冲区(可能需要先从实际设备复制到那里)。

我在用户进程中没有使用任何读取函数。我想知道键盘缓冲区中的数据是如何通过终端传递到用户进程的。我在程序中使用了scanf。 我曾经看到过scanf在调用read函数。那么,read函数的参数是如何与scanf映射的呢?缓冲区地址可以是变量的地址(即&x),但是read函数中的大小参数怎么计算呢? - debendra nath tiwary
如果内核直接将键盘缓冲区数据复制到用户空间,那么为什么数据会出现在终端上呢?例如:输入两个整数:__。当我输入时,它不应该出现在终端上,而是应直接复制到变量地址(即用户空间中)。我想知道数据如何显示在终端上并复制到用户空间变量地址。请不要忽略终端部分,我想了解机制。谢谢。 - debendra nath tiwary
@debendranathtiwary scanf() 在内部不调用 read() 函数。 - iqstatic
如果您在某个地方调用了 scanf(),则 read() 函数将被调用以将数据从内核的终端缓冲区传输到用户空间缓冲区。stdio 输入函数是带缓冲区的,因此当缓冲区为空时,典型的策略是发出一个读取请求,给出缓冲区的完整大小,然后未来的 "读取" 可以通过从缓冲区中复制一个或多个字符并调整可用字节数来满足。常量 BUFSIZ 给出了该缓冲区的名义大小。 - John Hascall
@JohnHascall 谢谢。好的,输入、输出和输出流只有一个缓冲区吗?据我所知,输出流没有与任何缓冲区相关联。如果我错了,请纠正我。另外,我该如何直接访问这些缓冲区呢? - debendra nath tiwary

0

对于你的问题,高层次的回答是你所拥有的。

User process <> Kernel <> Terminal Driver

在某些系统中,终端驱动程序可能是内核的一部分。在其他系统中,它是在内核模式下执行的单独代码(微小的区别)。
当有人按下键时,它会触发系统中断,由驱动程序处理。在这里,根据内核告诉驱动程序如何行为或驱动程序的实现方式,可能会发生以下两种情况之一。
1)驱动程序可能只是将按键存储在缓冲区中;或 2)驱动程序每次获取按键时都会通知内核。
内核可以以多种方式与进程交互,具体取决于系统和进程如何配置终端:
1)内核可能不对来自终端的数据进行任何操作,直到进程调用它。进程提供一个缓冲区,内核从其内部缓冲区(或驱动程序的缓冲区)复制数据。 2)内核可能向进程发送软件中断(例如Windows或VMS)。在这种情况下,进程事先向内核提供了一个缓冲区,供其复制数据。 3)内核可能将事件排队到进程中,进程必须查询该事件。
关于您的部分问题,重定向完全在内核外管理。应用程序(通常是命令行shell)通常会解释此内容。
  ./a.out > file 

1) Open FILE.
2) Create a new process where the standard output is the handle to FILE.
3) Run a.out in that process.

./a.out > file 与终端无关(因为isatty失败), 但是 ./a.out < file 与终端相关(因为isatty成功) 这种不同的行为是怎么回事? - debendra nath tiwary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接