linux环形缓冲区kfifo实践3:IO多路复用poll和select

基础知识 

poll和select方法在Linux用户空间的API接口函数定义如下。

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

poll()函数的第一个参数fds是要监听的文件描述符集合,类型为指向struct pollfd的指针。struct pollfd数据结构定义如下。

struct pollfd {int  fd;short events;short revents;
};

fd表示要监听的文件描述符,events表示监听的事件,revents表示返回的事件。常用的监听的事件有如下类型(掩码)。

  •         POLLIN:数据可以立即被读取。
  •         POLLRDNORM:等同于POLLIN,表示数据可以立即被读取。
  •         POLLERR:设备发生了错误。
  •         POLLOUT:设备可以立即写入数据。

        poll()函数的第二个参数nfds是要监听的文件描述符的个数;第三个参数timeout是单位为ms的超时,负数表示一直监听,直到被监听的文件描述符集合中有设备发生了事件。

Linux内核的file_operations方法集提供了poll方法的实现。 

<include/linux/fs.h>
struct file_operations {…unsigned int (*poll) (struct file *, struct poll_table_struct *);…
};

        当用户程序打开设备文件后执行poll或者select系统调用时,驱动程序的poll方法就会被调用。设备驱动程序的poll方法会执行如下步骤。

1)在一个或者多个等待队列中调用poll_wait()函数。poll_wait()函数会把当前进程添加到指定的等待列表(poll_table)中,当请求数据准备好之后,会唤醒这些睡眠的进程。

2)返回监听事件,也就是POLLIN或者POLLOUT等掩码。因此,poll方法的作用就是让应用程序同时等待多个数据流。

驱动代码:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/kfifo.h>
#include <linux/wait.h>
#include <linux/poll.h>#define DEBUG_INFO(format, ...) printk("%s:%d -- "format"\n",\
__func__,__LINE__,##__VA_ARGS__)struct ch5_kfifo_struct{struct miscdevice misc;struct file_operations fops;struct kfifo fifo;char buf[64];char name[64];wait_queue_head_t read_queue;wait_queue_head_t write_queue;
};static int ch5_open (struct inode *inode, struct file *file){struct ch5_kfifo_struct *p = (struct ch5_kfifo_struct *)container_of(file->f_op,struct ch5_kfifo_struct,fops);file->private_data = p;DEBUG_INFO("major = %d, minor = %d\n",MAJOR(inode->i_rdev),MINOR(inode->i_rdev));DEBUG_INFO("name = %s",p->misc.name);return 0;
}static int ch5_release (struct inode *inode, struct file *file){DEBUG_INFO("close");return 0;
}static unsigned int ch5_poll(struct file *file, poll_table *wait){int mask = 0;struct ch5_kfifo_struct *p __attribute__((unused)) = (struct ch5_kfifo_struct *)file->private_data;DEBUG_INFO("begin wait:%s",p->name);poll_wait(file, &p->read_queue, wait);poll_wait(file, &p->write_queue, wait);DEBUG_INFO("poll:%s",p->name);if (!kfifo_is_empty(&p->fifo)){mask |= POLLIN | POLLRDNORM;DEBUG_INFO("POLLIN:%s",p->name);}if (!kfifo_is_full(&p->fifo)){mask |= POLLOUT | POLLWRNORM;DEBUG_INFO("POLLOUT:%s",p->name);}return mask;
}static ssize_t ch5_read (struct file *file, char __user *buf, size_t size, loff_t *pos){struct ch5_kfifo_struct *p __attribute__((unused)) = (struct ch5_kfifo_struct *)file->private_data;int ret;int actual_readed = 0;if(kfifo_is_empty(&p->fifo)){if(file->f_flags & O_NONBLOCK){DEBUG_INFO("kfifo is null");return -EAGAIN;}ret = wait_event_interruptible(p->read_queue,kfifo_is_empty(&p->fifo) == 0);if(ret){DEBUG_INFO("wait_event_interruptible error");return ret;}DEBUG_INFO("");}ret = kfifo_to_user(&p->fifo, buf, size, &actual_readed);if (ret){DEBUG_INFO("kfifo_to_user error");return -EIO;}DEBUG_INFO("size = %d,actual_readed = %d\n",size,actual_readed);if (!kfifo_is_full(&p->fifo)){wake_up_interruptible(&p->write_queue);}memset(p->buf,0,sizeof(p->buf));ret = copy_from_user(p->buf, buf, actual_readed);if(ret != 0){DEBUG_INFO("copy_from_user error ret = %d\n",ret);}else{DEBUG_INFO("read p->buf = %s\n",p->buf);}*pos = *pos + actual_readed;return actual_readed;
}
static ssize_t ch5_write (struct file *file, const char __user *buf, size_t size, loff_t* pos){struct ch5_kfifo_struct *p = (struct ch5_kfifo_struct *)file->private_data;int actual_writed = 0;int ret;if(kfifo_is_full(&p->fifo)){if(file->f_flags & O_NONBLOCK){DEBUG_INFO("kfifo is full");return -EAGAIN;}ret = wait_event_interruptible(p->write_queue, kfifo_is_full(&p->fifo) == 0);if(ret){DEBUG_INFO("wait_event_interruptible error");return ret;}DEBUG_INFO("");}ret = kfifo_from_user(&p->fifo, buf, size, &actual_writed);if (ret){DEBUG_INFO("kfifo_from_user error");return -EIO;}DEBUG_INFO("actual_writed = %d\n",actual_writed);if (!kfifo_is_empty(&p->fifo)){wake_up_interruptible(&p->read_queue);}memset(p->buf,0,sizeof(p->buf));ret = copy_from_user(p->buf, buf, actual_writed);if(ret != 0){DEBUG_INFO("copy_from_user error ret = %d\n",ret);}else{DEBUG_INFO("write:p->buf = %s\n",p->buf);}*pos = *pos + actual_writed;return actual_writed;
}struct ch5_kfifo_struct ch5_kfifo[8];
//  = {
//     .misc = { 
//         .name = "ch5-04-block",
//         .minor = MISC_DYNAMIC_MINOR,
//     },
//     .fops = {
//         .owner = THIS_MODULE,
//         .read = ch5_read,
//         .write = ch5_write,
//         .open = ch5_open,
//         .release = ch5_release,
//     },
// };static int __init ch5_init(void){int ret = 0;int i = 0;struct ch5_kfifo_struct *p;DEBUG_INFO("start init\n");for(i = 0;i < sizeof(ch5_kfifo)/sizeof(ch5_kfifo[0]);i++){p = &ch5_kfifo[i];snprintf(p->name,sizeof(p->name),"ch5-05-poll-%d",i);p->misc.name = p->name;p->misc.minor = MISC_DYNAMIC_MINOR;p->fops.owner = THIS_MODULE;p->fops.read = ch5_read;p->fops.write = ch5_write;p->fops.open = ch5_open;p->fops.release = ch5_release;p->fops.poll = ch5_poll;p->misc.fops = &p->fops;ret = kfifo_alloc(&p->fifo,8,GFP_KERNEL);if (ret) {DEBUG_INFO("kfifo_alloc error: %d\n", ret);ret = -ENOMEM;return ret;}DEBUG_INFO("kfifo_alloc size = %d",kfifo_avail(&p->fifo));init_waitqueue_head(&p->read_queue);init_waitqueue_head(&p->write_queue);ret = misc_register(&p->misc);if(ret < 0){DEBUG_INFO("misc_register error: %d\n", ret);return ret;}}DEBUG_INFO("misc_register ok");return 0;
}static void __exit ch5_exit(void){int i = 0;struct ch5_kfifo_struct *p;for(i = 0;i < sizeof(ch5_kfifo)/sizeof(ch5_kfifo[0]);i++){p = &ch5_kfifo[i];misc_deregister(&p->misc);kfifo_free(&p->fifo);}DEBUG_INFO("exit\n");
}module_init(ch5_init);
module_exit(ch5_exit);MODULE_LICENSE("GPL");

应用测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <linux/input.h>
#include <unistd.h>#define DEBUG_INFO(format, ...) printf("%s:%d -- "format"\n",\
__func__,__LINE__,##__VA_ARGS__)int main(int argc, char**argv){char bufs[8][1024];char name[8][1024];int fd[8];int i = 0;int ret;int len;struct pollfd fds[8];for(i = 0;i < 8;i++){memset(name[i], 0, sizeof(name[i]));snprintf(name[i], sizeof(name[i]),"/dev/ch5-05-poll-%d",i);fd[i] = open(name[i],O_RDONLY | O_NONBLOCK);if(fd[i] < 0){perror("open");DEBUG_INFO("open %s failed",name[i]);return -1;}fds[i].fd = fd[i];fds[i].events = POLLIN;fds[i].revents = 0;}DEBUG_INFO("start poll\n");while(1){ret = poll(fds,8,-1);if(ret < 0){perror("poll");return 0;}DEBUG_INFO("ret %d\n",ret);for(i = 0;i < 8;i++){if(fds[i].revents & POLLIN){while(1){memset(bufs[i],0,sizeof(bufs[i]));len = read(fd[i],(void*)&bufs[i][0],sizeof(bufs[i]));if(len <= 0){DEBUG_INFO("read %s finish",name[i]);break;}DEBUG_INFO("read %s :buf = %s",name[i],bufs[i]);}}}}return 0;
}

测试:

加载模块生成8个设备

 后台运行应用:

/mnt # ./app &
/mnt # [  519.185812] ch5_open:30 -- major = 10, minor = 58
[  519.185812] 
[  519.186175] ch5_open:31 -- name = ch5-05-poll-0
[  519.186849] ch5_open:30 -- major = 10, minor = 57
[  519.186849] 
[  519.187772] ch5_open:31 -- name = ch5-05-poll-1
[  519.190276] ch5_open:30 -- major = 10, minor = 56
[  519.190276] 
[  519.190553] ch5_open:31 -- name = ch5-05-poll-2
[  519.191129] ch5_open:30 -- major = 10, minor = 55
[  519.191129] 
[  519.191604] ch5_open:31 -- name = ch5-05-poll-3
[  519.192090] ch5_open:30 -- major = 10, minor = 54
[  519.192090] 
[  519.192283] ch5_open:31 -- name = ch5-05-poll-4
[  519.192759] ch5_open:30 -- major = 10, minor = 53
[  519.192759] 
[  519.193020] ch5_open:31 -- name = ch5-05-poll-5
[  519.193486] ch5_open:30 -- major = 10, minor = 52
[  519.193486] 
[  519.193677] ch5_open:31 -- name = ch5-05-poll-6
[  519.194148] ch5_open:30 -- major = 10, minor = 51
[  519.194148] 
[  519.194340] ch5_open:31 -- name = ch5-05-poll-7
main:38 -- start poll[  519.199679] ch5_poll:43 -- begin wait:ch5-05-poll-0
[  519.200029] ch5_poll:46 -- poll:ch5-05-poll-0
[  519.200236] ch5_poll:54 -- POLLOUT:ch5-05-poll-0
[  519.200358] ch5_poll:43 -- begin wait:ch5-05-poll-1
[  519.200598] ch5_poll:46 -- poll:ch5-05-poll-1
[  519.200770] ch5_poll:54 -- POLLOUT:ch5-05-poll-1
[  519.201213] ch5_poll:43 -- begin wait:ch5-05-poll-2
[  519.201531] ch5_poll:46 -- poll:ch5-05-poll-2
[  519.201646] ch5_poll:54 -- POLLOUT:ch5-05-poll-2
[  519.201727] ch5_poll:43 -- begin wait:ch5-05-poll-3
[  519.201847] ch5_poll:46 -- poll:ch5-05-poll-3
[  519.201998] ch5_poll:54 -- POLLOUT:ch5-05-poll-3
[  519.202154] ch5_poll:43 -- begin wait:ch5-05-poll-4
[  519.202347] ch5_poll:46 -- poll:ch5-05-poll-4
[  519.202504] ch5_poll:54 -- POLLOUT:ch5-05-poll-4
[  519.202661] ch5_poll:43 -- begin wait:ch5-05-poll-5
[  519.202850] ch5_poll:46 -- poll:ch5-05-poll-5
[  519.203122] ch5_poll:54 -- POLLOUT:ch5-05-poll-5
[  519.203276] ch5_poll:43 -- begin wait:ch5-05-poll-6
[  519.203490] ch5_poll:46 -- poll:ch5-05-poll-6
[  519.203643] ch5_poll:54 -- POLLOUT:ch5-05-poll-6
[  519.203798] ch5_poll:43 -- begin wait:ch5-05-poll-7
[  519.203964] ch5_poll:46 -- poll:ch5-05-poll-7
[  519.204109] ch5_poll:54 -- POLLOUT:ch5-05-poll-7

 写数据

/mnt # echo "hello world" > /dev/ch5-05-poll-0 
[  576.205375] ch5_open:30 -- major = 10, minor = 58
[  576.205375] 
[  576.206863] ch5_open:31 -- name = ch5-05-poll-0
[  576.208285] ch5_write:122 -- actual_writed = 8
[  576.208285] 
[  576.208757] ch5_write:132 -- write:p->buf = hello wo
[  576.208757] 
[  576.209448] ch5_poll:43 -- begin wait:ch5-05-poll-0
[  576.209675] ch5_poll:46 -- poll:ch5-05-poll-0
[  576.209874] ch5_poll:49 -- POLLIN:ch5-05-poll-0
[  576.210058] ch5_poll:43 -- begin wait:ch5-05-poll-1
[  576.210291] ch5_poll:46 -- poll:ch5-05-poll-1
[  576.210451] ch5_poll:54 -- POLLOUT:ch5-05-poll-1
[  576.210645] ch5_poll:43 -- begin wait:ch5-05-poll-2
[  576.211496] ch5_poll:46 -- poll:ch5-05-poll-2
[  576.212140] ch5_poll:54 -- POLLOUT:ch5-05-poll-2
[  576.212315] ch5_poll:43 -- begin wait:ch5-05-poll-3
[  576.212517] ch5_poll:46 -- poll:ch5-05-poll-3
[  576.212707] ch5_poll:54 -- POLLOUT:ch5-05-poll-3
[  576.212928] ch5_poll:43 -- begin wait:ch5-05-poll-4
[  576.213169] ch5_poll:46 -- poll:ch5-05-poll-4
[  576.213333] ch5_poll:54 -- POLLOUT:ch5-05-poll-4
[  576.213515] ch5_poll:43 -- begin wait:ch5-05-poll-5
[  576.213752] ch5_poll:46 -- poll:ch5-05-poll-5
[  576.213869] ch5_poll:54 -- POLLOUT:ch5-05-poll-5
[  576.214067] ch5_poll:43 -- begin wait:ch5-05-poll-6
[  576.214238] ch5_poll:46 -- poll:ch5-05-poll-6
[  576.214392] ch5_poll:54 -- POLLOUT:ch5-05-poll-6
[  576.214545] ch5_poll:43 -- begin wait:ch5-05-poll-7
[  576.214963] ch5_poll:46 -- poll:ch5-05-poll-7
[  576.215300] ch5_poll:54 -- POLLOUT:ch5-05-poll-7
main:45 -- ret 1
[  576.216522] ch5_read:84 -- size = 1024,actual_readed = 8
[  576.216522] 
[  576.216920] ch5_read:95 -- read p->buf = hello wo
[  576.216920] 
[  576.217219] ch5_write:114 -- 
main:55 -- read /dev/ch5-05-poll-0 :buf = hello wo
[  576.217652] ch5_write:122 -- actual_writed = 4
[  576.217652] 
[  576.217989] ch5_write:132 -- write:p->buf = rld
[  576.217989] 
[  576.217989] 
main:55 -- read /dev/ch5-05-poll-0 :buf = rld[  576.218140] ch5_read:84 -- size = 1024,actual_readed = 4
[  576.218140] [  576.218294] ch5_read:95 -- read p->buf = rld
[  576.218294] 
[  576.218294] [  576.219434] ch5_read:67 -- kfifo is null
main:52 -- read /dev/ch5-05-poll-0 finish[  576.220169] ch5_release:36 -- close[  576.220874] ch5_poll:43 -- begin wait:ch5-05-poll-0
[  576.221959] ch5_poll:46 -- poll:ch5-05-poll-0
[  576.222639] ch5_poll:54 -- POLLOUT:ch5-05-poll-0
[  576.224333] ch5_poll:43 -- begin wait:ch5-05-poll-1
[  576.225068] ch5_poll:46 -- poll:ch5-05-poll-1
[  576.225443] ch5_poll:54 -- POLLOUT:ch5-05-poll-1
[  576.225890] ch5_poll:43 -- begin wait:ch5-05-poll-2
[  576.226298] ch5_poll:46 -- poll:ch5-05-poll-2
[  576.226829] ch5_poll:54 -- POLLOUT:ch5-05-poll-2
[  576.227435] ch5_poll:43 -- begin wait:ch5-05-poll-3
/mnt # [  576.227639] ch5_poll:46 -- poll:ch5-05-poll-3
[  576.227892] ch5_poll:54 -- POLLOUT:ch5-05-poll-3
[  576.228124] ch5_poll:43 -- begin wait:ch5-05-poll-4
[  576.228344] ch5_poll:46 -- poll:ch5-05-poll-4
[  576.228573] ch5_poll:54 -- POLLOUT:ch5-05-poll-4
[  576.228902] ch5_poll:43 -- begin wait:ch5-05-poll-5
[  576.229155] ch5_poll:46 -- poll:ch5-05-poll-5
[  576.229349] ch5_poll:54 -- POLLOUT:ch5-05-poll-5
[  576.229573] ch5_poll:43 -- begin wait:ch5-05-poll-6
[  576.229761] ch5_poll:46 -- poll:ch5-05-poll-6
[  576.230005] ch5_poll:54 -- POLLOUT:ch5-05-poll-6
[  576.230233] ch5_poll:43 -- begin wait:ch5-05-poll-7
[  576.230421] ch5_poll:46 -- poll:ch5-05-poll-7
[  576.231095] ch5_poll:54 -- POLLOUT:ch5-05-poll-7

小结

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

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

相关文章

如何让PPT看起来规整统一

一、字体 常见问题&#xff1a;字体风格太多、文字可读性差、页面风格不匹配 1.使用文字的几个原则 &#xff08;1&#xff09;一份PPT最多使用两种中文字体 比如首页大标题宋体、正文黑体、其他页标题黑体加粗。通过粗细、字号、不同颜色背景等区分不同层级。注意 使用粗体…

【React学习】—jsx语法规则(三)

【React学习】—jsx语法规则&#xff08;三&#xff09; 一、jsx语法规则&#xff1a; 1、定义虚拟DOM&#xff0c;不要写引号&#xff0c; 2、标签中混入JS表达式要用{} 3、样式的类名指定不要用class&#xff0c;要用className 4、内联样式&#xff0c;要用style{{key:value}…

AWS中Lambda集成SNS

1.创建Lambda 在Lambda中&#xff0c;创建名为AWSSNSDemo的函数 use strict console.log(loading function); var aws require(aws-sdk); var docClient new aws.DynamoDB.DocumentClient(); aws.config.regionap-southeast-1;exports.handler function(event,context,cal…

一台电脑B用网线共享另外一台电脑A的WiFi网络,局域网其它电脑C怎么访问电脑B服务

环境: 电脑A:联想E14笔记本 系统:WIN10 专业版 局域网IP:192.168.14.111 共享IP:192.168.137.1 电脑B:HP 288pro 台式机 Ubuntu20.04 系统:共享IP:192.168.137.180 电脑A正常连接WIFI,电脑B没有WIFI只有,有线网口,共享电脑A的无线网 (还有一种桥接网络不在本…

pdf怎么转换成jpg图片?这几个转换方法了解一下

pdf怎么转换成jpg图片&#xff1f;转换PDF文件为JPG图片格式在现代工作中是非常常见的需求&#xff0c;比如将PDF文件中的图表、表格或者图片转换为JPG格式后使用在PPT演示、网页设计等场景中。 【迅捷PDF转换器】是一款非常实用的工具&#xff0c;可以将PDF文件转换成多种不同…

创建CREATE_STAT_TABLE 统计信息表在达梦和oracle中的使用

达梦 创建CREATE_STAT_TABLE 统计信息表 PROCEDURE CREATE_STAT_TABLE ( STATOWN VARCHAR(128), STATTAB VARCHAR(128), TABLESPACE VARCHAR(128) DEFAULT NULL, GLOBAL_TEMPORARY BOOLEAN DEFAULT FALSE ); 创建普通表的对应系统表的列名字段包括以下&#xff1a; OWNER TABL…

C 语言的逻辑运算符

C 语言的逻辑运算符包括三种&#xff1a; 逻辑运算符可以将两个关系表达式连接起来. Suppose exp1 and exp2 are two simple relational expressions, such as cat > rat and debt 1000 . Then you can state the following: ■ exp1 && exp2 is true only if bo…

通讯协议035——全网独有的OPC HDA知识一之聚合(四)平均值

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…

计算机基础知识一

1、计算机系统组成 1.1 硬件 CPU&#xff1a;中央处理器、计算机核心部件、负责计算任务 内存&#xff1a;记忆功能、存储二进制数&#xff0c;内存是一个字节一个地址。 内存大小换算&#xff1a; 8 bits 1 Byte 1024 Bytes Bytes 1 KB &#xff0c; 1024 KB KB 1 …

java 企业工程管理系统软件源码 自主研发 工程行业适用 em

​ 工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

文盘 Rust -- tokio 绑定 cpu 实践

tokio 是 rust 生态中流行的异步运行时框架。在实际生产中我们如果希望 tokio 应用程序与特定的 cpu core 绑定该怎么处理呢&#xff1f;这次我们来聊聊这个话题。 首先我们先写一段简单的多任务程序。 use tokio::runtime; pub fn main() {let rt runtime::Builder::new_mu…

【Github】Uptime Kuma:自托管监控工具的完美选择

简介&#xff1a; Uptime Kuma 是一款强大的自托管监控工具&#xff0c;通过简单的部署和配置&#xff0c;可以帮助你监控服务器、VPS 和其他网络服务的在线状态。相比于其他类似工具&#xff0c;Uptime Kuma 提供更多的灵活性和自由度。本文将介绍 Uptime Kuma 的功能、如何使…

Redux中reducer 中为什么每次都要返回新的state!!!

Redux中reducer 中为什么每次都要返回新的state&#xff01;&#xff01;&#xff01; 最近在学习react相关的知识&#xff0c;学习redux的时候遇到看到一个面试题&#xff1a; 如果Redux没返回新的数据会怎样&#xff1f; 这就是要去纠结为什么编写reducer得时候为什么不允许直…

服装行业多模态算法个性化产品定制方案 | 京东云技术团队

一、项目背景 AI赋能服装设计师&#xff0c;设计好看、好穿、好卖的服装 传统服装行业痛点 • 设计师无法准确捕捉市场趋势&#xff0c;抓住中国潮流 • 上新周期长&#xff0c;高库存滞销风险大 • 基本款居多&#xff0c;难以满足消费者个性化需求 解决方案 • GPT数据…

Python数据分析实战-dataframe指定多列去重(附源码和实现效果)

实现功能 Python数据分析实战-利用df.drop_duplicates(subset[,])对dataframe指定多列去重 实现代码 import pandas as pddata{state:[1,1,2,2,1,2,2],pop:[a,b,c,d,b,c,d]} framepd.DataFrame(data)frameframe.drop_duplicates(subset[pop,state]) print(frame) 实现效果 本…

软件测试工程师面试如何描述自动化测试是怎么实现的?

软件测试工程师面试的时候&#xff0c;但凡简历中有透露一点点自己会自动化测试的技能点的描述&#xff0c;都会被面试官问&#xff0c;那你结合你的测试项目说说自动化测试是怎么实现的&#xff1f;一到这里&#xff0c;很多网友&#xff0c;包括我的学生&#xff0c;也都一脸…

8月9日上课内容 nginx负载均衡

负载均衡工作当中用的很多的&#xff0c;也是面试会问的很重要的一个点 负载均衡&#xff1a;通过反向代理来实现&#xff08;nginx只有反向代理才能做负载均衡&#xff09; 正向代理的配置方法&#xff08;用的较少&#xff09; 反向代理的方式&#xff1a;四层代理与七层代…

使用chatGPT-4 畅聊量子物理学

与chatGPT深入研究起源、基本概念&#xff0c;以及海森堡、德布罗意、薛定谔、玻尔、爱因斯坦和狄拉克如何得出他们的想法和方程。 1965 年&#xff0c;费曼&#xff08;左&#xff09;与朱利安施温格&#xff08;未显示&#xff09;和朝永信一郎&#xff08;右&#xff09;分享…

C 语言的 ctype.h 头文件

C 语言的 ctype.h 头文件包含了很多字符函数的函数原型, 可以专门用来处理一个字符, 这些函数都以一个字符作为实参. ctype.h 中的字符测试函数如表所示: 这些测试函数返回 0 或 1, 即 false 或 true. ctype.h 中的字符映射函数如表所示: 字符测试函数不会修改原始实参, 只会…

Python入门02

0目录 1.容器操作&#xff08;序列操作&#xff09; 2.函数 3.模块 1.容器操作&#xff08;序列操作&#xff09; 列表的基本操作 定义一个列表[] 访问列表&#xff08;打印或者通过下标和索引&#xff09; 新增元素 Append(在末尾) 指定位置新增元素 Insert 删除&…