程序在尝试使用 read() 系统调用读取文件时卡住
Program gets stuck while trying to read a file using read() system call
这是我的代码片段:
int fd;
bufsize = 30;
char buf[bufsize];
char cmd[100] = "file.txt";
int newfd = 1;
if (fd = open(cmd,O_RDONLY) >=0){
puts("wanna read");
while (read(fd,&bin_buf,bufsize)==1){
puts("reading");
write(newfd,&bin_buf,bufsize);
}
close(fd);
}
所以这里程序打印 "wanna read"
但从不打印 "reading"
。我也试过使用非阻塞标志打开,但没有用。有谁能够帮助我?我必须只使用 open()
和 read()
系统调用。谢谢。
编辑:我在代码中做了一些澄清。实际上,我正在写入的 newfd 是一个套接字描述符,但我认为这对这个问题并不重要,因为它停留在 write
.[=17= 之前的 read
上]
read
returns 从文件读取的字节数可以是 bufsize
或更少,如果必须读取的文件的剩余部分短于 bufsize
.
在您的情况下,很可能 bufsize
大于 1 并且文件大于 1 字节,因此 while 循环的条件被评估为 false,代码被跳到文件关闭的位置。
你应该检查是否有更多字节要读取:
while( read(fd,&bin_buf,bufsize) > 0 ) {
第一个问题是你的if
语句。您忘记使用足够的括号,所以如果 open()
有效,则读取会尝试从文件描述符 1 读取,也就是标准 output。如果那是你在 Unix 机器上的终端(可能是),那么它就可以工作——尽管这可能令人惊讶;该程序正在等待您输入内容。
修复:使用括号!
if ((fd = open(cmd, O_RDONLY)) >= 0)
赋值是在比较之前而不是之后完成的。
我顺便观察到你没有显示你是如何设置 cmd
的,但是如果你看到 'wanna read' 消息,那一定没问题。您没有显示 newfd
是如何初始化的;也许那也是 1
。
您也遇到了 'what the read()
call returns' 的问题。您可能需要:
int fd;
char buf[bufsize];
int newfd = 1;
if ((fd = open(cmd, O_RDONLY)) >= 0)
{
puts("wanna read");
int nbytes; // ssize_t if you prefer
while ((nbytes = read(fd, buf, sizeof(buf))) > 0)
{
puts("reading");
write(newfd, buf, nbytes);
}
close(fd);
}
你可以用你原来的if
但我的循环体输入一些东西('Surprise',或'Terminal file descriptors are often readable and writable'或其他东西)然后写在某个地方来证明我的主要观察。
您的 read()
调用尝试读取 bufsize
字节和 returns 实际读取的字节数。除非 bufsize ==
,read()
不太可能 return 1
,因此该块几乎总是被跳过,什么也不会写入。
还要注意 if (fd = open(cmd, O_RDONLY) >= 0)
是不正确的,如果文件存在,会将 fd
设置为 1
,标准输出的句柄,导致 read
失败因为标准输入很可能没有打开阅读。
请注意,使用 read
系统调用进行读取在某些环境下会很棘手,因为 return 值 -1
可能会重新启动。
这是一个改进的版本:
int catenate_file(const char *cmd, int newfd, size_t bufsize) {
int fd;
char buf[bufsize];
if ((fd = open(cmd, O_RDONLY)) >= 0) {
puts("wanna read");
ssize_t nc;
while ((nc = read(fd, buf, bufsize)) != 0) {
if (nc < 0) {
if (errno == EINTR)
continue;
else
break;
}
printf("read %zd bytes\n", nc);
write(newfd, buf, nc);
}
close(fd);
return 0;
}
return -1;
}
这是我的代码片段:
int fd;
bufsize = 30;
char buf[bufsize];
char cmd[100] = "file.txt";
int newfd = 1;
if (fd = open(cmd,O_RDONLY) >=0){
puts("wanna read");
while (read(fd,&bin_buf,bufsize)==1){
puts("reading");
write(newfd,&bin_buf,bufsize);
}
close(fd);
}
所以这里程序打印 "wanna read"
但从不打印 "reading"
。我也试过使用非阻塞标志打开,但没有用。有谁能够帮助我?我必须只使用 open()
和 read()
系统调用。谢谢。
编辑:我在代码中做了一些澄清。实际上,我正在写入的 newfd 是一个套接字描述符,但我认为这对这个问题并不重要,因为它停留在 write
.[=17= 之前的 read
上]
read
returns 从文件读取的字节数可以是 bufsize
或更少,如果必须读取的文件的剩余部分短于 bufsize
.
在您的情况下,很可能 bufsize
大于 1 并且文件大于 1 字节,因此 while 循环的条件被评估为 false,代码被跳到文件关闭的位置。
你应该检查是否有更多字节要读取:
while( read(fd,&bin_buf,bufsize) > 0 ) {
第一个问题是你的if
语句。您忘记使用足够的括号,所以如果 open()
有效,则读取会尝试从文件描述符 1 读取,也就是标准 output。如果那是你在 Unix 机器上的终端(可能是),那么它就可以工作——尽管这可能令人惊讶;该程序正在等待您输入内容。
修复:使用括号!
if ((fd = open(cmd, O_RDONLY)) >= 0)
赋值是在比较之前而不是之后完成的。
我顺便观察到你没有显示你是如何设置 cmd
的,但是如果你看到 'wanna read' 消息,那一定没问题。您没有显示 newfd
是如何初始化的;也许那也是 1
。
您也遇到了 'what the read()
call returns' 的问题。您可能需要:
int fd;
char buf[bufsize];
int newfd = 1;
if ((fd = open(cmd, O_RDONLY)) >= 0)
{
puts("wanna read");
int nbytes; // ssize_t if you prefer
while ((nbytes = read(fd, buf, sizeof(buf))) > 0)
{
puts("reading");
write(newfd, buf, nbytes);
}
close(fd);
}
你可以用你原来的if
但我的循环体输入一些东西('Surprise',或'Terminal file descriptors are often readable and writable'或其他东西)然后写在某个地方来证明我的主要观察。
您的 read()
调用尝试读取 bufsize
字节和 returns 实际读取的字节数。除非 bufsize ==
,read()
不太可能 return 1
,因此该块几乎总是被跳过,什么也不会写入。
还要注意 if (fd = open(cmd, O_RDONLY) >= 0)
是不正确的,如果文件存在,会将 fd
设置为 1
,标准输出的句柄,导致 read
失败因为标准输入很可能没有打开阅读。
请注意,使用 read
系统调用进行读取在某些环境下会很棘手,因为 return 值 -1
可能会重新启动。
这是一个改进的版本:
int catenate_file(const char *cmd, int newfd, size_t bufsize) {
int fd;
char buf[bufsize];
if ((fd = open(cmd, O_RDONLY)) >= 0) {
puts("wanna read");
ssize_t nc;
while ((nc = read(fd, buf, bufsize)) != 0) {
if (nc < 0) {
if (errno == EINTR)
continue;
else
break;
}
printf("read %zd bytes\n", nc);
write(newfd, buf, nc);
}
close(fd);
return 0;
}
return -1;
}