当前位置: 首页 > news >正文

『 Linux 』高级IO (一)

文章目录

    • 内容回顾及铺垫
    • 五种IO模型
    • 不同类型IO的区别
    • 非阻塞IO
      • fcntl( )
    • 多路转接 - select( )
      • select( ) 的基本使用 - SelectServer服务器


内容回顾及铺垫

在博客『 Linux 』基础IO/文件IO (万字)中介绍了对IO的认识;

IO实际上为Input/Output,输入输出;

以网络协议栈的视角来看,操作系统分为四层,分别为应用层,传输层,网络层及数据链路层;

假设在网络通信过程中调用read()/write()系统调用接口,对于应用层而言并不是真正的在进行IO操作;

当应用层在网络通信过程中通过调用read()/write()系统调用接口来进行网络通信,本质上是在进行一个拷贝操作;

  • read()

    将数据由内核缓冲区拷贝至应用层缓冲区;

  • write()

    将应用层缓冲区内数据拷贝至内核缓冲区;

因为这些函数本质只是拷贝函数,而真正对于数据是否进行发送的决策交由各层协议来决定;

而这些拷贝函数的拷贝行为是在缓冲区内资源(数据)已经就绪的前提下,若是资源未就绪则可能进行等待;

如在调用一些输入函数时,如从键盘中进行输入的函数scanf(),在调用该函数时执行流将会进行阻塞,原因为需要等待资源就绪,当用户使用键盘输入完毕后即表示资源已经就绪,届时执行流将继续执行;

再举例在进行网络通信过程中(以TCP协议为例),双方可以通过调用read()/write()send()/recv()函数进行网络通信,而TCP协议中, 双方都具有相同的缓冲区,即一个输入缓冲区和一个输出缓冲区;

而调用recv()或是read()进行对内核缓冲区内数据进行读取时若是内核缓冲区资源未就绪,则该执行流可能会阻塞一段时间;

因此本质上IO操作即为 “拷贝 + 等” ;

而要进行拷贝,必须先判断条件是否成立,此处的条件通常代指读写事件;

  • 读事件

    读事件表示内核缓冲区中的数据已经就绪,可以拷贝至上层缓冲区;

  • 写事件

    写事件表示上层缓冲区中的数据已经就绪,可以拷贝至内核缓冲区;

有一个关于IO的概念为,单位时间内单次IO吞吐量越高效率越高,实际上这也被称为高效的IO;

也可以理解为单位时间内的IO过程中,等的比重越小,IO的效率也就越高;

几乎所有提高IO效率的策略本质上就是降低IO过程中 “等” 的时间比重;


五种IO模型

IO模型主要分为五种,分别为阻塞IO,非阻塞IO,多路复用,信号驱动式IO以及异步IO;

该章节介绍IO模型以调用recvfrom()函数,即触发 “读事件” 为例;

  • 阻塞式IO

    阻塞IO是最常见的IO模型,通常情况下阻塞IO将在内核数据准备好前对应的系统调用将会一直处于等待状态;

    同时所有的套接字默认都为阻塞方式;

    当上层调用recvfrom()函数进行读取操作时,执行流将会阻塞,内核将会等待直至读事件就绪;

    当读事件就绪后执行流将继续,数据将由内核缓冲区拷贝至应用层缓冲区,再由上层进行对数据报的处理;

  • 非阻塞式IO

    非阻塞式IO同样会判断事件是否已就绪,与阻塞式IO模型不同,非阻塞式IO模型并不会阻塞执行流并等待事件就绪,该模型将会判断一次事件是否已经就绪,若是事件就绪则进行后续操作,若是事件未就绪则直接返回;

    当使用recvfrom()函数进行非阻塞IO操作时,若是事件未就绪将直接返回EWOULDBLOCK;

    因此通常在使用非阻塞式IO模型时都会采用轮询的方式,即反复调用对应的非阻塞式IO操作;

    通过轮询的方式,通常情况下,由于recvfrom()函数的非阻塞轮询操作是由上层调用的,这意味着上层可以通过轮询的策略使得在事件未就绪前能够进行其他操作;

  • 信号驱动IO

    信号驱动IO是一种利用SIGIO信号进行驱动的一种IO模型;

    通过注册信号处理函数告诉操作系统当事件就绪时发送对应的信号以进行通知,当注册好后对应的执行流可以进行其他任务的处理;

    当事件就绪后操作系统将会发送SIGIO信号给进程,对应的信号处理函数中将会调用recvfrom()等相关操作将数据由内核缓冲区拷贝至用户缓冲区;

    最终将数据交由上层进行数据报处理;

    信号驱动IO犹如收外卖,当外卖员将外卖送到了你的门前将会敲门,按门铃或是以打电话的方式,这些方式都是一种信号的递交方式;

    当你接收到信号后将要放下手中的活去开门拿外卖,或是付钱等操作;

    当然也可以利用多线程来完成这些操作,如让家里的其他家人代你去签收外卖一样;

  • IO多路转接(多路复用)

    多路转接(多路复用)类似于阻塞IO模型,也可以说该模型是阻塞模型的一种优化版本;

    传统的阻塞IO模型只能对一个IO的位置进行观察与等待;

    而通常情况下IO是通过文件描述符进行的,这意味着传统的阻塞式IO模型只能观察一个文件描述符,而多路复用则可以观察多个文件描述符以保证效率上的提升;

  • 异步IO模型

    异步IO模型与信号驱动型IO模型类似但不同,在使用信号驱动型IO模型进行IO操作时,当应用程序接收到对应的信号后,将要阻塞当前的执行流从而去处理IO操作中的拷贝操作或其他操作;

    而异步IO模型只需调用aio_read()函数即可通知内核当读事件就绪时直接让内核进行完整的IO操作而不必预先通知上层,当IO操作处理完毕后再使用指定的信号通知上层;


不同类型IO的区别

IO的本质是 " 等 + 拷贝 ";

  • 阻塞IO与非阻塞IO

    实际上无论是阻塞IO还是非阻塞IO其两者单凭IO效率而言两者的效率是相当的;

    在上文中所提到的五种模型中,单凭IO而言都是等待事件就绪再进行拷贝操作;

    而常常提到的非阻塞IO效率高的原因是在使用非阻塞IO模型时(可能是轮询也可能是信号驱动),在进行等待的过程中进程不会阻塞在原地一直等待至事件就绪,在非阻塞等待事件就绪的这个时间段进程可以去完成一些其他的任务,在总体的效率上提升效率;

  • 同步IO与异步IO

    上文中介绍的物种IO模型,除了异步IO模型以外都属于同步IO模型;

    其本质上的区别为是否需要参与IO过程;

    上述中的模型中除了异步IO外,其他所有的IO模型执行流都将在事件就绪后去进行数据的拷贝操作;

    而异步IO并不需要参与该过程,当调用对应的aio_read()函数后IO将全权交由内核进行处理,包括等待与拷贝的过程;

    当整个IO过程完成后内核将发送特定的信号或是采用回调函数的方式告诉上层IO已经完成;

    换句话来说就是异步IO只发起IO,不参与IO过程;


非阻塞IO

  • 如何进行非阻塞IO

在一些系统调用接口中,如read()/write()recv()/send()等函数进行IO操作时,默认采用的是阻塞IO的方式;

当然recv()/send()系统调用接口可根据flag参数来设置使用阻塞还是非阻塞的IO方式;

ssize_t send(int sockfd, const void *buf, size_t len, int flags);ssize_t recv(int sockfd, void *buf, size_t len, int flags);

这两个函数中的flag参数选项有许多,但用来设置非阻塞IO的选项为MSG_DONTWAIT;

但这种方式在实际的使用过程中并不方便,即使当需要设置一个文件描述符为非阻塞式IO时都要使用对应的函数并设置的选项,且使用这种方式进行非阻塞IO时只是在此操作中进行了一次非阻塞IO;

相比之下使用fcntl()系统调用接口将会在IO中使IO操作更加灵活;


fcntl( )

NAMEfcntl - manipulate file descriptorSYNOPSIS#include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );DESCRIPTIONfcntl() performs one of the operations described below on the open file descriptor fd.  The operation is determined by cmd.

通常情况下,每一个文件描述符的IO操作都是属于阻塞式IO的;

fcntl()系统调用接口可以设置一个文件描述符的IO属性为非阻塞模式;

当调用该函数将一个文件描述符的IO属性设置为非阻塞模式时,至手动解除非阻塞模式或是该文件描述符的生命周期结束前,所有关于该文件描述符的IO操作都将视为非阻塞IO操作(如read()/write(),recv()/send()等);

这种方式比每次调用send()/recv()函数时都传递MSG_DONTWAIT参数更加方便和灵活;

假设存在一个程序,这个程序将调用read()系统调用接口来获取0号文件描述符(键盘文件)中的数据并进行打印;

int main()
{char buff[1024];while (true){printf("Please Enter # ");fflush(stdout);ssize_t n = read(0, buff, sizeof(buff) - 1);if (n > 0){buff[n - 1] = 0;cout << "Echo: " << buff << endl;}else if (0 == n){cout << "Read Done" << endl;break;}else{cout << "Read Error" << endl;break;}}return 0;
}

以这段代码为例,定义了一个char类型的数组作为字符串来接收由0号文件描述符中所接收到的数据,并进行打印;

当程序运行时,进程阻塞并等待键盘文件中的资源就绪,即等待读事件就绪;

当读事件就绪后read()系统调用函数将数据读出而后进行打印;

在上文中提到,任何文件描述符的默认IO属性都是为阻塞式IO,而通过fcntl()系统调用接口可以设置一个文件描述符的IO属性;

void SetNonBlock(int fd)
{int flags = fcntl(fd, F_GETFL); // 获取标记位if (flags < 0){ // 获取标记位失败perror("fcntl");return;}fcntl(fd, F_SETFL, flags | O_NONBLOCK); // 利用或来增加属性
}int main()
{char buff[1024];SetNonBlock(0); // 调用while (true){// ...}return 0;
}

在原有的代码中增加了一个SetNonBlock()函数,这个函数是利用fcntl()系统调用接口实现的;

首先先调用fcnt()系统调用接口传递F_GETFL获取对应文件描述符中的标记位fd;

    int flags = fcntl(fd, F_GETFL); // 获取标记位

而后判断标记位是否获取成功,如果获取失败则返回;

随后调用fcnt()系统调用接口传递F_SETFL参数并添加O_NONBLOCK来将标记位以属性的方式设置进对应的文件描述符中;

    fcntl(fd, F_SETFL, flags | O_NONBLOCK); // 利用或来增加属性

当进程运行过后将进入非阻塞的轮询状态,不断调用read()系统调用接口,由于未读到任何有效数据(读事件未就绪),将一直走判断中的else部分;

键盘的输入与进程中的非阻塞轮询状态并不冲突,当键盘输入并按下回车时表示读事件已经就绪,对应的键盘所输入的信息将被打印出来;

而通常情况下read()系统调用接口默认是阻塞式IO方式,也验证了可以通过使用fcntl()系统调用接口来设置一个文件描述符的IO属性为非阻塞IO;

同时为了验证该处所对应的"Read Error"表示资源未就绪,可以使用strerror()函数来打印出对应的错误码及错误码信息;

 if (n > 0){// ...}else if (0 == n){// ...}else{cout << "Read Error , n = " << n << " errno code: " << errno << "  " << strerror(errno) << endl;}

运行结果为:

表示资源未就绪;

通常情况下可以通过errno以及strerror(errno)等方式来判断出错原因;

当然在程序当中最好根据错误码来识别是否出错,因此可以将代码完善一下:

    while (true){printf("Please Enter # ");fflush(stdout);ssize_t n = read(0, buff, sizeof(buff) - 1);if (n > 0){buff[n - 1] = 0;cout << "Echo: " << buff << endl;}else if (0 == n){cout << "Read Done" << endl;break;}else{if (errno == EWOULDBLOCK){cout << "Resource temporarily unavailable" << endl;// TODO 可完成其他任务}else{cout << "Read Error , n = " << n << " errno code: " << errno << "  " << strerror(errno) << endl;}}sleep(1);}

这是典型的非阻塞轮询IO模型,当判断事件未就绪时,执行流可以根据需求完成其他任务(TODO部分)随后再进行下一次轮询从而提高整体效率;


多路转接 - select( )

select() 函数是用来进行多路转接的一个接口;

IO可以分为 “等 + 拷贝” 两个部分,而select()函数真正做到的是其中的 “等” 的部分,其可以设置一个进程在IO过程中通过该接口阻塞等待多个文件描述符;

#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);void FD_CLR(int fd, fd_set *set);int  FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);

该函数的返回值(n表返回值)通常有三种情况:

  • n > 0

    返回值大于0则表示有n个文件描述符就绪;

  • n == 0

    表示超时,没有错误也没有文件描述符就绪;

  • n < 0

    表示出错;

select()函数参数为如下:

  • int nfds

    该参数用于标示可能需要检查的文件描述符个数;

    通常需要传入 当前进程最大文件描述符+1 ,即maxfd + 1;

  • struct timeval *timeout

    该参数类型是一个结构体类型,其定义如下:

    The timeout argument for select() is a structure of the following type:struct timeval {time_t      tv_sec;         /* seconds */suseconds_t tv_usec;        /* microseconds */};
    

    该类型为系统提供的一个时间结构体;

    其中time_t tv_sec;表示时间戳,单位为秒,suseconds_t tv_usec;表示微秒;

    该变量本质是为select()设置等待方式,也是一个超时事件,假设该参数传入[5,0],即struct timeval timeout = [5,0],则表示当5s过后将会返回(timeout)一次;

    若是设置为[0,0]则表示立马返回(典型的非阻塞式IO);

    需要澄清一下的是该参数所设置的等待方式是只用作于一次调用的;

    若是该参数设置为NULL则表示阻塞等待;

    同时当使用select()并设置等待方式后,该参数就会成为一个输入输出型参数;

    假设使用select()并设置等待方式为[5,0],但若是在2s后有文件描述符的事件就绪,对应的select()将立即返回,同时其timeout参数将会变为[3,0];

除了上两个参数以外,select()系统调用接口还有三个类型相同的参数,分别为readfds,writefds以及exceptfds;

这三个参数的类型都为fd_set,而该类型实际上即为一个位图类型,是有操作系统内核提供,与sigset类似;

这三个参数分别代表使用select()系统调用接口所关心的事件类型,即:

  • 读事件
  • 写事件
  • 异常事件

三种事件,其中用户所传入位图中的各个位标识着select()需要关心哪些文件描述符需要关心哪些事件;

如在读事件对应的参数传入0001,即表示关心0号文件描述符的读事件;

同时这三个fd_set类型的参数同样是输入输出型参数,当用户因调用select()传入对应的fd_set类型时,其中位图中的位标识对应文件描述符需要关心的对应事件是否就绪,而当该函数因某些文件描述符中的某些事件就绪后而返回,对应的事件类型中的位图将会被修改为事件已经就绪的文件描述符;

这表明了在使用select()函数时需要大量的进行位图操作,而这里的位图结构是由操作系统内核提供,为了保证内核安全性,系统不会直接让用户来修改对应的位图结构,因此为用户提供了一系列的位图操作;

即在上文中提到的:

	   void FD_CLR(int fd, fd_set *set);int  FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);
  • void FD_CLR(int fd, fd_set *set)

    表示将一个文件描述符从一个位图集合上去除;

  • int FD_ISSET(int fd, fd_set *set)

    判断一个文件描述符是否在对应的位图集合上被设置;

  • void FD_SET(int fd, fd_set *set)

    在一个位图集合上设置对应的文件描述符;

  • void FD_ZERO(fd_set *set)

    清空一个位图集合;


select( ) 的基本使用 - SelectServer服务器

为了验证select()的功能及其基础的使用,这里实现了一个SelectServer服务器;

在之前的博客中对Socket直接进行了封装,这里直接套用原有的代码不进行赘述(参考博客『 Linux 』协议的定制中 " 套接字接口的封装 " 部分,同样的这里还涉及到之前实现的日志系统的demo);

对于main()函数而言,只需要实例化一个服务器对象,并且调用服务器对象中的初始化方法Init()与服务器对象中的启动方法即Start();

/*	Main.cc	*/
int main()
{std::unique_ptr<SelectServer> svr(new SelectServer()); // 防拷贝智能指针svr->Init();svr->Start();return 0;
}

其中SelectServer即为服务器类型;

同样的,服务器需要提供初始化与启动的方法API;

/*	SelectServer.hpp	*/static const uint16_t defaultport = 8050;class SelectServer
{
public:SelectServer(uint16_t port = defaultport) : _port(port) {}bool Init(){_listensock.Socket();_listensock.Bind(_port);_listensock.Listen();return true;}void Start(){for (;;){// ...}}~SelectServer(){_listensock.Close();}private:NetSocket _listensock;uint16_t _port;
};

在这个类中提供了初始化的方法和启动的方法,其中初始化的方法包括监听套接字的创建初始化,绑定以及设置监听;

通常情况下,启动服务器时就可以调用accept()来获取新的连接;

而在使用select()时这里不能直接使用accept()来获取新连接,因为本质上accept()就是检测并获取_listensock监听套接字上的读事件,只能在这上面进行二选一;

若是使用select()时需要一个位图结构,这个位图结构即为内核提供的fd_set类型;

/*	SelectServer.hpp	*/class SelectServer
{
public:void Start(){int listensock = _listensock.GetFd();fd_set rfds;               // 读文件描述符集for (;;){// 不能直接accept 本质上accept就表示检测并获取listensock上的事件// 新连接的到来等价于读事件的就绪FD_ZERO(&rfds);            // 清空描述符集FD_SET(listensock, &rfds); // 将文件描述符写入至读文件描述符集中struct timeval timeout = {5, 0};int n = select(listensock + 1, &rfds, nullptr, nullptr, &timeout);switch (n){case 0:printf("Time out, timeout: %ld . %ld\n", timeout.tv_sec, timeout.tv_usec);break;case -1:printf("Select Error\n");break;default:printf("%d fd Even Ready, timeout: %ld . %ld\n", n, timeout.tv_sec, timeout.tv_usec);sleep(2);break;}}}
};

这段代码为SelectServer服务器中的Start()启动方法,使用select()进行事件的查看,首先定义了一个fd_set rfds文件描述符集(位图);

  • 随后循环进行以下操作:

    以此调用FD_ZERO()方法,将文件描述符集进行一次清空;

    随后调用FD_SET()方法传入_listensock.GetFd()+1,设置文件描述符中最大值+1(根据文件描述符的规律为 “顺序向上,有空补空” ,因此SelectServer服务器中的监听套接字描述符是最大的);

    创建timeval时间结构体并设置timeout等待方式(超时事件),此处设置为[5,0],表示5s后返回一次(timeout被设置时为输入输出型参数,每次都在自减,因此需要在循环中循环重新进行设置);

    最后调用select()将文件描述符集传入对应位置;

                int n = select(listensock + 1, &rfds, nullptr, nullptr, &timeout);
    

    最后根据返回值n判断其他操作;

对于返回值n的判断使用了switch()case语句的方式,当n > 0时表示n个文件描述符已经就绪,当n == 0时表示超时事件就绪(timeout一次),当n < 0时表示select()出错;

运行程序,并使用telnet工具配合环回地址测试;

从结果可以看出,当程序运行时,在还没有使用telnet工具进行连接时,由于select()没有检测到读事件,在5stimeout一次,对应的timeout的时间戳已经被减到了[0.0];

在第二次调用时等待了两秒作用使用telnet工具进行本地连接,select()立即返回,此时也可以观察到timeout的时间戳发生了变化;

第三次以及后续的timeout都返回了[4 . 99...]类似的值,本质是连接一直是存在的,而情况读文件描述符集与将文件描述符集通过select()以及该函数的调用与返回是有时间上的开销的,即使速度很快;

若是此处将timeout设置为[ 0 , 0 ]则说明使用非阻塞的方式进行,这里配合循环显然是一个典型的轮询机制,当然如果使用select()依旧使用轮询的话将会加大消耗,通常不建议这么使用;

同样的若是timeout设置为nullptr则表示使用阻塞式;

当程序运行时却没有连接(事件未就绪)将出于阻塞状态,直至有连接;

通常情况下当使用seletc()后返回时事件就绪后应该立即对就绪时间进行处理,若上层未处理select()将一直通知(原因在上文中有介绍);

相关文章:

『 Linux 』高级IO (一)

文章目录 内容回顾及铺垫五种IO模型不同类型IO的区别非阻塞IOfcntl( ) 多路转接 - select( )select( ) 的基本使用 - SelectServer服务器 内容回顾及铺垫 在博客『 Linux 』基础IO/文件IO (万字)中介绍了对IO的认识; IO实际上为Input/Output,输入输出; 以网络协议栈的视角来看,…...

Cisco WebEx 数据平台:统一 Trino、Pinot、Iceberg 及 Kyuubi,探索 Apache Doris 在 Cisco 的改造实践

导读&#xff1a;Cisco WebEx 早期数据平台采用了多系统架构&#xff08;包括 Trino、Pinot、Iceberg 、 Kyuubi 等&#xff09;&#xff0c;面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此&#xff0c;引入 Apache Doris 替换了 Trino、Pinot…...

Java - 日志体系_Apache Commons Logging(JCL)日志接口库

文章目录 官网1. 什么是JCL&#xff1f;2. JCL的主要特点3. JCL的核心组件4. JCL的实现机制5. SimpleLog 简介6. CodeExample 1 &#xff1a; 默认日志实现 (JCL 1.3.2版本)Example 2 &#xff1a; JCL (1.2版本&#xff09; Log4J 【安全风险高&#xff0c;请勿使用】 7. 使用…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02

在嵌入式开发中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种常用的串行通信协议&#xff0c;广泛应用于与外设&#xff08;如 EEPROM、传感器、显示屏等&#xff09;进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器&#xff0c;它提供 2Kbit…...

盒子模型(外边距的设置)

用于页面中元素的合理布局所有的元素都可以有宽高所有元素都是一个矩形所有元素都可以看成一个盒子盒子包括 外边距边框内边距元素内容 外边距设置 外边距的要素&#xff1a;top、bottom、left、right外边距的尺寸&#xff1a;合法的尺寸单位外边距语法&#xff1a;marign-方…...

买卖股票的最佳时机 IV - 困难

************* C topic&#xff1a;188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; ************* Stock angin: Still stocks. Intuitively, it feels hard. For once: class Solution { public:int maxProfit(vector<int>& prices) {in…...

ElasticSearch - 深入解析 Elasticsearch Composite Aggregation 的分页与去重机制

文章目录 Pre概述什么是 composite aggregation&#xff1f;基本结构after 参数的作用问题背景&#xff1a;传统分页的重复问题after 的设计理念响应示例 after 如何确保数据不重复核心机制Example步骤 1: 创建测试数据创建索引插入测试数据 步骤 2: 查询第一页结果查询第一页返…...

HTML5 Web IndexedDB 数据库

IndexedDB 是一种基于浏览器的 NoSQL 数据库&#xff0c;用于在客户端持久化存储大量结构化数据。 IndexedDB 允许通过键值对存储复杂的数据对象&#xff08;如对象、数组、文件等&#xff09;&#xff0c;并支持事务、索引、版本控制和复杂查询操作。 IndexedDB 是异步的&am…...

苏黎世联邦理工学院与加州大学伯克利分校推出MaxInfoRL:平衡内在与外在探索的全新强化学习框架

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

读书笔记~管理修炼-缄默效应

缄默效应&#xff1a;学会正确批评下属 员工明明犯了错误&#xff0c;却不及时告知你&#xff0c;总是拖到最后一刻无法弥补时才不得不承认出了问题——你遇到过这样的问题吗&#xff1f; 这其实是缄默效应在发挥作用。 在职场中&#xff0c;即使再扁平化的环境&…...

LabVIEW声音信号处理系统

开发了一种基于LabVIEW的声音信号处理系统&#xff0c;通过集成的信号采集与分析一体化解决方案&#xff0c;提升电子信息领域教学与研究的质量。系统利用LabVIEW图形化编程环境和硬件如USB数据采集卡及声音传感器&#xff0c;实现了从声音信号的采集到频谱分析的全过程。 项目…...

2024.12.10——攻防世界Web_php_include

知识点&#xff1a;代码审计 文件包含 伪协议 伪协议知识点补充&#xff1a; 在PHP中&#xff0c;伪协议&#xff08;Pseudo Protocols&#xff09;也被称为流包装器&#xff0c;这些伪协议以 php://开头&#xff0c;后面跟着一些参数&#xff0c;用于指定要执行的操作或需要…...

Linux shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件

Linux Debian12基于ImageMagick图像处理工具编写shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件&#xff0c;”多个图片分开生成多个PDF文件“或者“多个图片合并生成一个PDF文件” 在Linux系统中&#xff0c;使用ImageMagick可以图片格式转换&#xff0c…...

有没有检测吸烟的软件 ai视频检测分析厂区抽烟报警#Python

在现代厂区管理中&#xff0c;安全与规范是重中之重&#xff0c;而吸烟行为的管控则是其中关键一环。传统的禁烟管理方式往往依赖人工巡逻&#xff0c;效率低且存在监管死角&#xff0c;难以满足当下复杂多变的厂区环境需求。此时&#xff0c;AI视频检测技术应运而生&#xff0…...

LeetCode 每日一题 2024/12/16-2024/12/22

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 12/16 1847. 最近的房间12/17 3291. 形成目标字符串需要的最少字符串数 I12/18 3292. 形成目标字符串需要的最少字符串数 II12/19 3285. 找到稳定山的下标12/20 3138. 同位…...

gitlab代码推送

点击这个√ 修改的文件全部选上 填好提交的名称 点击commit 选取提交的 gitlab 库 点击Push...

小红书飞书素材库 | AI改写 | 无水印下载 | 多维表格 | 采集同步 | 影刀RPA

小红书飞书素材库 | AI改写 | 无水印下载 | 多维表格 | 采集同步 | 影刀RPA 模板准备 进入【小红书】素材采集库_荷逸模板&#xff0c;点击使用模板 创建文档应用 在开发者后台 - 飞书开放平台创建 企业自建应用 (需要账号有相应的权限, 如果没有权限向管理员申请) 获取 Ap…...

【计算机视觉基础CV-图像分类】02-入门详解图像分类、经典数据集、比赛与冠军图像模型演进史

前言 图像分类&#xff08;Image Classification&#xff09;是计算机视觉&#xff08;Computer Vision&#xff09;中一项基础且核心的任务。简单来说&#xff0c;就是让计算机从给定的类别集合中&#xff0c;为一张输入图片分配一个正确的类别标签。这个过程听起来直观&…...

【机器学习】探索机器学习与人工智能:驱动未来创新的关键技术

探索机器学习与人工智能&#xff1a;驱动未来创新的关键技术 前言&#xff1a;人工智能的核心技术深度学习&#xff1a;自然语言处理&#xff08;NLP&#xff09;&#xff1a;计算机视觉&#xff1a; 机器学习与人工智能的驱动创新医疗健康领域金融行业智能制造与工业互联网智慧…...

DS二叉树--基于数组存储的构建

题目描述 任意二叉树可以根据完全二叉树性质保存在一个数组中。已知二叉树的数组存储&#xff0c;用程序构建该二叉树。 提示&#xff1a;用递归方法或非递归都可以 输入 第一行输入一个整数t&#xff0c;表示有t个测试数据 第二行起输入二叉树的数组存储结果&#xff0c;空…...

入侵他人电脑,实现远程控制(待补充)

待补充 在获取他人无线网网络密码后&#xff0c;进一步的操作是实现入侵他人电脑&#xff0c;这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址&#xff08;通过伪造的网页、伪造的Windows窗口、hook&#xff0c;信…...

STM32基于标准库如何查看时钟主频,100%简单

基于原有的工程写入两行代码&#xff0c;见下图 RCC_ClocksTypeDef get_rcc_clock; RCC_GetClocksFreq(&get_rcc_clock); 进入我们的仿真加入断点&#xff0c;然后在watch1观察变量值数据&#xff0c;然后在计算器计算就能得出&#xff0c;如上图。 但是这样看的PAB1上…...

HarmonyOS NEXT 技术实践-基于意图框架服务实现智能分发

在智能设备的交互中&#xff0c;如何准确理解并及时响应用户需求&#xff0c;成为提升用户体验的关键。HarmonyOS Next 的意图框架服务&#xff08;Intents Kit&#xff09;为这一目标提供了强大的技术支持。本文将通过一个项目实现的示例&#xff0c;展示如何使用意图框架服务…...

[原创](Modern C++)现代C++的第三方库的导入方式: 例如Visual Studio 2022导入GSL 4.1.0

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共23年] 职业生涯: 21年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse…...

【jenkins插件】

1) 2) 3) 4) 5) 6) 参考: 知识库/运维/Jenkins/01-安装/13-插件.md zfoo/java-developer-document - 码云 - 开源中国...

springboot472基于web网上村委会业务办理系统(论文+源码)_kaic

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上村委会业务办理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…...

七层网络笔记

首先&#xff0c;用户感知到的只是最上面一层应用层&#xff0c;自上而下每层都依赖于下一层&#xff0c;所以我们从最下一层开始切入&#xff0c;比较好理解 每层都运行特定的协议&#xff0c;越往上越靠近用户&#xff0c;越往下越靠近硬件 物理层由来&#xff1a;上面提到&a…...

PostgreSQL编译安装教程

下载安装 1.在家目录创建一个文件夹放下载安装包 mkdir softwarecd software 2.下载文件压缩包 wget https://ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz 3.解压 tar -xzvf postgresql-16.0.tar.gz 4.编译 在software/postgresql-16.0下 cd software…...

音视频学习(二十四):hls协议

基本原理 HLS协议通过将视频文件切分成多个小的媒体段&#xff08;通常是10秒左右的.ts文件&#xff09;&#xff0c;并通过HTTP传输给客户端。视频播放过程中&#xff0c;客户端按顺序请求这些小段文件来逐步播放整个视频流。HLS还支持多种码率&#xff0c;以便适应不同网络条…...

pytorch MoE(专家混合网络)的简单实现。

专家混合&#xff08;Mixture of Experts, MoE&#xff09;是一种深度学习模型架构&#xff0c;通常用于处理大规模数据和复杂任务。它通过将输入分配给多个专家网络&#xff08;即子模型&#xff09;&#xff0c;然后根据门控网络&#xff08;gating network&#xff09;的输出…...

代码随想录day24 | leetcode 93.复原IP地址 90.子集 90.子集II

93.复原IP地址 Java class Solution {List<String> result new ArrayList<String>();StringBuilder stringBuilder new StringBuilder();public List<String> restoreIpAddresses(String s) {backtracking(s, 0, 0);return result;}// number表示stringb…...

Scala项目(图书管理系统)

3、service BookService package org.app package serviceimport org.app.dao.{BookDAO, BorrowRecordDAO} import org.app.models.{BookModel, BorrowRecordModel}import java.time.LocalDateTime import scala.collection.mutable.ListBuffer// 图书业务逻辑层 class BookS…...

Deepin/Linux clash TUN模式不起作用,因网关导致的问题的解决方案。

网关导致的问题的解决方案 查看路由 ip route寻找默认路由 默认路由应当为Mihomo default dev Mihomo scope link 如果不是&#xff0c;则 sudo ip route add default dev Mihomo在clash TUN开关状态发生变化时&#xff0c;Mihomo网卡会消失&#xff0c;所以提示找不到网卡…...

【macos java反编译工具Java Decompiler】

mac上能用的反编译工具 https://java-decompiler.github.io/...

VLAN数据格式

概念&#xff1a;VLAN叫做虚拟局域网&#xff0c;指在物理网络中根据用于、工作组、应用等进行逻辑划分的局域网&#xff0c;是一个广播域&#xff0c;与用户的物理位置没有关系。 作用&#xff1a;VLAN可以灵活的进行分段和组织&#xff0c;能够实现更好的安全性&#xff0c;…...

Error response from daemon: Get “https://registry-1.docker.io/v2/“ 问题解决

文章目录 一、参考资料二、修改nameserver三、修改daemon.json文件 一、参考资料 问题的根源在于系统每次都会自动修改DNS&#xff0c;所以需要永久修改 linux永久修改dns 二、修改nameserver sudo nano /etc/resolvconf/resolv.conf.d/head 没有该文件的话需要安装 sudo a…...

每天40分玩转Django:Django部署

Django部署 一、今日学习内容概述 学习模块重要程度主要内容生产环境配置⭐⭐⭐⭐⭐settings配置、环境变量WSGI服务器⭐⭐⭐⭐⭐Gunicorn配置、性能优化Nginx配置⭐⭐⭐⭐反向代理、静态文件安全设置⭐⭐⭐⭐⭐SSL证书、安全选项 二、生产环境配置 2.1 项目结构调整 mypr…...

学习threejs,scene.overrideMaterial全局材质效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.2 ☘️THREE.Scene 场景1.2 ☘️…...

新版Android Studio 2024.1.2版本,如何通过无线wifi连接手机实现交互

1、首先&#xff0c;先确定手机是否启动了开发者选项 在我的设备 -> 全部参数 -> MIUI版本点击6下 &#xff08;有的手机是 关于手机 -> 查看手机版本 &#xff09; 2、在设置中搜索 开启开发者选项 3、进入开发者选项后&#xff0c;在 调试 中选择 无线调试并选择…...

PTA 时间几何

作者 Happyer 单位 湖北文理学院 乘火车或飞机常有由始发时间历经时间计算终到时间的事儿。我们通过三个 函数来完成&#xff0c;当然&#xff0c;为了存储几点几分这个时间&#xff0c;我们专门定义了一个结构体Time_gxx,你要完成的是写二个函数&#xff1a;1&#xff09;st…...

事务、管道

目录 事务 相关命令 悲观锁 乐观锁 管道 实例 Pipeline与原生批量命令对比 Pipeline与事物对比 使用Pipeline注意事项 事务 相关命令 命令描述discard取消事务&#xff0c;放弃执行事务块内的所有命令exec执行所有事务块内的事务&#xff08;所有命令依次执行&#x…...

深入了解蓝牙Profile类型与设备的对应关系

在现代技术中,蓝牙作为一种无线通信技术,广泛应用于各种设备之间的短距离通信。不同的设备在连接时使用不同的蓝牙Profile(配置文件),每种Profile都为特定的设备功能提供支持,例如音频流传输、语音通话、文件传输等。在本文中,我们将详细介绍蓝牙Profile的常见类型及其对…...

net_device结构

net_device是Linux内核中用于表示网络设备的数据结构,它存储了特定网络设备的所有信息,无论是真实设备(如Ethernet)还是虚拟设备(如Bonding或VLAN)。以下是对net_device的详细解析: 一、定义与位置 net_device数据结构定义在Linux内核的include/linux/netdevice.h文件中…...

DuetWebControl 开源项目常见问题解决方案

DuetWebControl 开源项目常见问题解决方案 DuetWebControl A completely new web interface for the Duet electronics [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/du/DuetWebControl 一、项目基础介绍 DuetWebControl 是一个为 RepRapFirmware 设计的完全响…...

c# 不同数据类型转换

namespace Systempublic static class ConvertExtension {public static byte[] ToBinaryByteArray(this byte[] bytes){// 每个字节有 8 位&#xff0c;所以总位数为 bytes.Length * 8byte[] binaryArray new byte[bytes.Length * 8];int index 0;// 遍历每个字节foreach (b…...

2025.01.15python商业数据分析top2

一、 导入项目 导入项目、准备项目数据 import pandas as pd# 文件路径为python文件位置下的相对路径dwxpd.read_excel("电蚊香套装市场近三年交易额.xlsx") fmfzpd.read_excel("防霉防蛀片市场近三年交易额.xlsx") msmcpd.read_excel("灭鼠杀虫剂市…...

软件信息化平台项目投标技术方案中如何进行项目实施方案以及安全质量方案培训售后方案应急预案的编写?

在软件平台投标技术方案中,项目实施方案、质量管理、安全管理、培训方案、售后服务方案和应急预案等章节至关重要,它们分别从不同角度确保项目的顺利实施、高质量交付、安全稳定运行、用户有效使用、持续服务保障以及应对突发情况的能力。各章节编制要点相互关联、协同作用,…...

目标检测-R-CNN

R-CNN在2014年被提出&#xff0c;算法流程可以概括如下&#xff1a; 候选区域生成&#xff1a;利用选择性搜索(selective search)方法找出图片中可能存在目标的候选区域(region proposal) CNN网络提取特征&#xff1a;对候选区域进行特征提取(可以使用AlexNet、VGG等网络) 目…...

计算机毕业设计PySpark+PyFlink+Hive地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Hadoop 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

panddleocr-文本检测+文本方向分类+文本识别整体流程

panddleocr-文本检测文本方向分类文本识别整体流程 通过文本检测–>文本方向分类–>文本识别&#xff0c;即可识别出0~360度的旋转文本。 文本检测的最小外接矩形框根据长宽可以看到90度的角度&#xff0c;而再加入文本方向分类就能扩展到180度的角度。...