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) {
我正在开发一个进程,其中包括复制文件。我 运行 遇到一个问题,即读取功能无法按预期工作。
我的研究和之前的经验告诉我,(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) {