您现在的位置是:首页 >技术教程 >网络编程 lesson4 linux下的IO模型和特点网站首页技术教程
网络编程 lesson4 linux下的IO模型和特点
简介网络编程 lesson4 linux下的IO模型和特点
目录
在Linux中,有几种常见的I/O模型,它们决定了应用程序如何进行输入和输出操作。
阻塞式IO
工作流程
在阻塞I/O模型中,当应用程序发起I/O操作时,它会一直阻塞(即暂停执行),直到操作完成并返回结果。这意味着应用程序无法执行其他任务,直到I/O操作完成。阻塞I/O模型对于简单的应用程序来说是最简单的模型,但在处理多个并发连接时可能会导致性能问题。
特点:最简单,最常用;效率低
常见的阻塞IO有:
read,recv,recvfrom
write,send(注意sendto没有阻塞)
accept,connect
非阻塞式IO
工作流程
非阻塞I/O模型允许应用程序在发起I/O操作后立即返回,而不需要等待操作完成。如果操作不能立即完成,应用程序可以执行其他任务而不被阻塞。通过轮询来检查操作是否完成,可以实现非阻塞I/O。这种模型需要应用程序不断地查询I/O状态,可能会导致CPU资源浪费。
特点:无需等待,可处理多路IO;需要轮询,浪费cpu资源
设置非阻塞IO方法
1.通过函数自带的参数进行设置
例如:recv函数中可以通过MSG_DONTWAIT进行设置
2.通过设置文件描述符设置非阻塞(fcntl函数)
int fcntl(int fd, int cmd, ... );
功能:设置文件描述符属性
参数:
fd:文件描述符
cmd:设置方式 - 功能选择
F_GETFL 获取文件描述符的状态信息 第三个参数化忽略
F_SETFL 设置文件描述符的状态信息 通过第三个参数设置
O_NONBLOCK 非阻塞
O_ASYNC 异步
O_SYNC 同步
arg:设置的值 in
返回值:
特殊选择返回特殊值 - F_GETFL 返回的状态值(int)
其他:成功0 失败-1,更新errno
使用:0为例
0-原本:阻塞、读权限 修改或添加非阻塞
int flags=fcntl(0,F_GETFL);//1.获取文件描述符原有的属性信息
flags = flags | O_NONBLOCK;//2.修改添加权限
fcntl(0,F_SETFL,flags); //3.将修改好的权限设置回去
fcntl实例
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#define N 128
int main(int argc, char const *argv[])
{
char buf[N];
//注意fcntl得函数顺序
int Jurisdiction = fcntl(0, F_GETFL); //将0得权限拿出
Jurisdiction=0|O_NONBLOCK; //添加上非阻塞权限
fcntl(0, F_SETFL, Jurisdiction); //将修改后得权限设置回去
while (1)
{
fgets(buf, N, stdin);
printf("%s",buf);
sleep(1);
if (strncmp("quite", buf, 5) == 0)
{
break;
}
}
return 0;
}
信号驱动IO
工作流程
信号驱动I/O模型通过向应用程序发送信号来通知它I/O操作的完成。应用程序在发起I/O操作后可以继续执行其他任务,而当操作完成时,操作系统会发送一个信号给应用程序。应用程序需要注册信号处理程序来处理相应的信号。这种模型通常用于处理低延迟的I/O操作。
- 通过信号方式,当内核检测到设备数据后,会主动给应用发送信号SIGIO。
- 应用程序收到信号后做异步处理即可。
- 应用程序需要把自己的进程号告诉内核,并打开异步通知机制。
特点:异步通知模式,需要底层驱动的支持
也是通过fcntl实现
//将APP进程号告诉驱动程序
fcntl(fd, F_SETOWN, getpid());
//使能异步通知
int flag;
flag = fcntl(fd, F_GETFL);
flag |= O_ASYNC; //也可以用FASYNC标志
fcntl(fd, F_SETFL, flag);
signal(SIGIO, handler);
实例:在LINUX下检听自己鼠标的动作
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int fd;
void handler(int sig)
{
char buf[32];
int ret = read(fd, buf, sizeof(buf));
buf[ret] = '