read函数
ssize_t read(int fildes, void *buf, size_t nbyte);
返回值:
> 0: 实际读到的字节数
= 0: 读完数据(读文件, 管道, socket末尾-->对端关闭, 对端未关闭会一直等待)
-1: 异常:
errno == EINTR被信号中断, 重启或者退出
errno == EAGAIN或者EWOULDBLOCK以非阻塞方式读, 并且没有数据
其他值: 出现错误perror eixt
ssize_t write(int fildes, const void *buf, size_t nbyte);
返回值: 返回实际写出的字节数, 0表示什么也没有写
阻塞读终端
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// 阻塞读终端
int main(int argc, char const *argv[])
{
char buf[10];
int n;
n = read(STDIN_FILENO, buf, 10);
if (n < 0) {
perror("read STDIN_FILENO");
exit(1);
}
write(STDOUT_FILENO, buf, n);
return 0;
}
非阻塞读终端
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MSG_TRY "try again\n"
// 非阻塞读终端
int main(int argc, char const *argv[])
{
char buf[10];
int fd, n;
// /dev/tty --> 当前打开的终端设备
fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
if (fd < 0) {
perror("open /dev/tty");
exit(1);
}
tryagain:
n = read(fd, buf, 10);
if (n < 0) {
// 如果write为非阻塞, 但是没有数据可读, 此时全局变量errno被设置为EAGAIN
if (errno == EAGAIN) {
sleep(3);
write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
goto tryagain;
}
perror("read /dev/tty");
exit(1);
}
write(STDOUT_FILENO, buf, n);
close(fd);
return 0;
}
阻塞和非阻塞是文件的属性
默认非阻塞: 普通文件
默认阻塞: 终端设备, 管道, 套接字