Linux下的五种I/O模型

I/O模型 1 概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 IO 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。针对linux操作系 阅读详情
一、五种I/O模型

1、阻塞I/O模型
应用程序调用一个I/O函数,导致应用程序阻塞,等待数据,如果数据没有准备好,则一直阻塞,直到数据准备好,将数据从内核空间拷贝到用户空间,I/O函数成功返回。
2、非阻塞I/O模型
将套接口设置为非阻塞形式就是告诉内核,当所请求的I/O函数还没有准备好时,直接返回错误,而不让进程进入睡眠状态,此后,I/O函数不断地测试数据有没有准备好,如果数据没有准备好,则不断进行测试,直到数据准备好为止。在测试期间会浪费CPU的资源。
3、I/O复用模型
I/O复用模型会用到select函数、poll函数或者poll函数。该模型也会阻塞等待I/O函数,但是与阻塞I/O模型不同的是,该模型可以同时阻塞多个I/O,并且可以同时对多个读操作和写操作的I/O函数进行检测,直到有数据可读或者可写时,才真正调用I/O函数。
4、信号驱动模型
首先允许套接口进行信号驱动I/O,并安装一个信号处理函数,进行继续运行并不阻塞,当数据准备好时,进程会收到一个SIGIO信号,可以信号处理函数中调用I/O操作函数处理数据。
5、异步I/O模型
调用aio_read函数,告诉内核描述字,缓冲区指针,缓冲区大小,文件偏移以及通知的方式,然后立即返回,直到数据准备好之后,再通知应用程序。

二、同步I/O与异步I/O

1、同步
所谓同步就是调用者发出一个调用,在该调用返回之前,调用者一直进行等待,直到调用成功为止,调用者返回并带返回值。
2、异步
调用者发出一个调用请求,然后直接返回,此次返回没有返回值,然后被调用者通过状态来通知调用者,或者通过回掉函数来处理这个调用。

三、阻塞与非阻塞

阻塞与非阻塞指的是应用程序在等待调用结果时的状态
1、阻塞等待
在调用结果返回之前线程会挂起,直到得到调用结果之后才会返回。
2、非阻塞等待
在调用结果返回之前不会一直等待,也就是应用程序不会阻塞当前线程。
目前的阻塞和非阻塞是针对同步机制来说的。

四、高级I/O

非阻塞I/O、记录锁、系统V流机制、I/O多路转接、readv函数和writev函数、存储映射I/O都属于高级I/O。

五、I/O多路转接

什么叫多路转接?
对于多个非阻塞的I/O,如何知道该I/O是否已经准备好读数据或者写数据?
方法一:采用read函数和write函数进行轮询式的检测,知道有数据准备好被读写为止,但是这种方法十分浪费CPU的资源;
方法二:采用I/O多路转接(I/O复用技术):先构造一张列表,该列表中存储的是文件描述符。然后调用一个函数(select/poll/epoll)进行等待,当文件描述符列表中的一个或者多个文件描述符准备好之后,该函数就进行返回,函数返回时告诉当前进程哪些文件描述符已经准备好了。

六、I/O多路转接之select函数

1、函数原型
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);

2、需要包含的头文件:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
3、参数类型说明:
fd_set:表示文件描述符集合
struct timeval:是一个用于描述监视时间的结构体,如果在规定的时间之内,需要检测的文件描述符没有事件发生,则返回0值。
该结构体如下所示:
这里写图片描述
4、参数说明:
nfds:需要监视的最大文件描述符值加一
readfds:需要检测的可读文件描述符集合
writefds:需要检测的可写文件描述符集合
exceptfds:需要检测的异常文件描述符集合
timeout:函数的等待时间
5、用四种宏处理三种描述词组
(1)FD_CLR(int fd,fd_set* set);用来清除描述词组set中相关fd 的位。
(2)FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真。
(3)FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位 。
(4)FD_ZERO(fd_set *set);用来清除描述词组set的全部位 。
6、参数timeout的取值
(1)NULL:表示让函数select一直进行阻塞,直到某个文件描述符上的事件就绪。
(2)0:表示不等待文件描述符上的事件是否就绪,直接返回。
(3)取某一特定值x:表示在x时间内若还没有文件描述符上的事件就绪,则超时返回。
7、函数的返回值
(1)执行成功:则返回已经就绪的文件描述符的个数。
(2)返回0:意思为超时返回,即在指定时间内没有文件描述符的对应的事件就绪。
(3)返回-1:出错返回,出现错误的可能原因有:
错误原因存于errno,此时参数readfds,writefds,exceptfds和 timeout的值变成不可预测。错误值可能为: EBADF 文件描述词为无效的或该文件已关闭。
EINTR 此调用被信号所中断。
EINVAL 参数n 为负值。
ENOMEM 核心内存不足。
8、用select函数实现网络服务器
代码如下:

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <fcntl.h>

static void usage(const char* proc)
{
    printf("%s [local_ip] [local_port]\n",proc);
}

int CreatSock(const char* _ip,int _port)
{
    int Sock=socket(AF_INET,SOCK_STREAM,0);
    if(Sock<0)
    {
        perror("socket");
        exit(2);
    }

    struct sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port=htons(_port);
    local.sin_addr.s_addr=inet_addr(_ip);

    if(bind(Sock,(struct sockaddr*)&local,sizeof(local))<0)
    {
        perror("bind");
        exit(3);
    }

    if(listen(Sock,5)<0)
    {
        perror("listen");
        exit(4);
    }
    return Sock;
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        return 1;
    }

    char fds[1024];
    int listensock=CreatSock(argv[1],atoi(argv[2]));
    int nums=sizeof(fds)/sizeof(fds[0]);
    int maxfd=-1;
    int i=1;
    for(;i<nums;i++)
    {
        fds[i]=-1;
    }

    fds[0]=listensock;

    umask(0);
    int open_fd=open("./sever_log",O_CREAT | O_RDWR,0664);
    if(open_fd<0)
    {
        perror("open");
        exit(10);
    }
    close(1);

    int ret=dup2(open_fd,1);

    char buf[1024];
    while(1)
    {
        struct timeval timeout={5,0};
        fd_set set;
        FD_ZERO(&set);
        maxfd=-1;

        for(i=0;i<nums;i++)
        {
            if(fds[i]>0)
            {
                FD_SET(fds[i],&set);
                if(maxfd<fds[i])
                {
                    maxfd=fds[i];
                }
            }
        }
        switch(select(maxfd+1,&set,NULL,NULL,NULL))
        {
            case 0:
                printf("timeout...\n");
                break;
            case -1:
                perror("select\n");
                break;
            default:
            {
                int i=0;
                for(;i<nums;i++)
                {
                    if(fds[i]<0)
                        continue;

                if(i==0 && FD_ISSET(listensock,&set))
                {
                    struct sockaddr_in client;
                    socklen_t len=sizeof(client);
                    int new_fd=accept(listensock,(struct sockaddr*)&client,&len);
                    if(new_fd<0)
                    {
                        perror("accept\n");
                        exit(5);
                    }

                    printf("get a client:[%s:%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));

                    int j=1;
                    for(;j<nums;j++)
                    {
                        if(fds[j]==-1)
                        {
                            break;
                        }
                    }

                    if(j==nums)
                    {
                        printf("set is full\n");
                        close(new_fd);
                    }

                    else
                    {
                        fds[j]=new_fd;
                    }
                }
                else if(i>0 && FD_ISSET(fds[i],&set))
                {
                    ssize_t s=read(fds[i],buf,sizeof(buf));
                    if(s>0)
                    {
                        buf[s]=0;
                        printf("client say:%s\n",buf);
                        fflush(stdout);
                        write(fds[i],buf,strlen(buf));
                    }
                    else if(s==0)
                    {
                        printf("client quit\n");
                        fflush(stdout);
                        close(fds[i]);
                        fds[i]=-1;
                    }
                    else
                    {
                        perror("read\n");
                    }

                }
                else
                {
                    ;
                }
                }
            }
                break;
        }
    }
    close(open_fd);
    return 0;
}

通过对该函数的实现,可以更加深入地了解select模型
(1)可监控的文件描述符个数取决于sizeof(fd_set):例如sizeof(fd_set)=512,则最多可监控的文件描述符个数为(512*8),因为一个文件描述符占据一个比特位。
(2)必须使用一个全局数组来保存加入到select监控集中的文件描述符,该全局数组有两个作用:
a.用于select函数返回之后,全局数组作为源数据和fd_set进行判断;
b.由于select函数每次返回之后就会将fd_set中之前加入的但是并没有发生事件的文件描述符清空,因此在重新调用select函数之前都要重新从全局数组中取得文件描述符加入fd_set中,并且扫描最大的文件描述符值加1,作为select函数的第一个参数。
c.select模型必须在select函数调用之前循环全局数组:用于往fd_set中加文件描述符,并取得最大的文件描述符值;
也必须在select函数返回之后循环全局数组:用于判断fd_set中的文件描述符是否有效。
该函数中使用了网络输出重定向dup函数,将本应该输出到显示屏上的内容输出到了文件中。

下面是客户端的代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>

static void usage(const char* proc)
{
    printf("usage:%s [remote_ip] [remote_port]\n",proc);
}


int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        exit(1);
    }

    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }

    struct sockaddr_in remote;
    remote.sin_family=AF_INET;
    remote.sin_port=htons(atoi(argv[2]));
    remote.sin_addr.s_addr=inet_addr(argv[1]);

    if(connect(sock,(struct sockaddr*)&remote,sizeof(remote))<0)
    {
        perror("connect");
        exit(3);
    }

    umask(0);
    int fd=open("./client_log",O_CREAT | O_RDWR,0664);
    if(fd<0)
    {
        perror("open");
        exit(4);
    }
    close(1);
    int new_fd=dup2(fd,1);

    char buf[1024];
    while(1)
    {
        printf("please enter:");
        memset(buf,'\0',sizeof(buf));
        fgets(buf,sizeof(buf),stdin);
        if(strncmp("quit",buf,4)==0)
        {
            printf("quit\n");
            printf("client is quit!\n");
            break;
        }
        printf("%s\n",buf);
        fflush(stdout);

        write(sock,buf,strlen(buf));
        ssize_t s=read(sock,buf,sizeof(buf)-1);
        if(recv>0)
        {
            buf[s]=0;
            printf("sever echo:%s\n",buf);
        }
    }
    close(fd);
    return 0;
}

该程序中依然使用了dup函数进行了网络输出重定向。

七、I/O多路转接之poll函数

1、函数原型
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
2、需要包含的头文件
#include <poll.h>
3、参数说明
(1)pollfd是一个结构体,该结构体的结构成员如下:

 struct pollfd{
  int fd; //poll监控的文件描述符
  short events; //请求的事件
(fd上等待的事件)
  short revents; //返回的事件
(fd上实际发生的事件)
  };
第一个参数fds是一个数组,理论上poll所能等待的文件描述符没有上限,一次可以传入一个数组,这与select函数使用三个位图来描述三个文件描述符集的方式不同,同时pollfd结构体包含了要等待的事件和实际返回的事件,这点也不同于select函数,不用“参数-值”的形式进行传递。

poll所能处理的文件描述符上的事件:
POLLIN:当前有数据可读;
POLLPRI:读取优先级高的数据,即优先处理紧急指针所指向的数据;
POLLOUT:当前写入数据;

(2) 第二个参数表示poll函数监视的文件描述符的个数。
(3)第三个参数timeout和select函数中的timeout的作用是相同的,timeout可以取三个值,每个值代表不同的含义:
a.-1:表示如果监视的文件描述符没有事件发生,则一直进行阻塞等待,直到有事件发生为止;
b.0:表示不等待fd上所请求的事件,直接返回;
c.某一特定值x:表示在一段特定时间x内监控的文件描述符上所等待的事件没有发生,则超时返回。
4、poll函数与select函数的联系
(1)poll是select的优化版本,主要体现在两个方面:
a.poll所能监控的文件描述符理论上是没有上限的,由于poll每次传入一个数组;
b.poll将输入参数(所监控的文件描述符上所等待的事件)和输出参数(所监控的文件描述符上实际发生的事件)进行分离,因此在使用poll函数之前不需要重新传入文件描述符。
(2)poll和select一样,都需要在返回之后对poll或者select轮询来获取准备就绪的文件描述符。
5、函数返回值也同select
(1)执行成功:则返回已经就绪的文件描述符的个数。
(2)返回0:意思为超时返回,即在指定时间内没有文件描述符的对应的事件就绪。
(3)返回-1:出错返回
6、用poll实现网络服务器
代码如下:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <poll.h>

#define MAXBUFSIZE 1024
#define MAXFD 1024

static void usage(const char* proc)
{
    printf("Usage:%s [local_ip] [local_port]\n",proc);
}

int CreatSock(char* _ip,int _port)
{
    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }

    struct sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port=htons(_port);
    local.sin_addr.s_addr=inet_addr(_ip);

    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
    {
        perror("bind");
        exit(3);
    }

    if(listen(sock,5)<0)
    {
        perror("listen");
        exit(4);
    }
    return sock;
}
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        exit(1);
    }

    int listenSock=CreatSock(argv[1],atoi(argv[2]));

    char buf[MAXBUFSIZE];
    struct pollfd fds[MAXFD];
    int i=0;
    int maxfd=0;
    for(;i<MAXFD;i++)
    {
        fds[i].fd=-1;
        fds[i].events=POLLIN|POLLOUT;
    }

    fds[0].fd=listenSock;
    while(1)
    {
        maxfd=0;
        for(i=0;i<MAXFD;i++)
        {
            if(fds[i].events&(POLLIN|POLLOUT))
            {
                maxfd=i;
            }
        }
        switch(poll(fds,maxfd+1,-1))
        {
            case 0:
                printf("timeout...\n");
                break;
            case -1:
                perror("poll");
                exit(5);
                break;
            default:
                {
                    int i=0;
                    for(;i<MAXFD;i++)
                    {
                        if(fds[i].fd<0)
                            continue;

                        if(i==0 && (fds[i].fd & POLLIN))
                        {
                            struct sockaddr_in client;
                            socklen_t len=sizeof(client);

                            int new_fd=accept(listenSock,(struct sockaddr*)&client,&len);
                            if(new_fd<0)
                            {
                                perror("accept");
                                exit(6);
                            }

                          printf("get a client:[%s:%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));

                          int j=1;
                          for(;j<MAXFD;j++)
                          {
                              if(fds[j].fd==-1)
                              {
                                  break;
                              }
                          }

                          if(j==MAXFD)
                          {
                              printf("fds is full\n");
                              close(new_fd);
                          }
                          else
                          {
                              fds[j].fd=new_fd;
                              fds[j].events=POLLIN|POLLOUT;
                          }
                        }

                        else if(i!=0 && (fds[i].fd!=-1))
                        {
                            while(1)
                            {
                             ssize_t s=read(fds[i].fd,buf,sizeof(buf));
                             if(s>0)
                             {
                                buf[s]=0;
                                printf("client say:%s\n",buf);
                                fflush(stdout);
                                write(fds[i].fd,buf,strlen(buf));
                             }
                            else if(s==0)
                             {
                                printf("client is quit!\n");
                                fflush(stdout);
                                close(fds[i].fd);
                                fds[i].fd=-1;
                                break;
                             }
                            else
                             {
                                perror("read");
                                exit(7);
                             }
                            }
                        }
                        else
                        {}
                    }
                }

                break;
        }
    }
    close(listenSock);
    return 0;
}

下面是客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>

static void usage(const char* _proc)
{
    printf("usage:%s [sever_ip] [sever_port]\n",_proc);
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        exit(1);
    }

    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }


    struct sockaddr_in remote;
    remote.sin_family=AF_INET;
    remote.sin_port=htons(atoi(argv[2]));
    remote.sin_addr.s_addr=inet_addr(argv[1]);

    int ret=connect(sock,(struct sockaddr*)&remote,sizeof(remote));
    if(ret<0)
    {
        perror("connect");
        exit(3);
    }

    umask(0);
    int fd=open("./pc_log",O_CREAT|O_RDWR,0664);
    if(fd<0)
    {
        perror("open");
        exit(4);
    }
    close(1);
    int new_fd=dup2(fd,1);

    char buf[1024];
    while(1)
    {
        printf("please enter:");
        memset(buf,'\0',sizeof(buf));
        fgets(buf,sizeof(buf),stdin);
        if(strncmp("quit",buf,4)==0)
        {
            printf("client quit!\n");
            break;
        }
        printf("%s\n",buf);
        fflush(stdout);

        write(sock,buf,strlen(buf));
        ssize_t _s=read(sock,buf,sizeof(buf)-1);
        {
            if(_s>0)
            {
                buf[_s]=0;
                printf("sever echo:%s\n",buf);
            }
        }
    }

    close(fd);
    return 0;
}

说明:客户端的输入全部重定向在文件pc_log中。

理解Linux五种I/O模型、同步I/O与异步I/O、阻塞与非阻塞 五种IO模型 、五种I/O模型的比较 、同步I/O与异步I/O 阅读详情

相关推荐

保姆级教程:Unity编辑器汉化全流程(从下载到配置避坑指南)

本文提供Unity编辑器汉化的保姆级教程,涵盖从下载中文语言包到配置避坑的全流程。详细解析版本适配、文件系统交互及编辑器底层配置逻辑,帮助开发者高效完成汉化,解决常见报错问题,提升工作效率。

weixin_30825581的博客 155

阻塞/非阻塞、同步/异步IO

一、阻塞和非阻塞 二、同步/异步 内核缓冲区 延迟写 写同步函数 fflush()与fsync() 三、接口函数 3.1 read/write 3.2 fcntl:改变已打开文件的属性(只需提供fd即可) 附1:进程的不同状态 一、阻塞和非阻塞 若对文件的一次I/O系统调用,读操作时无数据或写数据时可用空间不够,则阻塞模式下即会阻塞该进程,非阻塞模式下返回...

kyang_823的博客 1164

基于QT的华为网络摄像头二次开发

第一次使用华为的网络摄像头并进行二次开发,网上关于QT对华为网络摄像头的二次开发的文章很少,基于项目的需求做了一些工作,特此记录。 目标: 1、实时预览 2、手动控制录制视频 3、监听告警型号 4、实时获取元数据中的划定区域内的人数 摄像头型号如下: 准备工作: 在购买摄像头后,应当在官网下载对应的开发资料,如果需要权限,则联系华为的技术支持人员。下载资料如下: SDC Development Kit Demo 8.0.T9 SDK DEMO下载地址:https://bbs.hua

xumingyifrend的博客 3169

Linux 中的五种 I/O 模型

阻塞 I/O 模型、非阻塞 I/O 模型、I/O 复用模型、信号驱动 I/O 模型、异步 I/O 模型

We choose to go to the moon in this decade and do the other things, not because they are easy, but beacase they are hard. 2008

最优化学习笔记1——关于拟牛顿法推导

从2020年3月份到现在,一年的时间里断断续续自学最优化,结合豆瓣读书、知乎等网站上的推荐,翻阅了以下书和课程: Stephen Boyd和Lieven Vandenberghe的《Convex Optimization》,这本书被公认为学习凸优化的必读经典著作,其中大量的篇幅讲应用,讲理论和算法的篇幅稍少一些。在B网站上有Boyd的视频课程,油管上也有,不过只有英文字幕,如果是零基础接触,直接看Boyd的视频稍显费劲,B站上也有凌青老师以《Convex Optimization》为教材的讲解,推荐作为入

xiaofei473的博客 1768

Ubuntu 22.04 搭建 PX4 飞控系统完全指南:从仿真到硬件试飞

定义消息文件protobufuint64 timestamp # 时间戳float32 temperature # 温度float32 humidity # 湿度生成代码:bashPX4 在 Ubuntu 22.04 的搭建涉及环境配置、编译仿真、硬件连接等多环节,核心是理解 PX4 1.14 的新特性(uXRCE-DDS、动态控制分配)。通过本文指南,开发者可快速构建稳定的 PX4 开发环境,为无人机应用开发奠定基础。

zqmgx13291的博客 3040

Linux网络编程之I/O模型(详解)

本博客参考《Linux C/C++ 服务器开发实践》——朱文伟 李建英。

weixin_61503529的博客 961

大模型量化技术全解析:从INT8到GPTQ/AWQ,降低部署成本实战指南

模型量化是一种通过降低神经网络权重和激活值的数据精度(如从FP16降至INT8/INT4),从而大幅减少模型内存占用和计算开销的核心模型压缩技术。其原理基于线性变换,将高精度浮点数映射到低精度整数表示,在硬件层面能利用专用低精度计算单元实现显著加速。这项技术的核心价值在于解决了大模型(如千亿参数LLM)部署时面临的高昂显存成本和推理延迟问题,使其能在消费级GPU和边缘设备上高效运行。当前,后训练量化(PTQ)因其无需重新训练的特性成为主流,衍生出GPTQ、AWQ、SmoothQuant等多种方法,广泛应用于

weixin_33804582的博客 630

Linux:(五种IO模型)

我们知道,IO过程我们在意的是拷贝,而不是等待。而拷贝需要的时间是由电路还有系统实现等保证的。随着科技的发展,拷贝本身花费的时间已经基本没有提升空间了,所以拷贝本身的效率已经很难再有提升了。那么等待时间的长度就决定了IO的效率。

weixin_70067429的博客 1178

5大步骤!轻松玩转Dorisoy.Rigger:基于.NET Core 6、MAUI和Blazor的多数据库开发框架生成器

各位小伙伴,你们是否厌倦了每次项目启动都要从头配置数据库连接、编写重复的代码?今天,我们就来聊聊如何使用Dorisoy.Rigger这个强大的开发框架生成器,让你的.NET Core 6、MAUI和Blazor项目开发变得简单又高效!准备好迎接开发的新乐趣了吗?让我们一起开始吧!接下来,我们需要定义数据模型。假设我们有一个简单的用户表,包含ID、用户名和密码字段。在项目中创建一个新的类文件,命名为User.csset;set;set;这段代码定义了一个用户模型,其中包含了用户的ID、用户名和密码。

java专栏 1739

基于Vivado MIG IP核的DDR3读写实验(top_rom_ddr/ddr_top)

一、前言 关于Vivado MIG IP核详细配置可以参考我之前的文章:基于Vivado MIG IP核的DDR3控制器(DDR3_CONTROL) 关于MIG IP核的用户端的接口时序可以参考这篇文章:XILINX 的 MIG IP(非AXI4)接口时序以及控制 二、实验内容 本次实验的内容主要是通过MIG IP核向DDR3读写数据,DDR3的接口时序由ddr_top模块提供: ddr_top模块的数据来源是wr_fifo,wr_fifo的数据实际来自top_sd_photo模块(本实验仿真

耐心的小黑的博客 3027

Linux 下的五种 I/O 模型

模型数据是否阻塞等待是否手动发起读取是否内核完成拷贝属于同步/异步阻塞 I/O是是是同步 I/O非阻塞 I/O否(轮询)是是同步 I/OI/O 复用是(等事件)是是同步 I/O信号驱动 I/O否(信号通知)是是同步 I/O异步 I/O否否(内核完成)是异步 I/O。

陈子青的博客 759

【第1章】基于FPGA的图像形态学处理学习教程——目录

本课程介绍图像形态学处理技术,通过腐蚀、膨胀、开运算、闭运算等算子对图像进行优化。腐蚀可去除边缘杂色使线条更清晰,膨胀能填补缺口修复图像,开运算擅长去噪,闭运算则用于修补断裂。课程内容涵盖四大形态学处理的理论分析、MATLAB仿真和FPGA开发实现,包括腐蚀、膨胀、开闭运算以及顶帽变换等操作,最后探讨形态学处理的实际应用场景。通过仿真测试和FPGA开发实践,帮助学员掌握图像"美容塑型"的核心技术。

MATLAB,verilog,python,opencv,tensorflow,caffe,C,C++ 338

『Linux』五种I/O模型

五种I/O模型。阻塞式I/O、非阻塞式I/O、I/O复用、信号驱动式I/O、异步I/O。其它重要概念。同步和异步。阻塞和非阻塞。其它高级I/O。如何设置非阻塞I/O。

叄拾叄画生 400

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

深入探讨:Linux 的五种 I/O 模型

I/O模型描述了应用程序与操作系统在数据传输过程中的交互方式。不同模型在效率、资源利用和复杂性方面各有特点,适用于多种使用场景。Linux 提供了以下五种主流 I/O 模型:阻塞 I/O(Blocking I/O)非阻塞 I/O(Non-blocking I/O)I/O 多路复用(I/O Multiplexing)信号驱动 I/O(Signal-driven I/O)异步 I/O(Asynchronous I/O)

leonharda的博客 630

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【Linux | 网络I/O模型】五种网络I/O模型详解

模型发起 I/O 请求等待 I/O 操作处理结果特点阻塞 I/O发起请求阻塞等待完成处理结果简单易懂,但效率低非阻塞 I/O发起请求立即返回(检查状态)处理结果轮询方式,效率较高I/O 多路复用发起请求等待事件发生处理已就绪事件高效处理多个 I/O 操作信号驱动式 I/O发起请求等待信号处理信号避免轮询,编程复杂异步 I/O发起请求继续执行其他任务处理结果(回调或通知)高效处理大量并发操作。

qq_42037383的博客 1594

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Linux五种I/O模型与fcntl非阻塞控制

五种I/O模型:1)阻塞I/O(进程全程等待);2)非阻塞I/O(轮询检查);3)信号驱动I/O(内核通知);4)I/O多路转接(单线程监控多描述符);5)异步I/O(内核全自动处理)。

Miun123的博客 4003

Linux五种I/O模型深度剖析:从阻塞到异步的全面指南

理解Linux的I/O模型是构建高性能系统的基石。从简单的阻塞I/O到复杂的异步AIO,每种模型都有其独特的价值。80%的场景使用epoll多路复用即可满足需求特殊场景考虑非阻塞或信号驱动模型存储密集型应用关注io_uring等新技术通过本文的代码实例和对比分析,希望您能根据具体需求选择最合适的I/O模型,构建出高效可靠的Linux应用。最后思考:随着存储硬件速度的提升(NVMe SSD、持久内存),I/O模型的选择将如何演变?欢迎在评论区分享你的见解!

conkl的博客 1073

Linux的五种I/O模型

在了解这几种I/O之前,徐要先明确同步异步,阻塞非阻塞的概念。

hhhlizhao的博客 422

【Linux网络】I/O 世界的技术之旅:探索五种模型与 fcntl 函数的魅力

1.获取,设置文件状态信息:cmd=F_GETFL,F_SETFL。 2.复制现有的描述符,cmd=F_DUPFD。 3.获取,设置文件描述符标识,cmd=F_GETFD,F_SETFD。 4.获取,设置异步IO所有权,cmd=F_GETOWN,F_SETOWN。 5.获取、设置记录锁,cmd=F_GETLK,F_SETLK,F_SETLKW。

路虽远,行则将至!事虽难,做则必成! 3434

Linux五种I/O模型

I/O = Input/Output,输入/输出。数据的流动输入:数据从外部设备 → 进入内存(比如读文件、收网络包、键盘输入)输出:数据从内存 → 到外部设备(比如写文件、发网络包、屏幕显示)

2301_81470485的博客 409

Linux网络编程必修课:五种I/O模型

欢迎各位文章底部关注我,每天专注分享Linux、Unix、 C/C+ +后端开发、面试题等技术知识讲解在当今这个数据驱动的时代,无论是 Web 服务器、数据库系统,还是嵌入式设备,都离不开一个核心操作——输入/输出(I/O)。而作为后端开发、系统编程、甚至是性能调优的核心战场,Linux 的 I/O 模型无疑是我们必须掌握的基础知识之一。I/O = 等待 + 拷贝,而且等待的时间往往比拷贝还长!所以,提升 I/O 效率的关键,就是减少等待时间。

m0_73443478的博客 712

【Linux】Linux/Unix五种I/O模型

【Linux】Linux/Unix五种I/O模型

半生瓜のblog 899

linux下五种i o的复用模式,Linux中五种常见的I/O模型

一般来说,程序进行输入操作有两步:等、搬迁。在Linux下,共有五种I/O模型,下面就逐一介绍:1>.阻塞I/O(使用比较广)应用程序调用一个I/O函数,如果数据木有准备好,就会导致应用程序阻塞,直到数据准备好了,从内核拷贝到用户空间(进程的缓存),I/O函数返回成功。如一个进程调用recvform,然后系统调用并不返回直到有数据包到达本地系统,然后完成数据拷贝。2>.非阻塞I/O(...

weixin_39623050的博客 195

linux的五种I/O模型、socket知识总结

1. Linux中的5种I/O模型 以read操作为例,I/O需要经历两个阶段: 等待数据准备好(waiting for the data to be eady) 将数据从内核拷贝到进程中(copying the data from the kernel to the process) 如果是socket中的read操作,第一步通常等待数据从网络中到达,数据到达后会被复制到内核的接收缓冲...

lucyLee的博客 444

linux编程下的五种网络I/O模型

在linux下编程,我们常见有四种调试模式,分别是同步(Sync),异步(Async),阻塞(block)和非阻塞(Unblock). 同步和异步的概念描述的是用户的线程与内核IO操作的方式:同步是指用户线程发起IO请求后需要等待内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后任然继续不断的执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。 linux下编程...

qq_44041062的博客 225
上一篇: TCP定时器
下一篇: Linux下的git配置
LP9127
博客等级 码龄11年 15粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值