/* * $Id: usbip_common.c 66 2008-04-20 13:19:42Z hirofuchi $ * * Copyright (C) 2003-2008 Takahiro Hirofuchi * * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ /* 提供的外部接口 usbip_debug_flag 调式的flag,用来决定输入哪些调式信息 usbip_debug 用于修改和打印usbip_debug_flag值 usbip_dump_urb 用户打印urb的内容 usbip_dump_header用于打印usbip_header内容 usbip_start_threads 开启 usbip_device 的接收和发送线程 usbip_stop_threads 停止 usbip_device 的接收和发送线程 usbip_task_init 初始化usbip_task结构体 usbip_xmit 接收和发送TCP包 sockfd_to_socket 将sockfd获得对应的socket对象 usbip_pack_pdu 对pdu和urb进行解压包,即urb和pdu字段之间的相互赋值 usbip_header_correct_endian usbip_header 在网络编码和主机编码之间的转换 usbip_alloc_iso_desc_pdu pdu中的iso的处理,完成urb和pdu之间对iso_desc的信息相互赋值 usbip_recv_iso 接收urb包中的iso_frame_desc数据 usbip_recv_xbuff 接收urb包中的缓存取数据,接收urb->transfer_buffer */ #include <linux/kernel.h> #include <linux/file.h> #include <linux/tcp.h> #include <linux/in.h> #include "usbip_common.h" /* version information */ #define DRIVER_VERSION "$Id: usbip_common.c 66 2008-04-20 13:19:42Z hirofuchi $" #define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi _at_ users.sourceforge.net>" #define DRIVER_DESC "usbip common driver" /*-------------------------------------------------------------------------*/ /* debug routines */ #ifdef CONFIG_USB_DEBUG unsigned long usbip_debug_flag = 0xffffffff; #else unsigned long usbip_debug_flag = 0; #endif EXPORT_SYMBOL(usbip_debug_flag); /* FIXME */ struct device_attribute dev_attr_usbip_debug; EXPORT_SYMBOL(dev_attr_usbip_debug); static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%lx\n", usbip_debug_flag); } static ssize_t store_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long flag; sscanf(buf, "%lx", &flag); usbip_debug_flag = flag; return count; } DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag); static void usbip_dump_buffer(char *buff, int bufflen) { } static void usbip_dump_pipe(unsigned int p) { } static void usbip_dump_usb_device(struct usb_device *dev) { } static void usbip_dump_request_type(__u8 rt) { } static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) { } void usbip_dump_urb (struct urb *purb) { } EXPORT_SYMBOL(usbip_dump_urb); void usbip_dump_header(struct usbip_header *pdu) { } EXPORT_SYMBOL(usbip_dump_header); /*-------------------------------------------------------------------------*/ /* thread routines */ //param为usbip_task //将进程后台化,允许信号SIGKILL,将当前进程赋予ut->thread,执行 //usbip_task中loop函数,并complete(ut->thread_done),通知ut已经完成启动 //等待loop函数因返回结束,complete_and_exit(ut->thread_done) int usbip_thread(void *param) { struct usbip_task *ut = (struct usbip_task *) param; if (!ut) return -EINVAL; lock_kernel();//禁止内核的调度 daemonize(ut->name);//进程后台化 allow_signal(SIGKILL);//允许SIGKILL信号的捕捉 ut->thread = current;//对ut->thread进行复制,保存当前进行 unlock_kernel();//解禁内核的调度 /* srv.rb must wait for rx_thread starting */ complete(&ut->thread_done);//通知执行完成 /* start of while loop */ ut->loop_ops(ut); /* end of loop */ ut->thread = NULL; complete_and_exit(&ut->thread_done, 0);//通知usbip_stop_threads中对应的tcp_rx和tcp_tx } //参数usbip_device //启动ud->tcp_rx和ur-tcp_tx这两个接收和发送独立线程,并等待usbip_thread的complete信号 void usbip_start_threads(struct usbip_device *ud) { /* * threads are invoked per one device (per one connection). */ kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0); kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0); /* confirm threads are starting */ wait_for_completion(&ud->tcp_rx.thread_done); wait_for_completion(&ud->tcp_tx.thread_done); } EXPORT_SYMBOL(usbip_start_threads); //参数usbip_device //停止接收和发送两个线程 void usbip_stop_threads(struct usbip_device *ud) { /* kill threads related to this sdev, if v.c. exists */ if (ud->tcp_rx.thread != NULL) { send_sig(SIGKILL, ud->tcp_rx.thread, 1); wait_for_completion(&ud->tcp_rx.thread_done); udbg("rx_thread for ud %p has finished\n", ud); } if (ud->tcp_tx.thread != NULL) { //在usbip_thread中支持allow_signal(SIGKILL)信号 //发送SIGKILL中后,[vhci|stub]_rx_loop中的signal_pending捕获到信号,然后退出循环 send_sig(SIGKILL, ud->tcp_tx.thread, 1); wait_for_completion(&ud->tcp_tx.thread_done);//与usbip_thread中的最后一行complete_and_exit对应 udbg("tx_thread for ud %p has finished\n", ud); } } EXPORT_SYMBOL(usbip_stop_threads); //初始化usbip_task相关属性 void usbip_task_init(struct usbip_task *ut, char *name, void (*loop_ops)(struct usbip_task *)) { ut->thread = NULL; init_completion(&ut->thread_done); ut->name = name; ut->loop_ops = loop_ops; } EXPORT_SYMBOL(usbip_task_init); /*-------------------------------------------------------------------------*/ /* socket routines */ //接收和发送buf,接收和发送通过msg_flags来判断方向 /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) { int result; struct msghdr msg; struct kvec iov; int total = 0; /* for blocks of if (dbg_flag_xmit) */ char *bp = buf; int osize= size; dbg_xmit("enter\n"); if (!sock || !buf || !size) { uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", sock, buf, size); return -EINVAL; } if (dbg_flag_xmit) { if (send) { if (!in_interrupt()) printk(KERN_DEBUG "%-10s:", current->comm); else printk(KERN_DEBUG "interupt :"); printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", sock, buf, size, msg_flags); usbip_dump_buffer(buf, size); } } do { sock->sk->sk_allocation = GFP_NOIO; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_namelen = 0; msg.msg_flags = msg_flags | MSG_NOSIGNAL; if (send) result = kernel_sendmsg(sock, &msg, &iov, 1, size); else result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); if (result <= 0) { udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", send ? "send" : "receive", sock, buf, size, result, total); goto err; } size -= result; buf += result; total += result; } while (size > 0); if (dbg_flag_xmit) { if (!send) { if (!in_interrupt()) printk(KERN_DEBUG "%-10s:", current->comm); else printk(KERN_DEBUG "interupt :"); printk("usbip_xmit: receiving....\n"); usbip_dump_buffer(bp, osize); printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", osize, result, size, total); } if (send) { printk("usbip_xmit: send, total %d\n", total); } } return total; err: return result; } EXPORT_SYMBOL(usbip_xmit); //以下四个函数,现在已经移到用户空间程序处理 /* now a usrland utility should set options. */ #if 0 int setquickack(struct socket *socket) { mm_segment_t oldfs; int val = 1; int ret; oldfs = get_fs(); set_fs(get_ds()); ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, (char __user *) &val, sizeof(ret)); set_fs(oldfs); return ret; } int setnodelay(struct socket *socket) { mm_segment_t oldfs; int val = 1; int ret; oldfs = get_fs(); set_fs(get_ds()); ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, (char __user *) &val, sizeof(ret)); set_fs(oldfs); return ret; } int setkeepalive(struct socket *socket) { mm_segment_t oldfs; int val = 1; int ret; oldfs = get_fs(); set_fs(get_ds()); ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char __user *) &val, sizeof(ret)); set_fs(oldfs); return ret; } void setreuse(struct socket *socket) { socket->sk->sk_reuse = 1; } #endif //参数 uint sockfd //根据sockfd,获取file对象,然后根据file对象,获取inode,调用SOCKET_I(inode)返回socke对象 struct socket *sockfd_to_socket(unsigned int sockfd) { struct socket *socket; struct file *file; struct inode *inode; file = fget(sockfd); if (!file) { uerr("invalid sockfd\n"); return NULL; } //获取file的inode值 inode = file->f_dentry->d_inode; if (!inode || !S_ISSOCK(inode->i_mode)) return NULL; //根据inode值获取socket对象 socket = SOCKET_I(inode); return socket; } EXPORT_SYMBOL(sockfd_to_socket); /*-------------------------------------------------------------------------*/ /* pdu routines */ //去除flags中本驱动不支持的标签,主要去除URB_NO_TRANSFER_DMA_MAP、URB_NO_SETUP_DMA_MAP /* there may be more cases to tweak the flags. */ static unsigned int tweak_transfer_flags(unsigned int flags) { if (flags & URB_NO_TRANSFER_DMA_MAP) /* * vhci_hcd does not provide DMA-mapped I/O. The upper * driver does not need to set this flag. The remote * usbip.ko does not still perform DMA-mapped I/O for * DMA-caplable host controllers. So, clear this flag. */ flags &= ~URB_NO_TRANSFER_DMA_MAP; if (flags & URB_NO_SETUP_DMA_MAP) flags &= ~URB_NO_SETUP_DMA_MAP; return flags; } //针对cmd命令,根据pack确定打包方向,将urb和pdu中的信息进行同步,完成相互复制 static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) { struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; /* * Some members are not still implemented in usbip. I hope this issue * will be discussed when usbip is ported to other operating systems. */ if (pack) { /* vhci_tx.c */ spdu->transfer_flags = tweak_transfer_flags(urb->transfer_flags); spdu->transfer_buffer_length = urb->transfer_buffer_length; spdu->start_frame = urb->start_frame; spdu->number_of_packets = urb->number_of_packets; spdu->interval = urb->interval; } else { /* stub_rx.c */ urb->transfer_flags = spdu->transfer_flags; urb->transfer_buffer_length = spdu->transfer_buffer_length; urb->start_frame = spdu->start_frame; urb->number_of_packets = spdu->number_of_packets; urb->interval = spdu->interval; } } //针对ret命令,根据pack确定打包方向,将urb和pdu中的信息进行同步,完成相互复制 static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack) { struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; if (pack) { /* stub_tx.c */ rpdu->status = urb->status; rpdu->actual_length = urb->actual_length; rpdu->start_frame = urb->start_frame; rpdu->error_count = urb->error_count; } else { /* vhci_rx.c */ urb->status = rpdu->status; urb->actual_length = rpdu->actual_length; urb->start_frame = rpdu->start_frame; urb->error_count = rpdu->error_count; } } //根据cmd命令类型和pack打包方向,对pdu和urb进行打包赋值 //调用usbip_pack_cmd_submit和usbip_pack_ret_submit void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack) { switch(cmd) { case USBIP_CMD_SUBMIT: usbip_pack_cmd_submit(pdu, urb, pack); break; case USBIP_RET_SUBMIT: usbip_pack_ret_submit(pdu, urb, pack); break; default: err("unknown command"); /* NOTREACHED */ //BUG(); } } EXPORT_SYMBOL(usbip_pack_pdu); //大小端编码问题,send代码转换方向 static void correct_endian_basic(struct usbip_header_basic *base, int send) { if (send) { base->command = cpu_to_be32(base->command); base->seqnum = cpu_to_be32(base->seqnum); base->devid = cpu_to_be32(base->devid); base->direction = cpu_to_be32(base->direction); base->ep = cpu_to_be32(base->ep); } else { base->command = be32_to_cpu(base->command); base->seqnum = be32_to_cpu(base->seqnum); base->devid = be32_to_cpu(base->devid); base->direction = be32_to_cpu(base->direction); base->ep = be32_to_cpu(base->ep); } } static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send) { if (send) { pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); cpu_to_be32s(&pdu->transfer_buffer_length); cpu_to_be32s(&pdu->start_frame); cpu_to_be32s(&pdu->number_of_packets); cpu_to_be32s(&pdu->interval); } else { pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); be32_to_cpus(&pdu->transfer_buffer_length); be32_to_cpus(&pdu->start_frame); be32_to_cpus(&pdu->number_of_packets); be32_to_cpus(&pdu->interval); } } static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send) { if (send) { cpu_to_be32s(&pdu->status); cpu_to_be32s(&pdu->actual_length); cpu_to_be32s(&pdu->start_frame); cpu_to_be32s(&pdu->error_count); } else { be32_to_cpus(&pdu->status); be32_to_cpus(&pdu->actual_length); be32_to_cpus(&pdu->start_frame); be32_to_cpus(&pdu->error_count); } } static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send) { if (send) pdu->seqnum = cpu_to_be32(pdu->seqnum); else pdu->seqnum = be32_to_cpu(pdu->seqnum); } static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send) { if (send) cpu_to_be32s(&pdu->status); else be32_to_cpus(&pdu->status); } //对接收到的pdu进行大小端调正,send代码接收还是发送 //函数根据pdu->base.command来分别对四种pdu包进行解析 void usbip_header_correct_endian(struct usbip_header *pdu, int send) { __u32 cmd = 0; if (send) cmd = pdu->base.command; correct_endian_basic(&pdu->base, send); if (!send) cmd = pdu->base.command; switch (cmd) { case USBIP_CMD_SUBMIT: correct_endian_cmd_submit(&pdu->u.cmd_submit, send); break; case USBIP_RET_SUBMIT: correct_endian_ret_submit(&pdu->u.ret_submit, send); break; case USBIP_CMD_UNLINK: correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); break; case USBIP_RET_UNLINK: correct_endian_ret_unlink(&pdu->u.ret_unlink, send); break; default: /* NOTREACHED */ err("unknown command in pdu header: %d", cmd); //BUG(); } } EXPORT_SYMBOL(usbip_header_correct_endian); //根据send判断方向,来调整iso字段的大小端 static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) { /* does not need all members. but copy all simply. */ if (send) { iso->offset = cpu_to_be32(iso->offset); iso->length = cpu_to_be32(iso->length); iso->status = cpu_to_be32(iso->status); iso->actual_length = cpu_to_be32(iso->actual_length); } else { iso->offset = be32_to_cpu(iso->offset); iso->length = be32_to_cpu(iso->length); iso->status = be32_to_cpu(iso->status); iso->actual_length = be32_to_cpu(iso->actual_length); } } //根据pack判断方向,将iso和uiso的属性字段进行相互赋值 static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, struct usb_iso_packet_descriptor *uiso, int pack) { if (pack) { iso->offset = uiso->offset; iso->length = uiso->length; iso->status = uiso->status; iso->actual_length = uiso->actual_length; } else { uiso->offset = iso->offset; uiso->length = iso->length; uiso->status = iso->status; uiso->actual_length = iso->actual_length; } } //分配urb->number_of_packets个usbip_iso_packet_descriptor描述结构体 //并将urb->iso_frame_desc[0----np-1]个usb_iso_packet_descriptor写入到buff中 //将bufff返回 /* must free buffer */ void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) { void *buff; struct usbip_iso_packet_descriptor *iso; int np = urb->number_of_packets; ssize_t size = np * sizeof(*iso); int i; buff = kzalloc(size, GFP_KERNEL); if (!buff) return NULL; for (i = 0; i < np; i++) { iso = buff + (i * sizeof(*iso)); //对每一个usbip_iso_packet_descriptor包进行处理,保存到iso中,并调整大小端 usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1); usbip_iso_pakcet_correct_endian(iso, 1); } *bufflen = size; return buff; } EXPORT_SYMBOL(usbip_alloc_iso_desc_pdu); //接收urb->number_of_packets个包,并以此对这些包进行大小端转换 /* some members of urb must be substituted before. */ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) { void *buff; struct usbip_iso_packet_descriptor *iso; int np = urb->number_of_packets; int size = np * sizeof(*iso); int i; int ret; if (!usb_pipeisoc(urb->pipe)) return 0; /* my Bluetooth dongle gets ISO URBs which are np = 0 */ if (np == 0) { //uinfo("iso np == 0\n"); //usbip_dump_urb(urb); return 0; } buff = kzalloc(size, GFP_KERNEL); if (!buff) return -ENOMEM; ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); if (ret != size) { uerr("recv iso_frame_descriptor, %d\n", ret); kfree(buff); if (ud->side == USBIP_STUB) usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); else usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return -EPIPE; } for (i = 0; i < np; i++) { iso = buff + (i * sizeof(*iso)); usbip_iso_pakcet_correct_endian(iso, 0); usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); } kfree(buff); return ret; } EXPORT_SYMBOL(usbip_recv_iso); //根据ud->side来判断urb->pipe的类型是否正确和获取接收大小,然后接收数据 //将接收的数据保存到urb->transfer_buffer /* some members of urb must be substituted before. */ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) { int ret; int size; if (ud->side == USBIP_STUB) { /* stub_rx.c */ /* the direction of urb must be OUT. */ if (usb_pipein(urb->pipe)) return 0; size = urb->transfer_buffer_length; } else { /* vhci_rx.c */ /* the direction of urb must be IN. */ if (usb_pipeout(urb->pipe)) return 0; size = urb->actual_length; } /* no need to recv xbuff */ if (!(size > 0)) return 0; //从接收ud->tcp_socket接收size大小的字节,保存到urb->transfer_buffer ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0); if (ret != size) { uerr("recv xbuf, %d\n", ret); //当发生错误时,产生相应的事件 if (ud->side == USBIP_STUB) { usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); } else { usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return -EPIPE; } } return ret; } EXPORT_SYMBOL(usbip_recv_xbuff); /*-------------------------------------------------------------------------*/ static int __init usbip_common_init(void) { info(DRIVER_DESC "" DRIVER_VERSION); return 0; } static void __exit usbip_common_exit(void) { return; } module_init(usbip_common_init); module_exit(usbip_common_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL");
相关推荐
"Comsol完美吸收器:可见光薄膜与金环宽带吸收器的二维斜入射研究",Comsol完美吸收器。 包含可见光薄膜完美吸收器,涉及二维斜入射。 包含金环宽带完美吸收器。 ,Comsol完美吸收器; 可见光薄膜完美吸收器; 二维斜入射; 金环宽带完美吸收器,"Comsol二维斜入射完美吸收器:可见光薄膜与金环宽带吸收技术"
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
,西门子S7-200smart型PLC使用profinet通讯控制G120变频器程序, 可以实现速度设定与读取,启停和故障复位等功能。
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
,大众斯柯达 免玻璃车道保持新方案
基于PFC5.0的岩石循环加卸载试验的3D实现技术,PFC5.0 3D实现岩石的循环加卸载试验, ,PFC5.0; 3D岩石; 循环加卸载试验; 岩石循环; 岩石加卸载模拟,"PFC5.0三维岩石循环加卸载试验研究"
nodejs010-nodejs-boom-0.4.2-2.el6.centos.alt.noarch.rpm
小学元旦晚会PPT 模版
STEP7-MicroWIN-SMART-V3.0测试版(2025.02最新)安装包-链接地址
内容概要:卷积神经网络(CNN)是一种特殊的神经网络模型,尤其适用于处理图像类的任务,如检测任务、分类与检索、超分辨率重构、医学任务、无人驾驶、人脸识别等。与传统神经网络输入一组向量值不同,CNN能够接受更为复杂的三维输入(深度、高度、宽度),从而有效地降低输入参数量并提高图像处理效率。文中介绍了卷积操作的基本原理及其在图像中的运用,例如通过设置合适的卷积核大小、步幅和零填充等手段,控制特征图的数量和尺度,进而达到优化网络性能的目的。此外还提及了卷积参数共享的概念以及池化层的作用。经典案例包括了AlexNet、VGG网路和残差网络的设计思想和结构特性,尤其是残差网络解决了非常深网络难以训练的问题,并提升了模型的表现力。感受野的介绍则强调了深层网络中的局部感知的重要性。 适合人群:从事计算机视觉领域的研究人员和技术人员,特别是关注图像识别和高级图像处理的研究人员或开发者。 使用场景及目标:①理解并掌握CNN的基本组成单元,如卷积层、池化层的工作机制;②深入探讨经典CNN架构背后的思路及其应用场景,帮助读者提升模型构建能力,以便更好地应用于实际项目中。
nodejs010-1.2-29.el6.centos.alt.x86_64.rpm
COMSOL注浆技术:浆液扩散模型及其应用研究,comsol注浆,浆液扩散模型 ,comsol注浆; 浆液扩散模型,"Comsol注浆技术下的浆液扩散模型研究"
"Modbus全功能调试工具:RTU、ASCII支持,主站调试必备,界面简洁易操作,数据记录与转换,串口助手功能齐备,自动应答及批量连续发送功能强大,学习测试必备利器",MobbusRTU ModbusASCII Modbus调试工具Modbus主站调试工具ModbusMaster支持所有Modbus设备调试; 功能强大,是学习测试的必备工具; 1.界面简洁 2.数据记录功能 3.串口助手功能 4.数据转功能 5.自动应答功能 5.批量发送功能 6.连续发送功能 ,ModbusRTU; ModbusASCII; 调试工具; 主站调试工具; ModbusMaster; 全部设备调试; 功能强大; 界面简洁; 数据记录; 串口助手; 数据转换; 自动应答; 批量发送; 连续发送。,"多功能Modbus调试工具:支持RTU/ASCII,主站必备,功能全面,操作简洁"
一个使用 C++ 结合 DeepSeek 模型进行文本相似度计算的源码。该实例会接收两段文本,借助 DeepSeek 模型提取文本特征,然后通过余弦相似度来衡量两段文本的相似程度。
内容概要:本文详细介绍了传统RNN网络存在的问题及其局限性,进而引出了Transformer模型的核心优势及其结构原理。传统RNN由于串行计算和无法有效处理长距离依赖等问题限制了其应用效果,尤其在自然语言处理领域表现不佳。相比之下,Transformer通过引入自注意力机制(self-attention mechanism)和平行化的架构解决了这些问题。自注意力机制允许模型在同一时间处理完整的输入序列,在计算每个位置的表征时不仅考虑到该位置的元素也综合了其他所有位置的相关度。此外,文章还具体讲解了多头注意力机制(multi-head attention),以及为何引入多头能够捕获更为丰富的语义特征;位置编码(positional encoding)的作用是为了赋予模型区分相同字符在不同顺序组合的意义能力;并在末尾提到了BERT这一基于Transformer的预训练模型及其两种主要训练方式——掩码语言模型(masked language model)和下一个句子预测(next sentence prediction)。总体而言,本文揭示了Transformers架构相对于以往序列建模方法的优势所在。 适合人群:对深度学习尤其是自然语言处理技术有一定基础的理解的研究人员和技术爱好者。 使用场景及目标:帮助读者深入理解为何传统递归神经网络受限于自身的设计无法很好地应对复杂的NLP任务,如翻译或文本摘要,并展示了Transformer是如何克服这些问题的;同时也旨在让有兴趣探索最先进预训练模型如BERT背后逻辑的人群受益。 阅读建议:鉴于本文涉及到大量数学概念与公式推导,请确保自己拥有坚实的机器学习基础知识并且愿意投入足够的时间消化吸收这些新信息。建议配合代码实现一起学习,在实践中加深对各个组件作用的认知。
混合励磁爪极电机在Maxwell中的仿真分析与优化研究,爪极电机 (混合励磁爪极电机) maxwell ,核心关键词:爪极电机; 混合励磁; 爪极电机Maxwell;,混合励磁爪极电机在Maxwell中的仿真研究
内容概要:本文介绍了DeepSeek模型在不同平台上部署的方法。首先阐述了基于Ollama的本地部署,包括Ollama的安装、模型拉取以及交互模式的使用。接着讲解了DeepSeek在移动设备(iOS和Android)上的部署细节:iPhone需要通过Safari安装快捷指令,配置API Key并通过快捷指令测试运行;Android则借助Termux安装必要组件,并手动搭建Ollama环境以加载和测试模型。最后详细叙述了基于Open WebUI部署的方式,涉及Ollama、Docker Desktop及Open WebUI的安装流程及其之间的配合使用来最终达成模型的成功部署。 适用人群:面向有兴趣了解或者实际操作DeepSeek模型跨平台部署的技术开发者、研究人员以及AI爱好者。 使用场景及目标:适用于希望利用DeepSeek模型快速构建本地化应用程序、开展实验研究的用户;具体目标为掌握DeepSeek模型在桌面系统(如Linux、macOS、Windows)、iOS和Android智能手机以及云端WebUI界面上的不同部署手段和技术。 其他说明:对于每种类型的部署都提供了详细的步骤指导,旨在帮助使用者顺利完成所需工具和环境的安装,并确保模型能够正常工作。文中给出的具体链接和命令行脚本,有助于降低初次接触者的上手难度,提升部署效率和成功率。此外,还强调了一些重要的配置注意事项,例如正确输入API key以及对Ollama的初始化检查等。
交变磁场感应材料对沥青路面温度影响的研究,交变磁场下含感应材料沥青路面温度 ,交变磁场; 感应材料; 沥青路面; 温度; 变化; 加热效率,交变磁场对含感应材料沥青路面温度的影响研究
"深度探讨:利用主从博弈理论,结合双层模型与遗传算法及yalmip+cplex求解器实现代码复现的电热综合能源系统动态定价与能量管理",代码复现 《基于主从博弈的电热综合能源系统动态定价与能量管理》 采用双层模型求解 上层为主问题使用遗传算法 下层为子问题调用yalmip+cplex求解器求解 有需要的联系留邮箱 ,代码复现; 动态定价; 能量管理; 主从博弈; 双层模型; 遗传算法; cplex求解器; 联系邮箱,代码复现:双层模型求解电热综合能源系统动态定价与能量管理策略
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx