首页 > 其他分享 >网编(liunx下的io)

网编(liunx下的io)

时间:2024-11-28 12:29:19浏览次数:11  
标签:IO 网编 int flag 阻塞 描述符 fd liunx io

1.  Linux下的IO模型

阻塞式IO、非阻塞式IO、异步通信IO、IO多路复用

1.1阻塞式IO

特点:最简单、最常用,效率低

阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。
缺省情况下(及系统默认状态),套接字建立后所处于的模式就是阻塞I/O 模式。
学习的读写函数在调用过程中会发生阻塞。相关函数如下:
•读操作中的read、recv、recvfrom
 读阻塞--》需要读缓冲区中有数据可读,读阻塞解除
•写操作中的write、send
写阻塞--》阻塞情况比较少,主要发生在写入的缓冲区的大小小于要写入的数据量的情况下,写操作不进行任何拷贝工作,将发生阻塞,一旦缓冲区有足够的空间,内核将唤醒进程,将数据从用户缓冲区拷贝到相应的发送数据缓冲区。 
注意:sendto没有写阻塞

1.2非阻塞式IO

特点:可以处理多路IO;需要轮询,浪费CPU资源

设置非阻塞:

1)通过函数参数设置

recv函数最后一个参数写0为阻塞,写MSG_DONTWAIT为非阻塞

2)通过fcntl函数设置文件描述符属性

int fcntl(int fd, int cmd, ... /* arg */ );
功能:获取/设置文件描述符属性    状态属性(O_RDONLY  O_NONBLOCK非阻塞)
参数:fd:文件描述符
      cmd:功能选择   
          状态属性: 
                  F_GETFL  :获取文件描述符原来的属性
                  F_SETFL  :设置文件描述符属性
    arg:根据cmd决定是否填充值   int
返回值:
     失败:-1
     成功:F_GETFL - 返回值的文件描述符号属性的值 int
           F_SETFL   0   

标准模板:

操作顺序:先读,后改,再写

int flag = fcntl(fd,F_GETFL);//原来属性值
flag |= O_NONBLOCK; //修改属性值,增加非阻塞属性
fcntl(fd,F_SETFL,flag);//将新的属性值写入文件描述符中

设置标准输入为非阻塞:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    int flag = fcntl(0, F_GETFL); // 原来属性值
    flag |= O_NONBLOCK;            // 修改属性值,增加非阻塞属性
    //flag &= ~ O_NONBLOCK;
    fcntl(0, F_SETFL, flag);      // 将新的属性值写入文件描述符中

    char buf[32]="hello";
    while(1)
    {
        fgets(buf,sizeof(buf),stdin);
        printf("buf:%s\n",buf);
    }
    
    return 0;
}

1.3信号驱动IO(异步IO)

特点:异步通知模式,需要底层驱动的支持

//将APP进程号告诉驱动程序
fcntl(fd, F_SETOWN, getpid());

//使能异步通知
int flag;
flag = fcntl(fd,F_GETFL);
flag|= O_ASYNC ;
fcntl(fd,F_SETFL,flag);

signal(SIGIO,handler)

sudo cat /dev/input/mouse0 :查看鼠标文件

用非阻塞方式监听鼠标的数据(鼠标操作需要加sudo)

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
int fd;
void handler(int num)//信号处理函数
{
    char buf[32];
    int ret = read(fd, buf, sizeof(buf) - 1);
    buf[ret] = '\0';
    printf("buf:%s\n", buf);
}
int main(int argc, char const *argv[])
{
    // 1.打开鼠标文件
    fd = open("/dev/input/mouse1", O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    // 2.将进程号告诉驱动程序
    fcntl(fd, F_SETOWN, getpid());

    // 3.开启异步IO通知
    int flag;
    flag = fcntl(fd, F_GETFL);
    flag |= O_ASYNC;
    fcntl(fd, F_SETFL, flag);

    // 4.收到信号,会调用函数
    signal(SIGIO, handler);

    char buf[64] = {};
    while (1)
    {
        scanf("%s", buf);
        printf("buf:%s\n", buf);
    }

    return 0;
}

前三种使用场景假设总结:

假设妈妈有一个孩子,孩子在房间里睡觉,妈妈需要及时获知孩子是否醒了,如何做?

1.  进到房间陪着孩子一起睡觉,孩子醒了会吵醒妈妈:不累,但是不能干别的了

2.  时不时进房间看一下:简单,空闲时间还能干点别的,但是很累

3.  妈妈在客厅干活,小孩醒了他会自己走出房门告诉妈妈:互不耽误

1.4IO多路复用

IO多路复用场景假设

假设妈妈有三个孩子,分别不同的房间里睡觉,需要及时获知每个孩子是否醒了,如何做?

1.不停进每个房间看一下:简单,空闲时间还能干点别的,但是很累

2.  把三个房间的门都打开,在客厅睡觉,同时监听所有房间的哭声,如果被哭声吵醒,那么能准确定位某个房间,及时处理即可:既能得到休息,也能及时获知每个孩子的状态

IO多路复用机制

其基本思想是:

¡先构造一张有关描述符的表(最大1024),然后调用一个函数。

¡当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。

¡函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。

基本流程:
1. 先构造一张有关文件描述符的表(集合、数组); ----》创建三个房间
2.将你关心的文件描述符加入到这个表中;        -----》将孩子放入房间
3.然后调用一个函数。 select / poll         -----》在客厅躺着
4.当这些文件描述符中的一个或多个已准备好进行I/O操作的时候
该函数才返回(阻塞)。                          ------》孩子哭了
5. 判断是哪一个或哪些文件描述符产生了事件(IO操作);  ---》哪个孩子哭了
6. 做对应的逻辑处理;                        ------》哄孩子

实现IO多路复用的方式

1.select实现

int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
   功能:select用于监测是哪个或哪些文件描述符产生事件;
   参数:nfds:    监测的最大文件描述个数
        (这里是个数,使用的时候注意,与文件中最后一次打开的文件
          描述符所对应的值的关系是什么?)
    readfds:  读事件集合; //读(用的多)
     writefds: 写事件集合;  //NULL表示不关心
     exceptfds:异常事件集合;  
     timeout:超时检测 
       如果不做超时检测:传 NULL 
       如果设置了超时检测时间:&tv
  返回值:
         <0 出错
        >0 表示有事件产生;
        ==0 表示超时时间已到;
  struct timeval {
               long    tv_sec;         /* seconds */
               long    tv_usec;        /* microseconds */
           };
           
 void FD_CLR(int fd, fd_set *set);//将fd从表中清除
 int  FD_ISSET(int fd, fd_set *set);//判断fd是否在表中
 void FD_SET(int fd, fd_set *set);//将fd添加到表中
 void FD_ZERO(fd_set *set);//清空表

特点:

select实现io多路复用的特点:

1.  一个进程最多只能监听1024个文件描述符 (千级别)FD_SETFILE

2.  select被唤醒之后需要重新轮询一遍驱动的poll函数,效率比较低(消耗CPU资源);

3.  select每次会清空表,每次都需要拷贝用户空间的表到内核空间,效率低

标签:IO,网编,int,flag,阻塞,描述符,fd,liunx,io
From: https://blog.csdn.net/luoqing418/article/details/144108077

相关文章

  • C++练级计划-> 《IO流》iostream fstream sstream详解
    如果是想全部过一遍就看完,如果想具体的了解某一个请点目录。因为有三种流的使用可能内容多 目录流是什么?C++IO流(iostream)io流的注意事项cin和cout为什么能直接识别出类型和数据fstreamfstream的使用方法: 1.以二进制打开文件并写入和读取2.以文本打开文件并读取或写......
  • iOS系统资源调度机制解析
    在开发高性能iOS应用时,深入了解并合理利用iOS系统的资源调度机制至关重要。资源调度涉及到线程的创建与管理、任务的分配与执行、以及进程优先级的调整等多个方面。本文将重点介绍iOS系统中的核心资源调度机制——GrandCentralDispatch(GCD),并深入探讨其在多线程管理和性能优化中......
  • 记录Vue Antd 表格RowSelection刷新列表后缓存问题
    起因 原来的代码//tsx部分<BaseTableoptions={tableData.options}columns={tableData.columns}data={tableData.data}/>constselectKeys=ref<string[]>([])//表格配置consthandleRowSelection={......
  • 深度学习笔记——DiT(Diffusion Transformer)
    本文详细介绍Transformer架构图像生成方面的应用,将Diffusion和Transformer结合起来的模型:DiT。目前DiT已经成为了AIGC时代的新宠儿,视频和图像生成不可缺少的一部分。文章目录论文定义架构与传统(U-Net)扩散模型区别架构噪声调度策略与传统扩散的相同输入图像/条件......
  • ABAP 关于INNER JION需要注意的一点
    INNERJOIN多取值的情况,举例如下比如A表一条数据FIELD1FIELD2A1A2 B表多条数据(假设三条)FIELDB1FIELD1FIELDB3B1A1B2B3A1B4B5B6B7 如果用AINNERJIONBATFIELD2WHEREFIELD2='A1',跑出来的结果将是两条数据FIELDB1FIELD1FIE......
  • STM32——GPIO
    目录一、基础知识      (一)基本特性                        数字和模拟信号                        IO端口基本结构      (二)引脚配置       多路复用——基于stm32f103       引......
  • (即插即用模块-Attention部分) 二十一、(2021) Polarized Self-Attention 极化自注意
    文章目录1、PolarizedSelf-Attention2、代码实现paper:PolarizedSelf-Attention:TowardsHigh-qualityPixel-wiseRegressionCode:https://github.com/DeLightCMU/PSA1、PolarizedSelf-Attention像素级回归是细粒度计算机视觉任务中的常见问题。回归问题往......
  • stopPropagation()和preventDefault()这两个方法有什么区别?
    stopPropagation()和preventDefault()是JavaScript中用于事件处理的两个重要方法,它们的主要区别在于它们针对事件的不同方面:stopPropagation()阻止事件冒泡:当一个元素上的事件被触发时,例如点击一个按钮,该事件会沿着DOM树向上冒泡,触发其父元素、祖先元素上的相同事件......
  • 使用rclone将Oss文件转存Minio
    解压unziprclone-v1.65.2-linux-amd64.zip添加可执行权限chmod+xrclone将可执行的rclone移动到系统的可执行路径中sudomvrclone/usr/local/bin/创建配置文件,配置文件需在指定位置vim/root/.config/rclone/rclone.conf修改成自己的bucket名称,执行同步命令–progre......
  • AlphaProof IMO 2024 P1 in LEAN 之 induction 策略(Tactic)
        在AlphaProof使用intro策略后,此时的目的(Goal)为:    这时,AlphaProof使用induction策略,对 n:ℕ进行,归纳证明:    induction策略,在假设中,增加了,在归纳证明中使用的,前值假设,即:    改写后的目的(Goal)的高亮部分,a:∀m<n,......