网络-多路io

了 fcntl 函数来操作文件描述符的状态标志,其中主要是为了设置非阻塞模式。下面是对 fcntl 函数及其参数的详细解释:

fcntl 函数

fcntl 是一个用于操作文件描述符的系统调用,可以用来设置或获取文件描述符的各种属性。其原型如下:

int fcntl(int fd, int cmd, ... /* arg */ );

  • fd: 需要操作的文件描述符。
  • cmd: 操作类型(命令),指定要执行的操作。
  • arg: 额外参数,根据 cmd 的不同可能需要。

参数解释

F_GETFL 和 F_SETFL
  • F_GETFL: 获取文件描述符的当前状态标志。这个命令将返回文件描述符的当前状态标志。
  • F_SETFL: 设置文件描述符的状态标志。这个命令将文件描述符的状态标志设置为指定的值。
代码分析
int flag = fcntl(fd_r, F_GETFL);
fcntl(fd_r, F_SETFL, flag | O_NONBLOCK);

  1. int flag = fcntl(fd_r, F_GETFL);

    • 获取文件描述符 fd_r 的当前状态标志,并存储在变量 flag 中。
    • F_GETFL 命令返回的状态标志包括文件描述符的访问模式(如读、写)和一些状态标志(如是否为非阻塞模式)。
  2. fcntl(fd_r, F_SETFL, flag | O_NONBLOCK);

    • 使用 F_SETFL 命令设置文件描述符 fd_r 的状态标志。
    • flag | O_NONBLOCK 表示将 O_NONBLOCK 标志添加到当前状态标志中。
    • O_NONBLOCK 是一个标志,用于设置文件描述符为非阻塞模式。非阻塞模式意味着读写操作不会阻塞进程,如果无法立即完成操作,系统调用会立即返回,而不是等待。
flag = fcntl(0, F_GETFL);
fcntl(0, F_SETFL, flag | O_NONBLOCK);

  1. flag = fcntl(0, F_GETFL);

    • 获取标准输入(文件描述符 0)的当前状态标志,并存储在变量 flag 中。
  2. fcntl(0, F_SETFL, flag | O_NONBLOCK);

    • 使用 F_SETFL 命令设置标准输入的状态标志。
    • flag | O_NONBLOCK 表示将 O_NONBLOCK 标志添加到标准输入的当前状态标志中。
    • 这将把标准输入设置为非阻塞模式,使得读取标准输入的操作不会阻塞进程。

总结

  • fcntl(fd_r, F_GETFL) 用于获取文件描述符 fd_r 的当前状态标志。
  • fcntl(fd_r, F_SETFL, flag | O_NONBLOCK) 用于将 fd_r 的状态标志设置为非阻塞模式,确保对 fd_r 的读写操作不会阻塞。
  • 同样,fcntl(0, F_GETFL) 和 fcntl(0, F_SETFL, flag | O_NONBLOCK) 将标准输入(文件描述符 0)设置为非阻塞模式,使得读取标准输入的操作也是非阻塞的。

通过这些设置,你可以确保读写操作在没有数据时不会导致程序阻塞,从而使程序能够在执行其他任务时保持响应。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo1",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}int fd_r = open("myfifo1",O_RDONLY);if(-1 == fd_r){perror("open");return 1;}int flag = fcntl(fd_r,F_GETFL);fcntl(fd_r,F_SETFL,flag|O_NONBLOCK);flag = fcntl( 0,F_GETFL);fcntl(0,F_SETFL,flag|O_NONBLOCK);while(1){char buf[128]={0};if(read(fd_r,buf,sizeof(buf))>0){printf("fifo:%s\n",buf);}bzero(buf,sizeof(buf));if(fgets(buf,sizeof(buf),stdin)){printf("terminal:%s\n",buf);}}return 0;
}

signal函数在多路io

演示了如何使用信号驱动 I/O(SIGIO)来处理命名管道(FIFO)的异步事件。下面是对代码及各个函数的作用的详细解释:

代码解析

1. #include 和 全局变量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>int fd_r;

  • #include:引入了必要的头文件,提供了函数原型和常量定义。
  • fd_r:定义一个全局变量,用于存储打开的 FIFO 文件描述符。
2. handle 函数
void handle(int num)
{char buf[128]={0};read(fd_r,buf,sizeof(buf));printf("fifo:%s\n",buf);return ;
}

  • handle:信号处理函数,当收到 SIGIO 信号时被调用。
    • num:传递给信号处理函数的信号编号,这里没有用到。
    • read(fd_r, buf, sizeof(buf)):从 FIFO 中读取数据到 buf
    • printf("fifo:%s\n", buf):打印读取到的数据。
3. main 函数
int main(int argc, char *argv[])
{signal(SIGIO, handle);

  • signal(SIGIO, handle):设置信号处理函数,当进程接收到 SIGIO 信号时,会调用 handle 函数。
    int ret = mkfifo("myfifo1",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}

  • mkfifo("myfifo1", 0666):创建一个名为 "myfifo1" 的 FIFO(命名管道)。如果文件已存在 (EEXIST),则不处理错误。
    fd_r = open("myfifo1", O_RDONLY);if(-1 == fd_r){perror("open");return 1;}

  • open("myfifo1", O_RDONLY):以只读模式打开 FIFO,并将文件描述符存储在 fd_r 中。如果打开失败,打印错误信息并退出。
    int flag = fcntl(fd_r, F_GETFL);fcntl(fd_r, F_SETFL, flag | O_ASYNC);

  • fcntl(fd_r, F_GETFL):获取当前文件描述符的状态标志。
  • fcntl(fd_r, F_SETFL, flag | O_ASYNC):设置文件描述符为异步模式 (O_ASYNC)。这意味着当文件描述符有数据可读时,会向进程发送 SIGIO 信号。
    fcntl(fd_r, F_SETOWN, getpid());

  • fcntl(fd_r, F_SETOWN, getpid()):设置 fd_r 文件描述符的信号所有者为当前进程(getpid())。这使得 SIGIO 信号会发送到当前进程。
    while(1){char buf[128]={0};bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);printf("terminal:%s\n", buf);}return 0;
}

  • 无限循环
    • fgets(buf, sizeof(buf), stdin):从标准输入读取数据到 buf
    • printf("terminal:%s\n", buf):打印从标准输入读取的数据。

主要函数的作用

  1. signal(SIGIO, handle)

    • 用于设置进程在接收到 SIGIO 信号时调用 handle 函数。
  2. mkfifo("myfifo1", 0666)

    • 创建一个命名管道(FIFO)。如果已存在,则不处理错误。
  3. open("myfifo1", O_RDONLY)

    • 打开创建的 FIFO 文件,以只读模式获取文件描述符。
  4. fcntl(fd_r, F_GETFL) 和 fcntl(fd_r, F_SETFL, flag | O_ASYNC)

    • 获取和设置文件描述符的状态标志,使其处于异步模式。异步模式会使文件描述符触发信号(SIGIO),当数据到达时通知进程。
  5. fcntl(fd_r, F_SETOWN, getpid())

    • 设置文件描述符 fd_r 的信号所有者为当前进程,使得 SIGIO 信号会发送到当前进程。
  6. read(fd_r, buf, sizeof(buf))

    • 在信号处理函数中,从 FIFO 中读取数据。
  7. fgets(buf, sizeof(buf), stdin) 和 printf("terminal:%s\n", buf)

    • 在主循环中,读取标准输入的数据并打印。

总结

这段代码通过设置文件描述符 fd_r 为异步模式,并为其指定信号所有者,使得当有数据可读时会发送 SIGIO 信号。信号处理函数 handle 会在收到 SIGIO 时被调用,从 FIFO 中读取数据并打印。这种方式允许进程在等待数据的同时执行其他操作,比如读取标准输入。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
int fd_r;
void handle(int num)
{char buf[128]={0};read(fd_r,buf,sizeof(buf));printf("fifo:%s\n",buf);return ;
}
int main(int argc, char *argv[])
{signal(SIGIO,handle);int ret = mkfifo("myfifo1",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}fd_r = open("myfifo1",O_RDONLY);if(-1 == fd_r){perror("open");return 1;}//给管道设置信号驱动int flag = fcntl(fd_r,F_GETFL);fcntl(fd_r,F_SETFL,flag| O_ASYNC);//如果有写管道,本进程作为sigio信号的接收者fcntl(fd_r,F_SETOWN,getpid());while(1){char buf[128]={0};bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);printf("terminal:%s\n",buf);}return 0;
}

select 函数用于监视多个文件描述符的状态,以便在其中一个或多个文件描述符变为可读、可写或出现异常时进行处理。下面是对 select 相关函数和操作的详细解释。

select 函数

select 函数用于监视文件描述符集合,以确定哪些文件描述符在某个时间点是就绪的(即,可以进行读、写操作或出现异常)。其原型如下:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

  • nfds: 文件描述符的数量+1。它通常是你感兴趣的最大文件描述符值加1。
  • readfds: 监视的文件描述符集合(用于读操作)。
  • writefds: 监视的文件描述符集合(用于写操作)。
  • exceptfds: 监视的文件描述符集合(用于异常条件)。
  • timeout: 指定 select 函数的超时时间。如果超时时间为 NULL,则 select 将无限期等待直到有文件描述符变为可用。

fd_set 操作函数

  • FD_ZERO(fd_set *set): 清空文件描述符集合 set
  • FD_SET(int fd, fd_set *set): 将文件描述符 fd 添加到文件描述符集合 set 中。
  • FD_CLR(int fd, fd_set *set): 从文件描述符集合 set 中移除文件描述符 fd
  • FD_ISSET(int fd, fd_set *set): 检查文件描述符 fd 是否在文件描述符集合 set 中。

代码分析

// 1. 创建文件描述符集合
fd_set rd_set, tmp_set; // 读集合
FD_ZERO(&rd_set);       // 清空读集合
FD_ZERO(&tmp_set);      // 清空临时集合// 2. 添加文件描述符
FD_SET(0, &tmp_set);    // 将标准输入(文件描述符 0)添加到临时集合
FD_SET(fd_r, &tmp_set); // 将文件描述符 fd_r 添加到临时集合while (1) {// 6. 复制临时集合到读集合rd_set = tmp_set;char buf[128] = {0};// 3. 等待事件发生select(fd_r + 1, &rd_set, NULL, NULL, NULL);// 4. 查找发生事件的文件描述符if (FD_ISSET(fd_r, &rd_set)) {read(fd_r, buf, sizeof(buf));printf("fifo: %s\n", buf);}if (FD_ISSET(0, &rd_set)) {bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);printf("terminal: %s\n", buf);}
}

  1. 创建文件描述符集合

    • fd_set rd_set, tmp_set; 定义了两个 fd_set 类型的变量,用于存储文件描述符集合。
    • FD_ZERO(&rd_set); 清空 rd_set 集合。
    • FD_ZERO(&tmp_set); 清空 tmp_set 集合。
  2. 添加文件描述符

    • FD_SET(0, &tmp_set); 将标准输入(文件描述符 0)添加到 tmp_set 集合中。
    • FD_SET(fd_r, &tmp_set); 将文件描述符 fd_r 添加到 tmp_set 集合中。
  3. 等待事件

    • rd_set = tmp_set; 复制 tmp_set 到 rd_setrd_set 用于 select 调用,避免在 select 调用后丢失对文件描述符的跟踪。
    • select(fd_r + 1, &rd_set, NULL, NULL, NULL); 等待直到 fd_r 或标准输入有数据可读。fd_r + 1 是需要监视的文件描述符的数量加1。
  4. 处理事件

    • FD_ISSET(fd_r, &rd_set) 检查 fd_r 是否在 rd_set 中,即检查 fd_r 是否有数据可读。如果有,读取数据并打印。
    • FD_ISSET(0, &rd_set) 检查标准输入是否在 rd_set 中,即检查标准输入是否有数据可读。如果有,读取数据并打印。

总结

  • select 用于监视多个文件描述符,以确定哪些文件描述符准备好进行读、写或异常处理。
  • fd_set 操作函数用于创建和修改文件描述符集合。
  • 在代码中,select 被用于等待标准输入或文件描述符 fd_r 中有数据可读,并根据文件描述符的状态执行相应的读取操作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo1",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}int fd_r = open("myfifo1",O_RDONLY);if(-1 == fd_r){perror("open");return 1;}//1 create set fd_set rd_set,tmp_set; //read set FD_ZERO(&rd_set);FD_ZERO(&tmp_set);// 2. add fd FD_SET(0,&tmp_set);FD_SET(fd_r,&tmp_set);while(1){//6.clean flagrd_set = tmp_set;char buf[128]={0};//3 wait event select(fd_r+1,&rd_set,NULL,NULL,NULL );//4 找到对应的fdif(FD_ISSET(fd_r,&rd_set)){read(fd_r,buf,sizeof(buf));printf("fifo:%s\n",buf);}if(FD_ISSET(0,&rd_set)){bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);printf("terminal:%s\n",buf);}}return 0;
}

epoll

epoll 被用来实现对两个文件描述符的事件通知机制。下面是对各个函数和操作的详细分析:

1. add_fd(int epfd, int fd)

这个函数用于将一个文件描述符 fd 添加到 epoll 实例 epfd 中,并指定感兴趣的事件类型。

  • 参数
    • epfdepoll_create 创建的 epoll 文件描述符。
    • fd:要添加到 epoll 的文件描述符。
  • 操作
    • 创建一个 epoll_event 结构体 ev,设置感兴趣的事件为 EPOLLIN,表示关注该文件描述符的可读事件。
    • 使用 epoll_ctl 函数将 fd 添加到 epoll 实例中,操作类型为 EPOLL_CTL_ADD
  • 返回值
    • 返回 epoll_ctl 的结果,如果返回 -1 表示添加失败,并调用 perror 打印错误信息。

2. main(int argc, char *argv[])

主函数的执行流程:

  1. 创建命名管道(FIFO)

    • 使用 mkfifo 创建两个命名管道 "myfifo1" 和 "myfifo2",这两个管道用于进程间通信。如果创建失败并且错误码不是 EEXIST(文件已存在),则打印错误信息并退出。
  2. 打开命名管道

    • 使用 open 打开 myfifo1(以只读模式)和 myfifo2(以只写模式),分别获得 fd_r 和 fd_w 文件描述符。如果打开失败,打印错误信息并退出。
  3. 创建 epoll 实例

    • 使用 epoll_create 创建一个 epoll 实例,并返回一个文件描述符 epfd。如果创建失败,打印错误信息并退出。
  4. 添加文件描述符到 epoll 实例

    • 调用 add_fd 函数将标准输入(文件描述符 0)和管道 myfifo1 的文件描述符 fd_r 添加到 epoll 实例中,开始监听它们的事件。
  5. 事件监听循环

    • 进入无限循环,调用 epoll_wait 等待事件发生。epoll_wait 会阻塞直到有事件发生,或者超时(这里设置为 -1,表示无限等待)。

    • 事件处理

      • 如果 epoll_wait 返回有事件发生,遍历所有的事件:
        • 如果事件的文件描述符是标准输入(0),读取输入数据并写入到 fd_w,如果输入为 "#quit\n",则退出程序。
        • 如果事件的文件描述符是 fd_r,从 fd_r 读取数据并打印。如果读取的数据是 "#quit\n" 或读取失败,则退出程序。

主要函数和操作的作用总结

  1. epoll_create:创建 epoll 实例,返回 epoll 文件描述符。此文件描述符用于后续的 epoll_ctl 和 epoll_wait 操作。

  2. epoll_ctl:对 epoll 实例进行控制操作,如添加、修改或删除文件描述符及其事件。此处用于将文件描述符添加到 epoll 实例中。

  3. epoll_wait:等待 epoll 实例中的文件描述符发生事件。阻塞直到有文件描述符的事件发生或者超时,返回发生的事件数量。

  4. fgets 和 write:用于从标准输入读取数据,并写入到 fd_w 对应的管道中。

  5. read 和 printf:用于从 fd_r 对应的管道中读取数据,并输出到标准输出。

这段代码展示了如何使用 epoll 机制来处理异步 I/O 操作,同时实现了基于命名管道的进程间通信。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/epoll.h>int add_fd(int epfd,int fd)
{struct epoll_event ev;ev.events = EPOLLIN;ev.data.fd = fd;int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);if(-1==ret){perror("add_fd");}return ret;
}int main(int argc, char *argv[])
{int ret = mkfifo("myfifo1",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}ret = mkfifo("myfifo2",0666);if(-1 == ret){if( EEXIST!= errno ){perror("mkfifo");return 1;}}int fd_r = open("myfifo1",O_RDONLY);if(-1 == fd_r){perror("open");return 1;}int fd_w = open("myfifo2",O_WRONLY);if(-1 == fd_w){perror("open");return 1;}struct epoll_event rev[2];int epfd;int ep_ret;epfd = epoll_create(2);if(-1==epfd){perror("epoll_create");return 1;}add_fd(epfd,0);add_fd(epfd,fd_r);while(1) {ep_ret = epoll_wait(epfd,rev,2,-1);if(ep_ret>0){int i=0;for(i=0;i<ep_ret;i++){if(0==rev[i].data.fd){printf("to A:");char buf[128]={0};fgets(buf,sizeof(buf),stdin);//#quitif(0 == strcmp(buf,"#quit\n")){exit(0);}write(fd_w,buf,strlen(buf));}else if(fd_r==rev[i].data.fd){char buf[128]={0};int ret = read(fd_r,buf,sizeof(buf));if(0==strcmp(buf,"#quit\n") || ret<=0){exit(0);}printf("from A:%s",buf);fflush(stdout);}}}}return 0;
}

第一步 创建epoll_create

第二步  添加成员

第三步  epoll_wait()

有timeout的使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415297.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubeadm部署 Kubernetes(k8s) 高可用集群【V1.20 】

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 calico.yaml kubernertes-dashboard.yaml 1. 安装要求 在开始之前&#xff0c;部署Kubernetes集群机器需要满足以下几个条件&#xff1a; 7台机器&#xff0c;操作系统Openeuler22.03 LTS SP4硬件配置&#…

通义千问AI PPT初体验:一句话、万字文档、长文本一键生成PPT!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

笔记:《利用Python进行数据分析》之透视表和交叉表

透视表和交叉表 透视表&#xff08;pivot table&#xff09;是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合&#xff0c;并根据行和列上的分组键将数据分配到各个矩形区域中。在Python和pandas中&#xff0c;可以通过本章所…

黑悟空!一区预定!原创首发!SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测

黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测 目录 黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序…

前缀和专题——一维模版+二维模版力扣实战应用

目录 1、模版 1.1【模版】一维前缀和 1.1.1 算法思想 1.1.2 算法代码 1.2【模版】二维前缀和 1.2.1 算法思想 1.2.2 算法代码 2、算法应用【leetcode】 2.1 题一&#xff1a;寻找数组的中心下标 2.1.1 算法思想 2.1.2 算法代码 2.2 题二&#xff1a;除自身以外数组…

聚观早报 | 理想汽车OTA 6.2发布;京东大幅上调校招薪资

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 9月3日消息 理想汽车OTA 6.2发布 京东大幅上调校招薪资 哪吒汽车8月销量持续破万 C919国产大飞机首航在即 现代…

怎么找TikTok代运营助力?灵感魔方怎么样?

在当今全球化的浪潮中&#xff0c;海外版抖音已然成为了品牌出海的重要阵地。然而&#xff0c;面对这个充满机遇与挑战的平台&#xff0c;如何找到专业的TikTok代运营团队来助力品牌成功出海呢&#xff1f;以下是一些关键的考量因素和方法。 首先&#xff0c;专业的TikTok代运…

【机器学习】图像处理与深度学习利器:OpenCV实战攻略全面解析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 前言 OpenCV想必大家都听过跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而…

巴黎奥运会引发体育健身热潮:气膜体育馆成为新宠—轻空间

随着巴黎奥运会的成功举办&#xff0c;全球范围内掀起了一股体育健身的热潮。各地的健身场所迎来了前所未有的参与热情&#xff0c;其中&#xff0c;融合了体育、娱乐、休闲等多种业态的综合气膜体育馆因其独特的优势&#xff0c;迅速成为群众健身的新宠&#xff0c;成为了大众…

视频搬运的素材网站有哪些?打包好的视频素材在哪找?

探索短视频创作世界时&#xff0c;是不是经常碰到缺乏素材的难题&#xff1f;无需担心&#xff0c;今天我们来聊聊一些能够即刻丰富你视频内容的素材网站。无论是搬运视频还是寻找灵感&#xff0c;这些资源站都将为你的创作锦上添花。特别强调的是&#xff0c;除了国际上的珍贵…

小土堆pytorch

anaconda安装 pip list 可以看有哪些package包 nvidia-smi查看显卡的状态 安装pytorch 检验pytorch是否安装成功&#xff0c;以及是否pytorch是否可以使用gpu。 (1)查看conda版本 conda --version 或 conda -V (2)更新conda&#xff08;将conda自身更新到最新版本&#xff09; …

sqlite数据插入效率

一、程序效率测试 时间相关接口&#xff1a; int gettimeofday(struct timeval*tv, struct timezone *tz); 功能&#xff1a;得到从1970年1月1日0时0分0秒到现在的秒数。<可以利用该函数来计算一个程序的运行时间&#xff0c;只需在程序前后调用该函数&#xff0c;…

计算机网络概述(分组延时、丢失和吞吐量)

目录 分组丢失和延时是怎样发生的&#xff1f; 四种分组延时 节点延时 排队延迟 分组丢失 吞吐量 吞吐量&#xff1a;互联网场景 分组丢失和延时是怎样发生的&#xff1f; 在路由器缓冲区的分组队列 分组到达链路的速率超过了链路输出的能力分组等待排队到队头、被传输…

基于.NET6的WPF基础总结(上)

目录 一.常用属性介绍 二、 程序退出方式 三、布局样式 3.1 Panel的附加属性ZIndex 3.2 Grid(网格)布局 3.3 UniformGrid&#xff08;均分布局&#xff09; 3.4 StackPanel&#xff08;堆积面板&#xff09; 3.5 WrapPanel&#xff08;换行面板&#xff09; 3.6 Doc…

什么是I2C总线?

1.什么是I2C&#xff1f; 1.1 I2C的由来 在电视机内部电路中&#xff0c;众多功能需要用到许多集成电路IC来实现&#xff0c;包括主控器件微控制器和众多外围设备器件。这些器件相互之间要传递数据信息&#xff0c;那么就需要用导线相互连接&#xff0c;如此众多IC器件的互连&…

linux下cpu多核运行程序以及运行时间统计

一、多核心运行程序 在linux下我们可以指定线程或者进程运行在指定的cpu核心上&#xff0c;操作方法如下&#xff1a; 1&#xff09;运行进程指定cpu核心 taskset -c 2 ./app //-c指定运行的cpu核心号&#xff0c;从0计数&#xff0c;查看效果如下&#xff1a; 2&#xff09…

两句话讲清楚离线安装docker镜像

两句话讲清楚离线安装docker镜像 文章目录 两句话讲清楚离线安装docker镜像写在前面解决方案 写在前面 背景&#xff1a;银河麒麟、离线环境&#xff0c;装吧&#xff0c;一装一个不吱声。 准备&#xff1a; 首先&#xff0c;你要有个docker&#xff0c;安装好了才能搞镜像是不…

C++:构造函数与析构函数

一.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数&#xff0c;如下图&#xff1a; 其中最重要的就是我们表格中的前四个函数&#xff0c;本篇文章我们主要介绍前三个。默认成员函数很重要&#xff0c;也比较复杂…

下载xhsell连接Linux系统

一、下载安装xshell 1、下载 免费版的网址&#xff1a;家庭/学校免费 - NetSarang Website 2、安装 选择自己想要下载的文件夹位置 创建一个新的文件夹即可 不想注册可以直接选择后来先进行试用 二、连接Linux虚拟机 1、点击加号新建会话 2、输入你要连接的虚拟机的IP地址…

4、Django Admin对自定义的计算字段进行排序

通常&#xff0c;Django会为模型属性字段&#xff0c;自动添加排序功能。当你添加计算字段时&#xff0c;Django不知道如何执行order_by&#xff0c;因此它不会在该字段上添加排序功能。 如果要在计算字段上添加排序&#xff0c;则必须告诉Django需要排序的内容。你可以通过在…