【问题标题】:Random integers coming from the "write" system call are not recognized from the "read" system call in CC 中的“读”系统调用无法识别来自“写”系统调用的随机整数
【发布时间】:2014-05-23 11:41:48
【问题描述】:

我正在尝试使用系统调用“write”将固定数量的随机整数写入文件,然后检查它们是否正确写入。为此,我调用了“读取”函数,然后逐个整数地读取所有文件内容并将它们打印到另一个文件中。

问题在于,尽管 write 函数正确写入了随机整数(大小为 500),但 read 函数能够提取其中的 200 个,然后返回其余 300 个的垃圾。有时,它只返回 10 个他们。每次我运行代码时,它都有不同的行为。

我已检查“写入”功能是否通过将所有数字打印到另一个文件(例如 file1)来正确写入它们。但是,打印“读取”函数返回的数字(例如 file2)向我表明它们并不完全相同。

我意识到,如果我使用单个数字(例如 5)而不是随机整数,则一切正常。我用谷歌搜索了很多,我检查了我是否正确打开/关闭文件,但我无法解决问题。

这是我的 C 代码。我删除了一些错误检查,以便向您展示一个小脚本。 你能帮帮我吗?

int main()
{
    srand ( time(NULL) );

    // write
    int fd = open("file_test_1", O_CREAT | O_WRONLY);
    int val;
    if (fd != -1) {
        for(int i=0;i<500;i++){
            val = (int) rand()%500;
           // val = 5;
            write(fd, &val, sizeof(val));
        }
    }
    close(fd);

    FILE * file_check;
    file_check=fopen("file_test_1_check","w");

   // test read
    fd = open("file_test_1", O_RDONLY);
    int new_val;
    int x;
    if (fd != -1) {
        while(  ( x = read(fd, &new_val, sizeof(new_val)) )>0 ){
            fprintf(file_check,"%d\t\t%d\n",new_val, x);
        }

    }
    close(fd);
    fclose(file_check);
    return 0;
}

【问题讨论】:

  • 你得到的数据和垃圾的例子?
  • 刚刚试了一下。工作正常。需要更多信息。
  • 我刚刚试了一下,使用 S_IWUSR 作为第一个 open 调用的第三个参数,设置文件所有者的读取权限。它仍然无法正常工作。
  • 好吧,我打印到 file_test_1_check 随机数和读取函数中的字节。所以,我第一次执行代码,我得到了类似的结果: 492 4, 177 4 ... 200 行。但是,在第二次执行中,我得到了 300 行,然后是 90368 4, 127488 4, ... 其他 100 行。
  • 非常适合我。您可以尝试发布最小的完整可编译代码来重现您的症状。

标签: c random integer system-calls


【解决方案1】:

使用O_CREAT打开文件时,需要为后续用户设置文件权限。您可以通过指定 pmode 来做到这一点,即 OR 标志 S_IREAD S_IWRITE 的组合(继续使用两者)。此外,由于您正在编写二进制文件,因此使用O_BINARY 通知系统不会有什么坏处。所以正确的open 应该是:

int fd = open("file_test_1", O_BINARY | O_CREAT | O_WRONLY | S_IREAD);

现在,当您重新打开该文件时,您确实需要以二进制形式打开它,因此正确的后续打开方式是:

fd = open("file_test_1", O_RDONLY | O_BINARY);

【讨论】:

    【解决方案2】:

    您的第一个open 呼叫是错误的。根据手册页,当您将 oflag 参数中的 O_CREAT 传递给 open 时,需要第三个 mode 参数。这将是文件的访问模式。在我的系统上,open 看到省略的第三个参数(寄存器或堆栈中的剩余值)为 0,因此下一个 open(读取文件)失败。

    【讨论】:

    • 谢谢安德鲁。我读了这个例子 [codewiki.wikidot.com/c:system-calls:open].所以,我可能应该在参数中写: (O_WRONLY | O_CREAT, S_IRUSR),以便能够再次读取文件?
    • 我尝试了上述参数组合,还有这个:O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR 和我没有解决问题。
    • 它对我有用。您是否先删除旧文件?如果旧文件(000 模式)仍然存在,则不会更改其权限(因为 open 调用并未创建它)。
    • 我试图将其删除而不是删除。读取函数的结果仍然是相同的不可预测的结果。
    猜你喜欢
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2013-11-27
    • 2014-12-25
    • 2015-05-27
    相关资源
    最近更新 更多