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

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

小结

相关文章:

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

基础知识 poll和select方法在Linux用户空间的API接口函数定义如下。 int poll(struct pollfd *fds, nfds_t nfds, int timeout); poll()函数的第一个参数fds是要监听的文件描述符集合&#xff0c;类型为指向struct pollfd的指针。struct pollfd数据结构定义如下。 struct poll…...

SpringBoot系列---【使用jasypt把配置文件密码加密】

使用jasypt把配置文件密码加密 1.引入pom坐标 <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version> </dependency> 2.新增jasypt配置 2.1…...

大数计算(大数加法/大数乘法)

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…...

【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio构建React完成点餐H5页面

前言 【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio 构建React完成点餐H5页面一、Cloud Studio介绍1.1 Cloud Studio 是什么1.2 相关链接1.3 登录注册 二、实战练习2.1 初始化工作空间2.2 开发一个简版的点餐系统页面1. 安装 antd-mobile2. 安装 less 和 less-loader3. …...

杭电多校 Rikka with Square Numbers 费马平方和定理

&#x1f468;‍&#x1f3eb; Rikka with Square Numbers &#x1f9c0; 参考题解 &#x1f37b; AC code import java.util.Scanner;public class Main {static boolean isSqu(int x){int t (int) Math.sqrt(x);return t * t x;}public static void main(String[] args…...

跟禹神VUE——组件间的通信方式(props配置项、组件间自定义事件、全局事件总线、消息订阅与发布、VUEX)

一、通过props配置项传递数据&#xff08;适用于父组件给子组件传递数据&#xff09; 父组件向子组件传递数据&#xff1a; 父组件代码&#xff1a;在子组件的标签中传递数据 <template><div><h2>学校名称&#xff1a;{{schoolName}}</h2><!-- 方…...

《2023年中国企业数字化转型发展白皮书》发布

导读 本报告主要采用市场调查、行业深度访谈、桌面研究等方法&#xff0c;并使用艾媒咨询旗下各大数据计算系统和相关计算模型。 对部分相关的公开信息进行筛选&#xff0c;通过对行业专家、相关企业与网民进行深度访谈&#xff0c;了解相关行业主要情况&#xff0c;获得相应…...

基于Python 简易实现接口测试自动化

目录 实现思路 统筹脚本 请求封装 日志封装 结果比对 结果邮件 用例获取及数据格式化 请求url转换 测试用例excel结构 测试报告 邮件接收结果 资料获取方法 实现思路 使用excel管理用例用例信息&#xff0c;requests模块发送http请求&#xff0c;实现了记录日志&…...

创建线程、线程的挂起与恢复、线程的优先级与终止线程

目录 一、创建线程 CreateThread函数&#xff1a; 下面是示例&#xff1a; ​编辑 ThreadProc函数解释&#xff1a; DWORD的本质是 unsigned long PVOID的本质是 void* 二、线程的终止 1.WaitForSingleObject()函数&#xff1a; 示例如下&#xff1a; 2.ExitThread()函…...

[保研/考研机试] KY180 堆栈的使用 吉林大学复试上机题 C++实现

题目链接&#xff1a; 堆栈的使用_牛客题霸_牛客网 描述 堆栈是一种基本的数据结构。堆栈具有两种基本操作方式&#xff0c;push 和 pop。其中 push一个值会将其压入栈顶&#xff0c;而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。 输入描述&#xff1a; 对于…...

【AI理论学习】手把手推导扩散模型:Diffusion Models(DDPM)

手把手推导扩散模型&#xff1a;Diffusion Models&#xff08;DDPM&#xff09; DDPM理论回顾前置知识过程详解Forward ProcessReverse Process DDPM算法伪代码训练部分采样部分 总结一下 参考链接 在这篇博客文章中&#xff0c;我们将深入研究 去噪扩散概率模型(也称为 DDPM&…...

智能汽车 论坛收集

1.焉知汽车 焉知汽车 2.智能汽车俱乐部 智能汽车资源网 - 智能表面&#xff0c;智能内饰&#xff0c;新能源汽车&#xff0c;HMI&#xff0c;人车交互&#xff0c;智能车灯&#xff0c;车用材料 3.行业报告 发现报告 - 专业研报平台丨收录海量行业报告、券商研报丨免费分享…...

24届近5年南京航空航天大学自动化考研院校分析

今天给大家带来的是南京航空航天大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、南京航空航天大学 学校简介 南京航空航天大学创建于1952年10月&#xff0c;是新中国自己创办的第一批航空高等院校之一。1978年被国务院确定为全国重点大学&#xff1b;1981年经…...

Linux Day07

一、僵死进程 1.1僵死进程产生的原因 子进程先于父进程结束, 而父进程没有获取子进程退出码&#xff0c;释放子进程占用的资源&#xff0c;此时子进程将成为一个僵死进程。 在第一个框这里时父进程子进程都没有结束&#xff0c;显示其pid 父进程是2349&#xff0c;子进程是235…...

数字化管理,让MRO工业品更高效

MRO商品数字化是将MRO商品的采购、库存及记录过程进行数字化管理&#xff0c;以提高MRO商品的效率和可控性。MRO&#xff08;Maintenance, Repair and Operations&#xff09;一般用于维修、保养及日常运营工作中&#xff0c;包括五金工具、紧固件、精加工刀具、备品备件、切屑…...

layui中渲染table表格

页面布局 可直接根据文档要求去写 table 组件&#xff08;这个不重要&#xff09; <table lay-filter"SyDictTable" id"SyDictTable" lay-data"{id: SyDictTable}"></table>Js 重要的是去修改JS里面的东西&#xff0c;比如&#…...

2023-08-10LeetCode每日一题(下降路径最小和 II)

2023-08-10每日一题 一、题目编号 1289. 下降路径最小和 II二、题目链接 点击跳转到题目位置 三、题目描述 给你一个 n x n 整数矩阵 grid &#xff0c;请你返回 非零偏移下降路径 数字和的最小值。 非零偏移下降路径 定义为&#xff1a;从 grid 数组中的每一行选择一个数…...

网络基础2(HTTP,HTTPS,传输层协议详解)

再谈协议 在之前利用套接字进行通信的时候&#xff0c;我们都是利用 “字符串” 进行流式的发送接收&#xff0c;但是我们平常进行交流通信肯定不能只是简单的发送字符串。 比如我们用QQ进行聊天&#xff0c;我们不仅需要得到对方发送的消息&#xff0c;还要知道对方的昵称&…...

Java实现籍贯级联选择器

在工作中要求写一个籍贯的级联选择器&#xff0c;记录一下自己写这个级联选择器的过程&#xff0c;因为自己才刚开始工作&#xff0c;有很多地方都没有考虑的很清楚&#xff0c;希望各位大佬能给出建议。 一、需求 A:正常的23个省&#xff0c;籍贯由“省区/县/市”组成&#xf…...

每日一学——OSI参考模型

OSI参考模型&#xff08;Open Systems Interconnection Reference Model&#xff09;是国际标准化组织&#xff08;ISO&#xff09;制定的一个网络通信协议的概念框架。它将网络通信划分为七个层次&#xff0c;每个层次负责不同的功能和任务&#xff0c;从物理层到应用层依次为…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...