read() 未按预期工作。 Returns 成功读取大块时值为 1

read() not working as expected. Returns value 1 on successful read of large block

我正在开发一个进程,其中包括复制文件。我 运行 遇到一个问题,即读取功能无法按预期工作。

我的研究和之前的经验告诉我,(fcntl) read() 函数应该 return 读取的字节数,但它是 returning 1。我已经达到了尝试的极限(主要是在 16 到 16MB 的缓冲区大小之间变化)。无论我尝试什么,我总是以分段错误(缓冲区大小 16MB)或 read() returns 值为 1.

结束

为了证明这一点,我已将程序减少到最低限度,它仍然可以编译和执行,但不会执行所需的操作。为了获得良好的性能,我需要一个很好的大缓冲区(最好是 15MB,但 1MB 也可以)。在此应用程序中,缓冲区大小为 1M,输出文件大小最终为原始大小的 1/1048567 倍(因此 16MB 输入文件被复制为 16 字节)。是的,我可以将缓冲区大小设置为 1,但如前所述,这应该比那个更有效。

这可以在您的系统上进行测试,方法是将“in”设置为系统上的某个现有文件,并将“out”设置为同样有效的文件名。注意:“out”如果存在将被覆盖!!!

环境为 Cygwin 3.2.0(0.340/5/3)

我需要做什么才能使这项工作如记录那样工作的任何线索?

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

#define BOOL char
#define TRUE (1 < 2)
#define FALSE (1 > 2)
#define MAX_BUFFER_SIZE 1048576 // 1M.  16MB (16777216) will caus segmentation fault

int    copyfile(const char *in, const char *out) ;
BOOL debug = TRUE ;


int main(int argc, char *argv[]) {
    int rc = 0 ;
    char *in = "/e/DCIM/100MEDIA/DJI_0292.MP4" ;
    char *out = "/m/Videos/2021/2021-08-Other/temp/08140708_dji_0292.mp4" ;

    rc = copyfile(in, out) ;
    return rc ;
    }



int copyfile(const char *in, const char *out) {
    int rtnVal = TRUE ;
    int fd_in, fd_out ;
    char buff[MAX_BUFFER_SIZE], *out_ptr ;
    ssize_t nRead, nRemaining, nWritten, totWritten = 0 ;
    int save_errno ;
    struct stat st ;

    unlink(out) ; // In case it exists ...
    if ((fd_in = open(in, O_RDONLY)) < 0) {
        fprintf(stderr, "Could not open input file %s\n\t%s\n", in, strerror(errno)) ;
        rtnVal = FALSE ;
        }
    else if ((fd_out = open(out, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) {
        fprintf(stderr, "Could not open output file %s\n\t%s\n", out, strerror(errno)) ;
        rtnVal = FALSE ;
        }
    if (rtnVal) {
        if (stat(in, &st) < 0) {
            fprintf(stderr, "Could not stat input file: %s\n\t%s\n", in, strerror(errno)) ;
            exit(1) ;
            }
        if (debug)
            fprintf(stdout, "\n\n\nSize of %s is %ld\n", in, st.st_size) ;
        while (((nRead = read(fd_in, buff, MAX_BUFFER_SIZE) > 0) && (rtnVal == TRUE))) {
            // if (debug)
            //     fprintf(stdout, "%ld bytes read this time.\n", nRead) ;
            out_ptr = buff ;
            nRemaining = nRead ;
            while (nRemaining > 0) {
                nWritten = write(fd_out, out_ptr, nRemaining) ;
                if (nWritten >= 0) {
                    out_ptr += nWritten ;
                    totWritten += nWritten ;
                    nRemaining -= nWritten ;
                    if (debug)
                        fprintf(stdout, "\tDEBUG: %ld bytes read. So far, %ld bytes have been written. %ld remain\n"
                                      , nRead, totWritten, nRemaining) ;
                    }
                else if (errno != EINTR) { // No error - try again (see 
                    rtnVal = FALSE ;
                    fprintf(stderr, "Could not copy from: %s\n"
                                    "                 to: %s\n"
                                    "     %s\n"
                                  , in, out, strerror(errno)
                                   ) ;
                    break ;
                    }
                } // While remaining
            }     // While read()
        }         // If rtnVal
    save_errno = errno ;
    if (fd_in)  close(fd_in) ;
    if (fd_out) close(fd_out) ;

    if (stat(out, &st) < 0) {
        fprintf(stderr, "Could not stat output file: %s\n\t%s\n", in, strerror(errno)) ;
        exit(1) ;
        }
    if (debug)
        fprintf(stdout, "Size of %s is %ld\n", out, st.st_size) ;
    errno = save_errno ;
    return(rtnVal) ;
    }

样本运行:

Size of /e/DCIM/100MEDIA/DJI_0292.MP4 is 406514367
    DEBUG: 1 bytes read. So far, 1 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 2 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 3 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 4 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 5 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 6 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 7 bytes have been written. 0 remain
...
...
    DEBUG: 1 bytes read. So far, 385 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 386 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 387 bytes have been written. 0 remain
    DEBUG: 1 bytes read. So far, 388 bytes have been written. 0 remain
Size of /m/Videos/2021/2021-08-Other/temp/08140708_dji_0292.mp4 is 388

您将 nread 设置为 > 比较运算的结果,而不是 read() 的结果,因为 > 的优先级高于 [=15] =].您需要在作业周围加上括号。

while ((nRead = read(fd_in, buff, MAX_BUFFER_SIZE)) > 0 && rtnVal) {