1

我正在尝试制作一个程序,使用所述系统调用将 512 个字节从一个文件复制到另一个文件(我可以制作几个缓冲区,memcpy() 然后 fwrite() 但我想练习 Unix 特定的低级 I/ ○)。这是代码的开头:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
     int src, dest, bytes_read;
     char tmp_buf[512];

     if (argc < 3)
        printf("Needs 2 arguments.");

     printf("And this message I for some reason don't see.... o_O");

     if ((src = open(argv[1], O_RDWR, 0)) == -1 || (dest = open(argv[2], O_CREAT, 0)) == -1)
         perror("Error");

     while ((bytes_read = read(src, tmp_buf, 512)) != -1)
         write(dest, tmp_buf, 512);

   return 0;
}

我知道我没有处理读取的文件大小不会是 512 的倍数的事实。但首先我真的需要弄清楚两件事:

  1. 为什么我的消息没有显示?也没有分段错误,所以我最终不得不抄送程序

  2. 这些低级函数究竟是如何工作的?是否有一个指针随着每个系统调用而变化,比如如果我们使用 FILE *file 和 fwrite,我们的 *file 会自动递增,还是我们必须手动递增文件指针?如果是这样,假设 open() 等从不指定文件指针,而只是指定文件 ID,我们将如何访问它?

任何帮助都会很棒。请。谢谢!

4

2 回答 2

3

您看不到打印消息的原因是您没有刷新缓冲区。但是,一旦程序完成,文本应该会显示出来(这永远不会发生,为什么会这样,在 trojanfoe 的评论和 paxdiablo 的回答中进行了解释)。只需在字符串末尾添加换行符即可查看它们。

而且你在读/写循环中有一个严重的错误。如果您读取的字节数少于请求的512字节数,您仍将写入512字节数。

此外,虽然您在打开时确实检查了错误,但您不知道哪些open调用失败了。即使出现错误,您仍然可以继续执行该程序。

最后,这些函数非常简单:它们调用内核中的一个函数,为您处理所有事情。如果您读取 X 字节,则文件指针在调用完成后向前移动 X 字节。

于 2013-11-14T08:20:40.883 回答
2

您看不到该消息的原因是您处于行缓冲模式。只有在发现换行符时才会刷新它。

至于为什么它永远等待,你只会在错误时得到-1。

成功读取到文件末尾会给你一个 0 返回值。

更好的循环将遵循以下原则:

int bytes_left = 512;
while ((bytes_left > 0) {
    bytes_read = read(src, tmp_buf, bytes_left);
    if (bytes_read < 1) break;
    write(dest, tmp_buf, bytes_read);
    bytes_left -= bytes_read;
}
if (bytes_left < 0)
    ; // error of some sort
于 2013-11-14T08:21:38.353 回答