我正在尝试编写具有阻塞文件描述符的最短代码。
我先设置:O_NONBLOCK
第二个:ICANON,[VMIN],[VTIME] 作为我的文件描述符...
我还需要设置哪些选项才能拥有阻塞文件描述符?
(sample.txt 是空的 & 不同模式的 open() 不会发生任何事情)
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
void set_blocking(int fd, int blocking) {
int flags = fcntl(fd, F_GETFL, 0);
if (blocking)
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
return;
}
int main(){
int fd;
char buff[100];
struct termios options;
options.c_lflag &= ~ICANON;
options.c_cc[VMIN] = 2;
options.c_cc[VTIME] = 0;
fd = open("sample.txt",O_RDWR);
tcsetattr(fd, TCSANOW, &options);
set_blocking(fd,1);
read(fd,buff,2);
printf("%s\n",buff);
return 0;
}
最佳答案
您的代码仅修改了未初始化的 struct termios options
变量的一部分。当您的代码调用 tcsetattr
时,大部分 options
变量将被设置为随机位,因此 tcsetattr
可能返回错误或应用终端的虚假设置。
由于您的代码仅显式修改某些终端设置,因此初始化 options
变量的最佳方法是调用 tcgetattr
将旧设置读入其中:
ret = tcgetattr(fd, &options);
if (ret < 0) {
perror("tcgetattr");
exit(1);
}
options.c_lflag &= ~ICANON;
options.c_cc[VMIN] = 2;
options.c_cc[VTIME] = 0;
ret = tcsetattr(fd, TCSANOW, &options);
if (ret < 0) {
perror("tcsetattr");
exit(1);
}
上面的代码示例假定文件描述符fd
链接到终端,因此isatty(fd)
返回1。当fd
链接到一个普通文件。
在您发布的代码中,fd
链接到当前目录中名为“sample.txt”的文件,该文件不太可能是终端。在这种情况下,tcgetattr
和 tcsetattr
调用将返回 -1
并将 errno
设置为 ENOTTY
.
关于无法将文件描述符设置为阻塞模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58118569/