LINUX I/O复用
标准流功能
- stdin 0 标准输入
- stdout 1 标准输出
- stderr 2 标准错误
write()
在linux中所有的 输入输出 都可以由write 来实现,硬盘读取,网络读取,文件读取都可以
write(目的,源,lemgth)
write(stdout,buf,sizeof(buf)); //和printf效果一样在屏幕输出
文件流指针
fopen() 只可以打开普通的文件
- int setvbuf(FILE stream, char buf, int type, unsigned size); 设置流缓冲区
- stream为文件流指针
- buf为缓冲区首地址
- type为缓冲区类型
- _IOFBF (满缓冲):当缓冲区为空时,从流读入数据。或当缓冲区满时,向流写入数据。
- _IOLBF (行缓冲):每次从流中读入一行数据或向流中写入—行数据。
- _IONBF (无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区
- size为缓冲区内字节的数量
- 返回值 成功为0 失败非0
setvbuf(fp,NULL,_IONBF,0);
FILE 结构体
- _IO_buf_base 读取到的位置
- _IO_read_ptr 源文件缓冲区启示位置
- _IO_buf_end 源文件缓冲区结束位置
缓冲区
全缓冲区 BUFSIZE 默认开启
- 缓冲区刷新函数:fflush(stdout);
行缓冲区
预见换行符才进行刷新- scanf() 行缓冲区 以 \n 判断是否结束
- gets() 行缓冲区 以 \n 判断是否结束
无缓冲区
- write(0,buf); 无缓冲区
- read(0,buf,size) 以EOF 判断是否结束
- puts(0); 在输出内容后面自动加 \0
- strerr()
fputs("enter any charcter",stdout);//标准输出打印内容
- 指定缓冲区
void setbuf(FILE_ stream,char_buf)
- buf 参数必须指向一个长度为BUFSIZE的缓冲区 如果为空 就为空缓冲区
void setbuffer(FILE_ stream,char_buf,size_t size)
- size : 指定缓冲区长度
void setlinebuf(FILE* stream)
- 系统自动指定 缓存长度
文件读写函数
都以\n为结尾
fgetc
getc
gets
puts
read
write
文件流定位
int fseek(FILE *stream, long offset, int fromwhere); 修改当前文件流指针
fromwhere: 起始点
- SEEK_SET 0 文件开头
- SEEK_CUR 1 文件当前位置
- SEEK_END 2 文件末尾
ftell(FILE *srteam) 返回当前文件指针位置
rewind(FILE *srteam) 把文件指针移回开头
SOCKET 的IO模型
- 非阻塞IO处理
- 阻塞IO处理
- IO复用
- 信号驱动
- 异步IO
非阻塞IO处理
- 缺点:轮询次数高,不知数据拷贝的量
IO复用
- 监听一个文件夹中的多个文件夹
- 当文件夹中有任何一个文件可以返回就会返回,或者 超时
- 内核层:
fcntl() 设置socket为非阻塞IO
int fcntl(int fd, int cmd, long arg);
头文件 #include
fd:文件描述符
cmd: 操作命令
arg: 供命令使用的参数
返回值 失败 -1
cmd:
一. F_DUPFD :复制文件描述词 。
二. FD_CLOEXEC :设置close-on-exec标志。如果FD_CLOEXEC位是0,执行execve的过程中,文件保持打开。反之则关闭。
三. F_GETFD :读取文件描述词标志。
四. F_GETFL :读取文件状态标志。
五. F_SETFL :设置文件状态标志
F_SETFL
- O_NONBLOCK 非阻塞I/O
- O_APPEND 强制每次写(write)操作都添加在文件大的末尾
- O_ASYNC 当I/O可用的时候,允许SIGIO信号发送到进程组
知识连接:
https://www.cnblogs.com/xuyh/p/3273082.html
https://blog.csdn.net/bailyzheng/article/details/7463775
设置非阻塞IO
int sock = socket(AF_INET,SOCK_STREAM,0);
fcntl(sock,F_SETFL,O_NONBLOCK);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 设置此次 recv为非阻塞
recv(sock,buf,bufsize,MSG_DONTWAIT);
select IO复用手段
fd_set 文件集合结构体
1.分配 select
定义 fd_set 结构体
2. 设置
初始化: FD_ZERO(&rfds);
加入句柄:FD_SET(fd,&rfds);
移除句柄:FD_CLR(fd,fd_set* set)
3. 使用
int select(int nfds, fd_set _readfds, fd_set _writefds,
fd_set _exceptfds, struct timeval _timeout);
- 头文件 #include
- nfds :文件集合中最大fd+1
- readfds:可以使用单个,读写错误要对应,没有写NULL
- timeout:超时时间
- 返回值:错误 -1 超时0 成功 可连接数
struct timeval 结构体
struct timeval
{
long tv_sec; //秒
long tv_usec; //微秒
};
FD_ISSET() 判断由哪一个fd引发的返回
int FD_ISSET(int fd, fd_set *set);