You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cygwin环境下fcntl的read()返回1而非实际读取字节数问题求助

问题根因与解决方案

你遇到的两个问题都是代码编写失误导致的,和read函数本身、Cygwin环境无关,修正方案如下:


1. read始终返回1的问题

这是运算符优先级错误导致的:
你写的while条件存在括号位置错误:

// 错误写法
while (((nRead = read(fd_in, buff, MAX_BUFFER_SIZE) > 0) && (rtnVal == TRUE)))

C语言中>比较运算符的优先级高于=赋值运算符,所以实际执行顺序是:

  • 先调用read得到实际读取字节数
  • 判断这个返回值是否>0,得到布尔结果1(真)或0(假)
  • 把这个布尔值赋值给nRead
    所以只要成功读到数据,nRead永远是1,和read的实际返回值无关。

修正方法:把赋值逻辑单独用括号包裹:

// 正确写法
while (((nRead = read(fd_in, buff, MAX_BUFFER_SIZE)) > 0) && (rtnVal == TRUE))

2. 16MB缓冲区触发段错误的问题

这是栈空间不足导致的:
你当前的缓冲区是函数内定义的局部数组char buff[MAX_BUFFER_SIZE],局部变量分配在进程栈空间,Cygwin默认栈大小仅为8MB左右,定义超过栈上限的局部数组会直接栈溢出触发段错误。

修正方案二选一即可:

  • 把buff的定义移到函数外,作为全局变量,全局变量分配在数据段,不受栈大小限制
  • 改用malloc动态分配缓冲区,使用完毕后释放,示例如下:
// 替换char buff[MAX_BUFFER_SIZE]
char *buff = malloc(MAX_BUFFER_SIZE);
if (buff == NULL) {
    // 内存分配失败处理
    fprintf(stderr, "malloc buffer failed: %s\n", strerror(errno));
    rtnVal = FALSE;
}
// 函数退出前释放
free(buff);

修正后完整可运行代码

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

#define BOOL char
#define TRUE (1 < 2)
#define FALSE (1 > 2)
#define MAX_BUFFER_SIZE 15*1024*1024 // 15MB,符合你的性能要求

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 = -1, fd_out = -1;
    char *buff = NULL, *out_ptr ;
    ssize_t nRead, nRemaining, nWritten, totWritten = 0 ;
    int save_errno ;
    struct stat st ;

    // 动态分配15MB缓冲区
    buff = malloc(MAX_BUFFER_SIZE);
    if (buff == NULL) {
        fprintf(stderr, "Failed to alloc %d buffer: %s\n", MAX_BUFFER_SIZE, strerror(errno));
        return FALSE;
    }

    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)) ;
            rtnVal = FALSE;
            goto cleanup;
        }
        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)) {
            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) {
                    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

cleanup:
    save_errno = errno ;
    if (fd_in >= 0)  close(fd_in) ;
    if (fd_out >= 0) close(fd_out) ;
    if (buff != NULL) free(buff);

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

修正后重新编译运行,read就会返回实际读取的字节数,15MB缓冲区也不会触发段错误,拷贝性能符合要求。


内容的提问来源于stack exchange,提问作者Dennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:15:02