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是要监听的文件描述符集合,类型为指向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…...
大数计算(大数加法/大数乘法)
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...
【腾讯云 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 费马平方和定理
👨🏫 Rikka with Square Numbers 🧀 参考题解 🍻 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配置项传递数据(适用于父组件给子组件传递数据) 父组件向子组件传递数据: 父组件代码:在子组件的标签中传递数据 <template><div><h2>学校名称:{{schoolName}}</h2><!-- 方…...
《2023年中国企业数字化转型发展白皮书》发布
导读 本报告主要采用市场调查、行业深度访谈、桌面研究等方法,并使用艾媒咨询旗下各大数据计算系统和相关计算模型。 对部分相关的公开信息进行筛选,通过对行业专家、相关企业与网民进行深度访谈,了解相关行业主要情况,获得相应…...
基于Python 简易实现接口测试自动化
目录 实现思路 统筹脚本 请求封装 日志封装 结果比对 结果邮件 用例获取及数据格式化 请求url转换 测试用例excel结构 测试报告 邮件接收结果 资料获取方法 实现思路 使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志&…...
创建线程、线程的挂起与恢复、线程的优先级与终止线程
目录 一、创建线程 CreateThread函数: 下面是示例: 编辑 ThreadProc函数解释: DWORD的本质是 unsigned long PVOID的本质是 void* 二、线程的终止 1.WaitForSingleObject()函数: 示例如下: 2.ExitThread()函…...
[保研/考研机试] KY180 堆栈的使用 吉林大学复试上机题 C++实现
题目链接: 堆栈的使用_牛客题霸_牛客网 描述 堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。其中 push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。 输入描述: 对于…...
【AI理论学习】手把手推导扩散模型:Diffusion Models(DDPM)
手把手推导扩散模型:Diffusion Models(DDPM) DDPM理论回顾前置知识过程详解Forward ProcessReverse Process DDPM算法伪代码训练部分采样部分 总结一下 参考链接 在这篇博客文章中,我们将深入研究 去噪扩散概率模型(也称为 DDPM&…...
智能汽车 论坛收集
1.焉知汽车 焉知汽车 2.智能汽车俱乐部 智能汽车资源网 - 智能表面,智能内饰,新能源汽车,HMI,人车交互,智能车灯,车用材料 3.行业报告 发现报告 - 专业研报平台丨收录海量行业报告、券商研报丨免费分享…...
24届近5年南京航空航天大学自动化考研院校分析
今天给大家带来的是南京航空航天大学控制考研分析 满满干货~还不快快点赞收藏 一、南京航空航天大学 学校简介 南京航空航天大学创建于1952年10月,是新中国自己创办的第一批航空高等院校之一。1978年被国务院确定为全国重点大学;1981年经…...
Linux Day07
一、僵死进程 1.1僵死进程产生的原因 子进程先于父进程结束, 而父进程没有获取子进程退出码,释放子进程占用的资源,此时子进程将成为一个僵死进程。 在第一个框这里时父进程子进程都没有结束,显示其pid 父进程是2349,子进程是235…...
数字化管理,让MRO工业品更高效
MRO商品数字化是将MRO商品的采购、库存及记录过程进行数字化管理,以提高MRO商品的效率和可控性。MRO(Maintenance, Repair and Operations)一般用于维修、保养及日常运营工作中,包括五金工具、紧固件、精加工刀具、备品备件、切屑…...
layui中渲染table表格
页面布局 可直接根据文档要求去写 table 组件(这个不重要) <table lay-filter"SyDictTable" id"SyDictTable" lay-data"{id: SyDictTable}"></table>Js 重要的是去修改JS里面的东西,比如&#…...
2023-08-10LeetCode每日一题(下降路径最小和 II)
2023-08-10每日一题 一、题目编号 1289. 下降路径最小和 II二、题目链接 点击跳转到题目位置 三、题目描述 给你一个 n x n 整数矩阵 grid ,请你返回 非零偏移下降路径 数字和的最小值。 非零偏移下降路径 定义为:从 grid 数组中的每一行选择一个数…...
网络基础2(HTTP,HTTPS,传输层协议详解)
再谈协议 在之前利用套接字进行通信的时候,我们都是利用 “字符串” 进行流式的发送接收,但是我们平常进行交流通信肯定不能只是简单的发送字符串。 比如我们用QQ进行聊天,我们不仅需要得到对方发送的消息,还要知道对方的昵称&…...
Java实现籍贯级联选择器
在工作中要求写一个籍贯的级联选择器,记录一下自己写这个级联选择器的过程,因为自己才刚开始工作,有很多地方都没有考虑的很清楚,希望各位大佬能给出建议。 一、需求 A:正常的23个省,籍贯由“省区/县/市”组成…...
每日一学——OSI参考模型
OSI参考模型(Open Systems Interconnection Reference Model)是国际标准化组织(ISO)制定的一个网络通信协议的概念框架。它将网络通信划分为七个层次,每个层次负责不同的功能和任务,从物理层到应用层依次为…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
