有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在什么情况下c的write()函数可以写的数据比请求的少?

我正在以10b到16000B的数据块写入一个文件,突然,每个数据块在4050字节左右被截断(具体地说,是4050、4051和4074字节,按这个顺序)。这意味着后续写入将覆盖本应写入的数据,从而弄乱我的数据。4050b以下的任何数据块都可以很好地写出

不幸的是,我无法复制它。我所拥有的只是一个乱七八糟的文件,所以我正在调试,寻找可能导致这种情况的原因

调试它时,我意识到c的write()函数是在后台被调用的(这是Java代码,FileChannel.write(),但标准库调用c的write并只检查写入的字节数>;0),并且它的文档并不保证它会写出要求的所有数据,只会告诉您写了多少

我不检查用Java语言写回的字节(但我知道,函数签名几乎完全相同),所以修复非常简单。然而,由于我无法重现这一点,我不知道我已经解决了实际问题。因此,我希望一些c专家能告诉我,我正在吸食可卡因,或者在某些合法的情况下,write()一次写入的字节数不能超过4050字节

这是在64位Linux内核3.0.0-26版上运行的

编辑:根据以下注释展开:

我正在写入一个普通的文件系统文件。我不确定非阻塞在这种情况下意味着什么,我没有使用回调或任何东西,但明确告诉操作系统刷新到磁盘并不是针对每个块完成的。该文件是使用Java的RandomAccessFile“rw”模式打开的


共 (2) 个答案

  1. # 1 楼答案

    重现问题的最简单方法是让消费者反应迟钝。当您调用write()时,这将导致发送缓冲区几乎已满,这意味着您提供的数据不能全部写入。您可以减小发送和接收缓冲区的大小,使此问题更加明显

  2. # 2 楼答案

    man 2 write

       The number of bytes written may be less than  count  if,  for  example,
       there  is  insufficient space on the underlying physical medium, or the
       RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)),  or  the
       call was interrupted by a signal handler after having written less than
       count bytes.  (See also pipe(7).)
    

    man 2 setrlimit

       RLIMIT_FSIZE
              The maximum size of files that the process may create.  Attempts
              to extend a file beyond this  limit  result  in  delivery  of  a
              SIGXFSZ  signal.   By default, this signal terminates a process,
              but a process can catch this signal instead, in which  case  the
              relevant  system  call  (e.g., write(2), truncate(2)) fails with
              the error EFBIG.
    

    可以使用以下命令查看这些限制:

    ulimit -Sf
    ulimit -Hf
    

    或使用此C程序:

    #include <stdio.h>
    #include <errno.h>
    #include <sys/resource.h>
    
    int main()
    {
        struct rlimit rl;
        if (getrlimit(RLIMIT_FSIZE, &rl) == 0) {
            printf("%d %d\n", rl.rlim_cur, rl.rlim_max);
        } else {
            fprintf(stderr, "error: %d\n", errno);
        }
        return 0;
    }