【问题标题】:C syntax of a stream not associated to any peripheral与任何外围设备无关的流的 C 语法
【发布时间】:2020-05-03 14:20:53
【问题描述】:

我在下面引用了 The C Programming Language 的第二版。

B.1 输入和输出:,第 2 节:

是可能与磁盘或其他外围设备相关联的数据源或目标。

然后可以说流可能与任何外围设备相关联:流可以存在而不与任何外围设备相关联。

因此出现了以下问题:与任何外围设备无关的流是什么样的?

考虑到作者

B.1 输入和输出:,第 3 节:

[...] 交替使用“文件指针”和“流”[...]

FILE *p;
p = NULL;

这么好的答案?

【问题讨论】:

  • fopencookie 可以关联...任何你想要的。

标签: c file-io stdio


【解决方案1】:

如果“文件指针”和“流”确实是严格的同义词,那么:

FILE *fp = NULL;

定义了一个,它(还没有)与任何外围设备相关联。也不是 (但)与任何数据源或目标相关联。

如果您要问 Brian Kernighan 或已故的 Denis Ritchie,“fp 真的在那里吗?”, 他们可能会说“好吧,也许不是。每当它在使用中 用于 I/O 时,它就是一个流——当你成功打开它时,直到你 成功关闭它。不用的时候说是流,还是说文件指针,都没什么大不了的。”

用于 I/O 的文件指针(或流)是某些 C 语言的编程表示 数据的来源或目的地。该源或目标可能是 - 或在 - 外围设备 例如 U 盘、SSD 或 HDD、磁带卷或终端。或者它可能不会。 C 的定义 没有指定或限制FILE * 可以表示的数据源或目标的物理实现。这就是为什么书中说数据的来源或目的地可能与磁盘或其他外围设备相关联。

C 标准库仅提供函数fopen, in <stdio,h>(它是强化变体fopen_s)作为 一种从头开始创建流的方法。1 它提供了众所周知的现成的FILE *stdinstdoutstderr<stdio.h> 这样提供的流通常但不一定与外围设备相关联。

标准库以外的 C 库可能会为您提供函数 返回与外围设备无关的FILE * 流。例如。这 Linux C 库为您提供fmemopen 和朋友们, 它为内存区域提供FILE * I/O。

您甚至可以仅使用<stdio.h> 工具在内存中读取或写入FILE * 流。 Linux 让您轻松创建tmpfs 虚拟内存 文件系统。然后,您可以纯粹用标准 C 编写执行常规 FILE * I/O 的程序 在您的tmpfs 文件系统中,并且它们都不会与外围设备相关联。 C 不知道也不关心文件系统的实现。


[1] 还有freopenfreopen_s,它们关闭现有流并打开 再次使用新的文件名。

【讨论】:

  • 启蒙。对于我在问题中提到的引用,我没有这样阅读 may 运算符。
【解决方案2】:

这取决于您如何定义“外围设备”。有些特殊设备不是连接到机器上的硬件意义上的“外围设备”。

例如,/dev/null/dev/zero 就是两个这样的设备。如果您打开这些(/dev/zero 用于读取,/dev/null 用于读取或写入),然后将流与它关联,它们并没有真正与外围设备通信。你也可以对/dev/random 和/或/dev/urandom 提出同样的看法(它们是只读的)。

在 Linux 上,您可以在 /proc 文件系统下打开文件——它们与外围设备没有直接关联。

【讨论】:

  • 也许我们可以将“外围设备”的概念视为“文件”或“设备”的子集(假设“文件”和“设备”是同义词)。那么我们首先可以区分两种“设备”:“外围设备”和“非外围设备”。因此,我们可以编写与任何“文件”或“设备”无关的流的通用形式:FILE *p = NULL;,但对于与任何“外围设备”无关的流(在这种情况下,正如您提到的,仅FILE *p = fopen("/dev/null", "r");FILE *p = fopen("/dev/zero", "r"); 等都适合。)
  • 我没有提到伪终端或伪 tty(同样的事情)。他们很棘手。总的来说,它们不是外围设备。如今,绿屏终端对大多数人来说是遥远的过去,但终端是 GUI 界面中的一个窗口。这可能或多或少算作外围设备。我不确定这里有什么有用的区别。文件流是文件流是文件流。有你可以寻找的流(磁盘文件,包括 SSD,也许是磁带驱动器)和更多你不能寻找的流(管道,FIFO,套接字,...)。如果这是一个家庭作业问题,请研究课程笔记。
  • 这不是作业问题。由于我对 C 编程很陌生,所以当我需要从概念上理解某些东西时,我会阅读 K&R 书。我知道流的概念是一个高级概念,因此它可以应用于许多不同的设备。因此,如果没有更深入的层次,对它的综合和系统理解可能会非常复杂。正如您在我的文字中看到的那样,我正在尝试使用一些非常基本的代码来解决问题。
  • 我会将FILE *fp = NULL; 视为“非流”或“无法打开”流。它不是流;它当然没有连接到任何外围设备。在很大程度上,Unix(甚至 Plan9)将所有内容都视为一个文件。这是一个了不起的统一概念。这意味着您大部分时间都不必担心文件流正在读取或写入的内容。如果它是可读流,则可以从中读取。如果它是可写流,则可以写入。大多数时候,这就足够了。实际上,您不必担心它是否连接到外围设备。
  • 阅读 K&R 的书,我在想:既然写了FILE *fp;,它就存在一个流(fp),任何人都可以用它。 (因为它存在一个整数指针,因为自从写了int *p;,可以用p 做任何事情。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多