标签:终端 mask pre read amp `` fcntl out 读取
头文件 -> unistd.h, fcntl.h, stdio.h, errno.h
read(fd, buf, sizeof(buf))
write(fd, buf, ret) // ret是read函数返回的字节数, 0表示达到了文件末尾, -1是异常
close(fd)
示例(这里忽略里错误处理)
int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
int ret = 0;
char buf[1024];
char *msg = "try again...";
while (ret = read(fd, buf, sizeof(buf))) {
if (-1 == ret) {
// 注意
if (errno != EAGAIN) {
// STDOUT_FILENO 是数字1, STDIN_FILENO 是数字0
perror("error");
exit(1);
}
write(STDOUT_FILENO, msg, strlen(msg));
sleep(1);
continue;
}
write(STDOUT_FILENO, buf, ret);
}
在上例中, 如果终端没有数据, 则read函数返回-1, 但是这并不代表着read错误了, 如果没有数据, Linux会将errno这是为EAGAIN, 如果errno不是EAGAIN, 则读取错误
在执行一个程序的时候, 默认会PCB指向的数组指针中会在0, 1, 2下标对应的位置创建file struct, 代表着stdin, stdout, stderr, 所以我们使用终端的时候, 终端已经被打开了, 在上面的程序中, 我们要向实现非阻塞的功能, 需要打开一个已经打开的文件, 这个是不必要的, Linux提供了fcntl函数用于修改已经打开的文件的属性
示例
```c
// F_GETFL是Get File Flag, 获取文件属性, 文件属性就是一个int类型, 采用bitmap的方式实现保存多个属性
int ret = 0;
int flag = fcntl(STDOUT_FILENO, F_GETFL);
// 将对应的位置1, 也许O_NONBLOCK是000000000000000000001000000
// |即使加法, 在fnctl内部判断flag是否有O_NONBLOCK属性, 是通过flag & O_NONBLOCK, 如果返回的是1则表示有O_NONBLOCK属性, 0则表示没有
flag |= O_NONBLOCK;
char buf[1024];
char *msg = "try again...";
while (ret = read(STDOUT_FILENO, buf, sizeof(buf))) {
if (-1 == ret) {
// 注意
if (errno != EAGAIN) {
// STDOUT_FILENO 是数字1, STDIN_FILENO 是数字0
perror("error");
exit(1);
}
write(STDOUT_FILENO, msg, strlen(msg));
continue;
}
write(STDOUT_FILENO, buf, ret);
}
```
移动文件指针(lseek)
示例
```c
int fd = open("./test.txt", O_RDONLY | O_CREAT, 0644);
// 文件大小
int offset = lseek(fd, 0, SEEK_END);
// 追加数据
write(...);
close(fd);
```
int main(int argc, char *argv[]) {
char buf[1024] = {‘\0‘};
int ret = 0;
if (argc < 3) {
printf("Too Few Parameters\n");
return 1;
}
int fd_src = open(argv[1], O_RDONLY);
int fd_dst = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666);
while ((ret = read(fd_src, buf, sizeof(buf)))) {
write(fd_dst, buf, ret);
}
close(fd_src);
close(fd_dst);
return 0;
}
标签:终端 mask pre read amp `` fcntl out 读取
原文地址:https://www.cnblogs.com/megachen/p/10184395.html