【问题标题】:Equivalent of fgetc with Unix file descriptorsfgetc 等价于 Unix 文件描述符
【发布时间】:2015-11-14 21:36:00
【问题描述】:

fgetc(3) 函数将FILE * 作为其输入流。我必须使用read(2) 重新实现一次字符输入,还是有一个<unistd.h> 样式的等效项来代替整数文件描述符?

【问题讨论】:

  • integer file descriptor ?
  • ssize_t read(int fd, void *buf, size_t count); 来自手册页。
  • 所以您想使用int variableopen 文件?
  • 是的,这将是使用open(2) 打开文件的标准方式。

标签: c unix io stream file-descriptor


【解决方案1】:

如果您愿意,可以使用open() 打开文件 -

int fh = open("abc.txt", O_RDONLY, S_IREAD);  // there are different permissions you can provide (refer to link).

然后您可以在read() 调用中使用fh

【讨论】:

  • 请注意,stat() 的 Linux 手册页说明 S_IREAD 在 POSIX 中不是标准的,因此不应在新代码中使用 S_IREAD;请改用 POSIX 标准 S_IRUSR。然后你会注意到open() 是一个可变参数函数;可以使用 2 或 3 个参数调用它。如果第二个参数包含O_CREAT,那么第三个参数的存在和合理设置是至关重要的。如本例所示,如果没有创建文件,则不需要第三个参数(不过,如果设置得当,我不会反对)。
【解决方案2】:

不,不存在这样的事情,请永远不要执行read(fd, &ch, sizeof(char))(解释如下)。

read(2) 函数通常实现为操作系统kernelsystem call。尽管此处不应讨论此类事物的内部(和时髦)细节,但总体思路是系统调用(通常)便宜。

用户空间应用程序和内核执行系统调用只是为了从文件描述符中获取单个字符是低效的。

例如,fgetc(3) 通常最终会在 FILE 对象的结构中进行一些缓冲。这意味着 fgetc(3) 的内部 read(2) 不会只读取单个字符,而是会尝试获取更多信息效率。

无论如何,搞砸这种低级的东西通常不是一个好主意。您可以通过使用fdopen(3) 从文件描述符创建 FILE 对象来获得缓冲(以及 FILE 整体)的所有好处,正如您的问题似乎暗示的那样你现在手头只有一个原始文件描述符。

【讨论】:

  • 实际上shell内置read命令必须以1字节/字符的长度重复调用read,因为它必须让所有超出换行符的内容都未读下一个要读取的命令。因此,尽管效率极低,但有时您别无选择。
  • 这不是真的。 shell 可能会使用某种缓冲区来存储“错误地预取”的命令字符串以供将来使用。我实际上已经这样做了一次或另一次,这仍然保持效率,所以仍然不需要read(fd, &ch, sizeof(char))
  • @KemyLand:正如 rici 所说,接下来读取的不一定是 shell。如果您有一个高度优化的 shell 解释器,它可能能够确定下一个执行读取操作,但一般来说,执行下一个读取操作的将是其他一些外部命令。因此,您确实被单字节读取所困扰。只需使用 strace 并查看任何真实世界的 shell 的作用。
  • @R..:@rici:好吧,我很抱歉。一个简单的strace 确认shell 确实在无缓冲模式下一次读取一个字节,我认为我们这里的所有人都同意它的效率非常低(现在我知道为什么shell 会这么慢)。 (@R..:不知何故我在你编辑之前做了strace :))
  • @kemyland:速度很慢。但除非有更好的方法来做到这一点,否则它不会是低效的,有时就是没有。 (“高效”并不是说“快”的花哨方式。它的意思是“使用尽可能少的资源尽可能来解决问题。”)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 2011-11-22
  • 1970-01-01
相关资源
最近更新 更多