Vxworks学习(一)_多任务、任务通信
Vxworks学习(一)_记录
- VxWorks简介
- 一、多任务
- 1.1 任务状态
- 1.2 Wind任务调度
- 1.3 任务控制
- 1. 任务创建函数:
- 2. 任务删除
- 3. 任务控制
- 4. 任务拓展函数
- 5. 任务错误errno
- 6. 任务异常处理
- 7. 共享代码和重入
- 二、任务间通信
- 2.1 互斥办法
- 2.2 信号量
- 2.2.1 二进制信号量
- 2.2.2 互斥信号量
- 2.2.3 计数信号量
- 2.3 注意:优先级倒置
- 2.4 消息队列
- 2.5 管道
- 2.6 任务间网络通信
- 2.7 信号
- 2.8 看门狗定时器
VxWorks简介
学习Vxworks之前希望读者已经具备计算机网络、操作系统、C/C++、网络通信等基础知识。建议阅读CSAPP,打好基础。
Vxworks为美国风河公司推出的高性能实时操作系统,现已广泛应用于各类大型项目,同时Tplink等公司也应用Vxworks作为某些路由器的操作系统。
实时性在计算机中分为强实时、软实时,vx所支持的为强实时,Linux普遍为软实时。
在一个实时操作系统之中,最关注的是每个任务在多长时间内可以完成。简单地说,实时和分时操作系统最大的不同在于 **时限(deadline)**这个概念。它不允许任何超出时限的错误。超时错误会带来损害甚至导致系统失败、或者导致系统不能实现它的预期目标。软实时系统的时限是一个柔性灵活的,它可以容忍偶然的超时错误。失败造成的后果并不严重,例如在网络中仅仅是轻微地降低了系统的吞吐量。
声明本学习记录为笔者的学习记录笔记,其中大量借鉴了多本已出版书籍与网络资料,并会在文章末尾注明出处,同时笔者无虚拟机镜像。
一、多任务
现代实时系统是在多任务和任务间通信的基础上建立起来的。一个多任务的环境允许将实时应用构造成一组独立的任务,每个任务拥有各自的线程和一套系统资源。为了协调任务间的行为,任务间的通信设备允许这些任务通过同步和通信操作协调各自的活动。在VxWorks 操作系统中,任务间通信设备包括信号量、消息队列、管道以及网络套接字等设备。
在实时系统中,处理中断是另一个主要功能,这是因为中断是将外部事件通知系统的重要方式。为了能得到较快的中断响应,VxWorks操作系统里中断服务程序(ISR)在一个专门的上下文中执行,是处于任务的上下文之外。
Vxworks实时内核Wind提供了基本的多任务环境,并提供了相应的调度算法。每个任务均具备自己的上下文,上下文均保存在任务控制块TCB中。其中TCB包括以下内容:
注意Vxworks系统是支持虚拟内存的。
1.1 任务状态
Vxworks任务状态表如下:
1.2 Wind任务调度
Wind内核的默认算法为基于优先级的抢占式调度算法,同时也支持RR调度算法,两种算法均依赖任务优先级。Wind内核中有256种优先级,0-255,0为*。函数如下:
1.基于优先级的抢占式任务调度
字面理解,优先级高的任务会掠夺CPU资源进行执行,低的任务将被掠夺。
优点:紧急任务可以立刻执行。
缺点:当多个优先级相同的任务共享一个CPU时,若某个任务永不阻塞,它将独占CPU,其他任务无法执行。任务调度会产生上下文切换,频繁掠夺会导致上下文切换造成的资源浪费。
由此引出轮转调度算法。
2.轮转调度算法(RR)
平均使用CPU,相同优先级任务获得相同CPU处理时间,当一个时间片用完,自愿放弃对CPU的使用,进行上下文切换。
==注意:==若在轮转调度中,某个任务被高优先级任务抢占,则保留该任务的时间片剩余时间,在高优先级任务执行完毕后,恢复低优先级任务执行并用完用于时间片。
3.抢占上锁
taskLock()、taskUnlock(),可以禁止内核调度。若某个任务开启了禁止调度,却在执行中被阻塞和挂起,内核有资格执行调度,选择高优先级任务执行,当该任务解除阻塞或挂起时,禁止抢占将再次生效。
注意: 应用程序的优先级应设置在 100-250之间,驱动程序优先级位于 51-99。
1.3 任务控制
1. 任务创建函数:
id = taskSpawn(name, priority, options, stacksize, main, arg1, arg10);
taskInit();
taskActive();
//id 为4个字节 int
//name: 任务名
//stacksize:任务堆栈
//options:任务选项
//main:入口函数地址
//arg10:传给入口函数的启动参数
//示例:
tid = taskSpawn("tMyTask", 90, VX_FP_TASK, 20000, myFunc, 2387, 0, 0
0, 0, 0, 0, 0, 0, 0);
2. 任务删除
exit();//终止任务调用,释放内存
taskDelete();//终止指定任务,释放内存
taskSafe();//保护调用任务免于删除
taskUnsafe();//解除任务删除保护
注意删除任务之前,应先释放该任务所占有的共享资源。也需要注意,若某个任务需要访问临界区,若该任务释放时,同时对其持有的信号量进行删除,这将导致其他任务无法对该临界区进行访问。此时应调用taskSafe()保护该任务被删除。
3. 任务控制
4. 任务拓展函数
5. 任务错误errno
操作系统中的潜在的全局变量errno是已被定义的,可直接与操作系统相连接的应用代码所应用,上下文切换时,errno同时被保存。
6. 任务异常处理
对于操作系统来说,CSAPP讲到异常分为中断、陷阱、异常,同时中断也分为硬件中断与软件中断,通常硬件中断是异步的,即不可预料的;软件中断是同步的,即是可预料的,Debug就是通过陷阱实现的。
7. 共享代码和重入
- 代码共享必须是可重入的,多个任务同时调用一个函数不发生冲突;
2)Vx中的I/O与驱动程序为可重入的;
Vx函数使用下列重入技术:
动态堆栈变量:多任务调用一个函数时,每个任务都有自己堆栈;
被信号保护的全局和静态变量:使用semMLib提供的mutex或互斥信号量;
任务变量:多任务调用一个程序,但每个任务调用使用不同的全局变量或静态变量。
二、任务间通信
- 共享内存:可以说是最快的通信方式,也简单
- 信号量:同步与互斥
- Mutexe和条件变量
- 消息队列和管道:用于同一个CPU内任务间消息传递
- Sockets和远程程序调用:网络编程
- 信号:异常处理
2.1 互斥办法
中断上锁:
int lock = intLock();
//禁止中断的代码临界区
intUnlock(lock);
抢占上锁:
taskLock();
//禁止中断的代码临界区
taskUnlock();
2.2 信号量
#include "vxWorks.h"
#include "semLib.h"
SEM_ID semMutex;
semMutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
semTake(semMutex, WAIT_FOREVER);
//临界区
semGive(semMutex);
信号量同时可用于同步。具体为任务1等待某信号量,任务2完成某个任务后,释放该信号量,此时任务1捕捉到该信号,解除阻塞,开始执行任务。
一致性
和信号量有关的一致性问题主要包括:(1)删除信号量时不会使阻塞其上的任务陷入无限等待;(2)持有信号量的任务不会因为意外停止运行而使其他任务陷入无限等待。一致性问题可能会使部分任务无法运行,严重时使整个系统得不到期望的结果甚至崩溃。其中,第(1)点由系统保证,系统在删除信号量时自动解除信号量阻塞队列上所有阻塞的任务。
2.2.1 二进制信号量
可进行同步和互斥
2.2.2 互斥信号量
2.2.3 计数信号量
2.3 注意:优先级倒置
基于优先级调度的操作系统会存在一个问题。
解决办法:优先级继承。
由此提出互斥信号量
semID = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
计数器信号量
CSAPP均赘述,不做介绍。
Wind标准信号量接口包括两个特定选项,不兼容POSIX。
(1)超时: NO_WAIT, WAIT_FOREVER;
(2)队列:
2.4 消息队列
单个CPU里任务间主要通信方式。
-
全双工通信需要两个消息队列。
函数:
- 可选择任务优先级顺序与FIFO顺序
- 接受超时与紧急消息选项
推荐模型:
为什么使用消息队列
“信号量+共享缓冲区”不需要在用户缓冲区(即共享缓冲区)和系统内核缓冲区之间复制数据,因此效率很高,适合数据量非常大的场合;而使用消息队列时通信双方需要经过系统内核缓冲区交换数据,因此效率比“信号量+共享缓冲区”低。
优势在于:程序简单。
数据量不大的情况下,程序简化效果明显。
信号量的优先级问题只考虑一个阻塞任务队列的优先级排序。和信号量优先级不同,消息队列优先级问题从下面两个方面考虑。
(1)消息自身的优先级:决定消息队列中多条消息提交给接收任务的顺序;
(2)阻塞任务队列优先级:决定阻塞任务队列中多个发送者任务或者多个接收者任务谁先被执行。
消息优先级被分成两类,normal和urgent,urgent插在队头,normal队尾。
信号量与消息队列实验
/*
msgorder.c: test message processing order*/
#include "vxworks.h"
#include "msgQLib.h"
#include " semLib.h"
#define MAxMSG 3
#define MAX_MSG_LEN 50
#define TEST_NUM 8
MSG_Q_ID msgQueue = NULL;
SEM_ID semMutex = NULL;
SEM_ID semCounter = NULL;
char logBuf[ TEST_NUM*3 ][MAX_MSG_LEN+20];
int nLog = 0;
void sendMsg( int );
void rcvMsg ( void ) ;
void msgOrder(){
/*定义:发送任务优先级消息自身优先级接收任务优先级*/
const int senderPri[TEST_NUM]= {50, 51, 52, 49, 53, 56, 55, 54};
const int msgPri[TEST_NUM]={ 0,1,1.1,0,1,0, 1 };
const int rcvPri = 60;
int i, j;
if( msgQueue || semMutex || semcounter ) {
printf ('last running not exit properly ! \n" );
exit (-1);
}
/*创建:消息队列互斥信号量计数信号量*/
msgQueue = msgQCreate(MAX_MSG,MAX_MSG_LEN,MSG_Q_FIFO);
semMutex= semMCreate(SEM_Q_FIFO) ;
semCounter = semccreate(SEM__Q_FIFO,0); .
if( !msgQueue || !semMutex li || !semCounter )
exit (-1) ;
/生成发送任务(发送消息)*/
for( i=0; i<TEST_NUM; i++ )
taskSpawn( 0, senderPri(i], 0,2000,sendMsg, msgPri[i], 0,0,0,0,0,0,0,0,0 ) ;
/*生成接收任务(接收消息)`*/
taskspawn(0, rcvPri, 0, 2000, rcvMsg, 0,0,0,0,0,0,0,0, 0,0 ) ;
/★等待所有任务退出*/
i = 0 ;
while( i++ < TEST_NUM+1 )
semTake(semCounter, WAIT_FOREVER);
printf ( " \n**Logged result : ln" ) ; /*输出结果*/
for( i=0; i<nLog; i++ ) {
printf ( "<%2d> %sln" , i,logBuf[i] ) ;
}
msgQDelete(msgQueue); msgQueue = 0;/*正常退出清理*/
semDelete(semMutex); semMutex=0;
semDelete(semcounter); semCounter= 0;
}
void sendMsg( int msgPri ) /*发送消息msgPri表示消息优先级*/
{
int taskPri ;
char msgBuf[MAx_MSG_LEN];
/*生成消息内容msgBuf:任务优先级+消息优先级记录*/
taskPriorityget(taskIdself(), &taskPri ) ;
sprintf(msgBuf,"task pri : %d,msg pri: %s",taskPri, msgPri == MSG_PRI_NORMAL ? "LO" : "HI") ;
semTake(semMutex, WAIT_FOREVER) ;
sprintf( logBuf [nLog], "---s:[ %s ] ready" , msgBuf ) ;
nLog++;
semGive( semMutex);
/*发送消息―记录*/
msgQSend(msgQueue,msgBuf,MAX_MSG_LEN,WAIT_FOREVER,msgPri );
semTake(semMutex,WAIT_FOREVER);
sprintf(logBuf [nLog] , "---s: [ %s ] sent" , msgBuf );
nLog++;
semGive(semMutex);
semGive( semcounter);
}
void rcvMsg(void) /*接收消息*/
int i, j;
char msgBuf [MAX_MSG LEN ] ;
for( i=0; i<TEST_NUM; i++) {
j = msgQReceive(msgQueue,msgBuf,MAX_MSG_LEN,WAIT_FOREVER );
semTake(semMutex,WAIT_FOREVER) ;
if{j)
sprintf( logBuf [nLog], "---R:[ %s ] received" , msgBuf);
else
sprintf( logBuf [nLog], "---R: 0 bytes read" );
nLog++;
semGive(seMutex);
}
semGive(semCounter);
}
)
2.5 管道
#include "pipeDrv.h"
status = pipeDevCreate("/pipe/name", max_msgs, max_length);
status = pipeDevDelete(char *name, BOOL force);
#include "ioLib.h"
int open(const char *name, int flags, int mode);
管道提供了一个消息队列不具备的重要特性,可使用select(),属于I/O复用范畴,请读者自行检索。
和直接的VxWorks消息队列相比,VxWorks管道具有如下一致的地方:
- 当任务试图从一个空的管道中读取数据,或向一个满的管道中写入数据时,任务被阻塞:
- 支持中断服务程序向管道中写入信息,驱动程序判断调用环境属于中断则不阻塞,即使没有可用的缓冲区,但是不能从管道中读取,如同中断服务程序不能对消息队列做接收操作一样;
- 往管道中写入数据时,一次写入的数据不能超出消息队列最大允许消息长度
由于管道具有上述消息队列的本质内容,本书有时称管道中的数据为消另外,VxWorks管道相比消息队列有如下不足: - 管道的效率不如消息队列的高。需要将应用程序中标准的IIO调用映射到pipeDrv驱动程序函数,并最终由消息队列函数实现;
- 管道会稍微多占用一些内存资源和IO系统资源;
- 不支持消息的优先级控制,消息队列支持两级消息优先级和阻塞任务队列优先级
- 管道不支持超时控制;
- 较老版本可能不支持管道删除,消息队列不再使用时可以删除以释放资源。
2.6 任务间网络通信
- 套接字
TCP/UDP
可以去看看图解TCP/IP,通俗易懂。 - 远程程序调用(RPC)(笔者:总看见RPC框架什么的,没有深入了解过,JAVA用户应该比较了解)
2.7 信号
“信号可以异步改变任务的控制流程”
信号也称为 软中断。
Wind内核支持:UNIX BSD风格信号与POSIX兼容信号。
2.8 看门狗定时器
(懒得手打了 = =, 坐的好累)
参考书籍及文献:
[1]: VxWorks程序员指南 [美]Wind River著-清华大学出版社
上一篇: vxWorks驱动架构
下一篇: 选择实时操作系统(RTOS)的相关问题
推荐阅读
-
KDD 2021|美团联合多所大学提出多任务学习模型,应用于联名卡客户获取场景
-
KDD 2021|美团联合多所大学提出多任务学习模型,应用于联名卡客户获取场景
-
手机通信中使用了哪些通信调制技术--调制和多任务处理技术
-
多任务学习 分布式和联合学习
-
中科院和香港大学团队利用多任务学习的新方法实现低能耗、低时间消耗的可穿戴传感器储层内计算
-
AAAI2023 | DeMT:CNN+变换器实现多任务学习(分割/深度等)-1 领域背景
-
c++ 学习笔记(套接字编程一对多通信)
-
41 个下载免费 3D 模型的最佳网站-使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 17. Clara.io Clara.io 是一个创建 3D 内容的全球平台,也是一个培养新 3D 艺术家的社区。Clara.io 提供+100,000个免费的3D模型,包括OBJ,Blend,STL,FBX,DAE,Babylon.JS,Three.JS格式,用于 Clara.io,Unity 3D,Blender,Sketchup,Cinema 4D,3DS Max和Maya。 使用说明:免费,标准和专业帐户仅供个人使用,如果您需要将 clara.io 用于商业用途,请与销售团队联系。 18. 3DExport 3DExport是一个市场,您可以在其中购买和销售用于CG项目的3D模型,3D打印模型和纹理。它提供15 +不同的3D格式供下载,如3DS MAX(.max),Cinema4D(.c4d),Maya(.mb,.ma),Lightwave(.lwo),Softimage(.xsi),Wavefront OBJ(.obj),Autodesk FBX(.fbx)等。它还提供15种不同的语言! 使用说明:免费下载仅供个人和非商业用途。 19. 3D Warehouse 3D Warehouse是一个开放的库,允许用户共享和下载SketchUp 3D模型,用于建筑,设计,施工和娱乐!任何人都可以免费制作,修改和重新上传内容到3D仓库,您可以找到任何您能想到的东西,如家具,电子产品,室内产品等。 使用说明:3D Warehouse中的所有模型都是免费的,因此任何人都可以下载文件以用于SketchUp甚至其他软件,如AutoCAD,Revit和ArchiCAD。 20. CadNav.com CadNav是CGI平面设计师和CAD / CAM / CAE工程师的在线3D模型库,我们提供超过50000 +免费3D模型和CAD模型下载。在CadNav网站上,您可以下载高质量的多边形网格3D模型,3D CAD实体对象,纹理,Vray材料,3D作品,CAD图纸等。 使用说明:免费下载仅供个人和非商业用途。 21. All3dfree.net 就像网站名称一样,它提供免费的3D模型,还包括Vray材料,CAD块,2d和3d纹理集合,无需注册即可免费下载。它是不断更新的,因此您可以查找或请求3DS,MAX,C4D,skp,OBJ,FBX,MTL等格式的模型。 使用说明:所有资源均不允许用于商业用途,否则您将承担责任。 22. Hum3D 自2005年以来,Hum3D帮助来自3多个国家的80D艺术家节省3D建模时间,并制作逼真的3D模型,用于电影,视频游戏,AR应用程序和可视化。所有模型均由首席3D艺术家进行验证,他们检查其是否符合专业要求和最新的3D建模标准。 使用说明:免费下载仅供个人和非商业用途。 23. Artist-3D.com 艺术家-3D 库存的免费 3D 模型下载按通用类别排序。它为人体解剖学、汽车、家具、火箭、卫星等模型提供 AutoDesk 3DS Max 格式。您还可以在浏览他们的网站时找到教程和类似类型的建模。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 24. Free the models 就像本网站的标题一样,它为3d应用程序和3d游戏引擎提供免费的内容模型。您可以为您的任何项目找到许多有趣且有用的模型!它提供3ds,wavefront,bryce,poser,lightwave,md2和unity3d格式的模型。还有一个很棒的纹理集合,可以在您最喜欢的建模和渲染程序中使用。 使用说明:您从这里下载的所有内容都可以免费使用,除非它不能包含在另一个免费的网络或CD收藏中,也不能单独出售。否则,您可以在商业游戏,3D应用程序或渲染作品中使用它。您不必提供信用,但如果您这样做,那就太好了。 25. Resources.blogscopia 本网站由一家名为Scopia的公司创建。他们制作3D图像和视频,您可以找到许多为CGI工作的信息架构设计的模型,所有这些都可以在现实生活中使用。您可以免费下载它们,但是,如果您想一次下载它们,您可以支付 3 到 9 欧元。 使用说明:您可以免费下载模型部分的所有文件。每个压缩文件都包含您也可以在此处找到的许可证。基本上,您可以对文件执行任何操作。唯一的限制是不归属于Scopia的重新分发。 26.ambientCG 1000+公共领域PBR材料适合所有人!环境CG是使用许多不同的方法和资产类型创建的,例如照片纹理(PBR),贴花(PBR),图集(PBR),照片纹理(普通),物质存档(SBSAR),雕刻画笔,3D模型和地形。您可以在所有项目中*使用它们! 使用说明:在 ambientCG 上提供下载的所有 PBR 材料、画笔、照片和 3D 模型均根据知识共享 CC0 1.0 通用许可提供。您可以复制、修改、分发和执行作品,即使是出于商业目的,也无需征得许可。信用将不胜感激。 不要满足于平庸的大理石纹理 - 立即使用我们的免费PBR大理石纹理升级您的3D设计。 27.Pixar One Twenty Eight 这是一个提供官方动画行业经典纹理的网站:皮克斯,创建于 1993 年,该纹理库包括 128 个重复纹理,现在免费提供。 它包含您来到的纹理,包括砖块和动物毛皮。肯定会有一些你可以使用的东西。 使用说明:皮克斯动画工作室的《Pixar One Twenty Eight》根据知识共享署名4.0国际许可协议进行许可。即使出于商业目的,您也可以重新混合、调整和构建您的作品,只要您以相同的条款对新创作进行信用和许可。 访问数以千计的免费纹理并提升您的设计游戏 - 立即开始下载! 28. 3DXO 即使有近 620 个免费贴纸可供下载,3DXO 也不是最大的资源,但它的内容非常有用,不需要注册。无论是简单的墙壁或地板,还是一些奇怪的小东西,您都需要的纹理都可以在此网站上看到。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 29. 3DModelsCC0 3DModelsCC0 与其他产品的不同之处在于它包含超过 250+ 个高质量 3D 模型,并且本网站上的所有内容都是免费的,完全是公共领域!使用我们的模型时无需信用或归属! 使用说明:为每个人提供完全免费的公共领域内容。 30.Sketch up texture club Sketchup Texture Club是一个非营利性的教育和信息门户网站,由3D社区的图像促进协会管理,特别强调面向学生和建筑和室内设计专业人士的可视化和渲染技术,以及所有正在学习3D可视化的人。 使用说明:您无需支付版税或使用费。纹理可以免费下载和使用。不允许将纹理作为竞争产品出售或重新分发,即使图像被修改也是如此。 31. FlippedNormals FlippedNormal 是一个提供计算机图形和 3D 资产的市场,您可以找到许多用于雕刻、建模、纹理、概念艺术、3D 模型、游戏资产或课程的高级资产! 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 32. NASA 3D NASA 3D网站是一个在线门户,提供与太空和各种NASA任务相关的大量三维模型和模拟。该网站是用户友好的,并提供有关每个型号的详细信息。该网站允许用户探索和下载几种不同格式的模型,包括 OBJ、STL 和 FBX,只需单击下载按钮即可。 使用说明: 要下载模型,只需单击模型页面上的下载按钮并选择所需的格式。 33. 3DAGOGO (Astroprint) 3DAGOGO 是一个提供广泛 3D 模型的网站,包括角色、车辆和建筑物。3DAGOGO 的独特功能之一是它专注于适合 3D 打印的模型,使其成为希望创建物理原型或模型的设计师的绝佳资源。要使用 3DAGOGO,设计师只需在网站上搜索他们正在寻找的模型类型,然后下载 STL 格式的文件。 使用说明: 要使用 3DAGOGO,只需搜索所需的 3D 模型类型并下载 STL 格式的文件。根据需要自定义模型,并确保在将其用于商业目的之前检查使用权限。 34. FreeCAD FreeCAD是一款了不起的3D建模软件,可让您在计算机上创建令人难以置信的3D设计。该软件可免费下载和使用,它提供了广泛的工具和功能,可用于创建用于各种目的的3D模型。 该网站易于浏览,您可以找到开始使用FreeCAD的所有必要信息。此外,该网站还提供一系列教程和指南,可帮助您了解 3D 建模的来龙去脉。 使用说明: 要下载模型,请访问网站并从库中选择所需的模型。该网站还提供了一系列使用该软件的教程和指南。 35. Pinshape Pinshape是一个提供一系列3D打印模型的网站。网站上提供的型号质量很高,因此您可以确保您的最终印刷产品看起来很棒。该网站提供了广泛的模型,包括从家居用品到小雕像和珠宝的所有物品。 但这还不是Pinshape所能提供的全部!该网站还允许用户上传和共享自己的3D模型。这意味着您不仅可以下载出色的模型,还可以通过分享自己的设计为社区做出贡献。此外,Pinshape 提供了一系列自定义选项,因此您可以调整和调整模型以满足您的特定需求。 使用说明: 要下载模型,请在网站上创建一个帐户,搜索所需的模型,然后单击下载按钮。该网站还为每种型号提供了一系列定制选项。 36.Yeggi Yeggi 提供了大量免费的 3D 模型,您可以下载各种格式的模型,例如 STL、OBJ 和 FBX。该网站易于使用,您可以按关键字、类别或特定网站搜索模型。 Yeggi 对于任何寻找 3D 模型的人来说都是一个很好的资源。它提供了大量的模型集合,从日常物品到复杂的机械,以及介于两者之间的一切。该网站的收藏量在不断增长,每天都有新的型号增加。 使用说明: 要下载模型,请在网站上搜索所需的模型,然后单击下载按钮。该网站还提供指向托管模型的原始网站的链接。 37. Open3DModel 来自开放3D模型的图像 Open3DModel具有各种类别的模型,包括建筑,车辆和角色。无论您需要建筑物,汽车还是人的3D模型,都可以在此网站上找到。 该网站易于浏览,您可以按类别或关键字搜索模型。每个模型都附带预览图像和详细信息,例如文件格式、大小和多边形数量。此信息可以帮助您选择适合您需求的模型。 使用说明: 要下载模型,请访问网站,从库中选择所需的模型,然后单击下载按钮。 使用最好的 3D 资产管理工具简化您的 3D 制作流程。立即试用它们,将您的 3D 项目提升到一个新的水平! 38. 3DExport 对于那些为其 3D 设计项目寻找 3D 模型、纹理和其他资源的人来说,该平台是一个很好的资源。该网站有大量模型可供选择,包括 3D 打印对象、游戏资产等。用户可以按类别、文件格式或价格范围浏览,以找到适合其项目的完美资源。此外,3DExport 还提供一系列教程和其他 3D 资源,以帮助用户提高技能并创建更令人印象深刻的设计。 使用说明: 要使用 3DExport,只需创建一个帐户并浏览可用型号。您可以按类别、格式和价格进行搜索,以找到所需的型号。找到喜欢的模型后,只需下载它并开始在您的项目中使用它。 39.Blend Swap Blend Swap是一个社区驱动的市场,提供与Blender软件兼容的各种免费3D模型。该平台允许用户共享和下载模型、纹理和其他资产,以便在他们的项目中使用。 使用说明: 创建免费帐户后,您可以浏览社区上传的大量3D模型。当您找到要使用的一个时,只需下载它并将其导入您选择的 3D 软件即可。 40. 3DShook 3DShook 是一个高级 3D 模型市场,提供一系列用于建筑、游戏等各个行业的高质量模型。该平台提供基于订阅的模型,具有不同的定价计划,允许用户访问一系列模型。 使用说明: 注册免费帐户后,只需浏览3D模型库,选择您喜欢的模型,然后以您需要的格式下载它们。 41. Smithsonian X 3D 史密森尼 X 3D 对于正在寻找历史文物和文物的高质量 3D 模型的设计师来说,这是一个独特的资源。该平台提供了大量3D模型,这些模型是根据史密森尼博物馆和研究中心中的真实物体扫描创建的。 使用说明:
-
windows下进程间通信的(13种方法)-摘 要 本文讨论了进程间通信与应用程序间通信的含义及相应的实现技术,并对这些技术的原理、特性等进行了深入的分析和比较。 ---- 关键词 信号 管道 消息队列 共享存储段 信号灯 远程过程调用 Socket套接字 MQSeries 1 引言 ---- 进程间通信的主要目的是实现同一计算机系统内部的相互协作的进程之间的数据共享与信息交换,由于这些进程处于同一软件和硬件环境下,利用操作系统提供的的编程接口,用户可以方便地在程序中实现这种通信;应用程序间通信的主要目的是实现不同计算机系统中的相互协作的应用程序之间的数据共享与信息交换,由于应用程序分别运行在不同计算机系统中,它们之间要通过网络之间的协议才能实现数据共享与信息交换。进程间通信和应用程序间通信及相应的实现技术有许多相同之处,也各有自己的特色。即使是同一类型的通信也有多种的实现方法,以适应不同情况的需要。 ---- 为了充分认识和掌握这两种通信及相应的实现技术,本文将就以下几个方面对这两种通信进行深入的讨论:问题的由来、解决问题的策略和方法、每种方法的工作原理和实现、每种实现方法的特点和适用的范围等。 2 进程间的通信及其实现技术 ---- 用户提交给计算机的任务最终都是通过一个个的进程来完成的。在一组并发进程中的任何两个进程之间,如果都不存在公共变量,则称该组进程为不相交的。在不相交的进程组中,每个进程都独立于其它进程,它的运行环境与顺序程序一样,而且它的运行环境也不为别的进程所改变。运行的结果是确定的,不会发生与时间相关的错误。 ---- 但是,在实际中,并发进程的各个进程之间并不是完全互相独立的,它们之间往往存在着相互制约的关系。进程之间的相互制约关系表现为两种方式: ---- (1) 间接相互制约:共享CPU ---- (2) 直接相互制约:竞争和协作 ---- 竞争——进程对共享资源的竞争。为保证进程互斥地访问共享资源,各进程必须互斥地进入各自的临界段。 ---- 协作——进程之间交换数据。为完成一个共同任务而同时运行的一组进程称为同组进程,它们之间必须交换数据,以达到协作完成任务的目的,交换数据可以通知对方可以做某事或者委托对方做某事。 ---- 共享CPU问题由操作系统的进程调度来实现,进程间的竞争和协作由进程间的通信来完成。进程间的通信一般由操作系统提供编程接口,由程序员在程序中实现。UNIX在这个方面可以说最具特色,它提供了一整套进程间的数据共享与信息交换的处理方法——进程通信机制(IPC)。因此,我们就以UNIX为例来分析进程间通信的各种实现技术。 ---- 在UNIX中,文件(File)、信号(Signal)、无名管道(Unnamed Pipes)、有名管道(FIFOs)是传统IPC功能;新的IPC功能包括消息队列(Message queues)、共享存储段(Shared memory segment)和信号灯(Semapores)。 ---- (1) 信号 ---- 信号机制是UNIX为进程中断处理而设置的。它只是一组预定义的值,因此不能用于信息交换,仅用于进程中断控制。例如在发生浮点错、非法内存访问、执行无效指令、某些按键(如ctrl-c、del等)等都会产生一个信号,操作系统就会调用有关的系统调用或用户定义的处理过程来处理。 ---- 信号处理的系统调用是signal,调用形式是: ---- signal(signalno,action) ---- 其中,signalno是规定信号编号的值,action指明当特定的信号发生时所执行的动作。 ---- (2) 无名管道和有名管道 ---- 无名管道实际上是内存中的一个临时存储区,它由系统安全控制,并且独立于创建它的进程的内存区。管道对数据采用先进先出方式管理,并严格按顺序操作,例如不能对管道进行搜索,管道中的信息只能读一次。 ---- 无名管道只能用于两个相互协作的进程之间的通信,并且访问无名管道的进程必须有共同的祖先。 ---- 系统提供了许多标准管道库函数,如: pipe——打开一个可以读写的管道; close——关闭相应的管道; read——从管道中读取字符; write——向管道中写入字符; ---- 有名管道的操作和无名管道类似,不同的地方在于使用有名管道的进程不需要具有共同的祖先,其它进程,只要知道该管道的名字,就可以访问它。管道非常适合进程之间快速交换信息。 ---- (3) 消息队列(MQ) ---- 消息队列是内存中独立于生成它的进程的一段存储区,一旦创建消息队列,任何进程,只要具有正确的的访问权限,都可以访问消息队列,消息队列非常适合于在进程间交换短信息。 ---- 消息队列的每条消息由类型编号来分类,这样接收进程可以选择读取特定的消息类型——这一点与管道不同。消息队列在创建后将一直存在,直到使用msgctl系统调用或iqcrm -q命令删除它为止。 ---- 系统提供了许多有关创建、使用和管理消息队列的系统调用,如: ---- int msgget(key,flag)——创建一个具有flag权限的MQ及其相应的结构,并返回一个唯一的正整数msqid(MQ的标识符); ---- int msgsnd(msqid,msgp,msgsz,msgtyp,flag)——向队列中发送信息; ---- int msgrcv(msqid,cmd,buf)——从队列中接收信息; ---- int msgctl(msqid,cmd,buf)——对MQ的控制操作; ---- (4) 共享存储段(SM) ---- 共享存储段是主存的一部分,它由一个或多个独立的进程共享。各进程的数据段与共享存储段相关联,对每个进程来说,共享存储段有不同的虚拟地址。系统提供的有关SM的系统调用有: ---- int shmget(key,size,flag)——创建大小为size的SM段,其相应的数据结构名为key,并返回共享内存区的标识符shmid; ---- char shmat(shmid,address,flag)——将当前进程数据段的地址赋给shmget所返回的名为shmid的SM段; ---- int shmdr(address)——从进程地址空间删除SM段; ---- int shmctl (shmid,cmd,buf)——对SM的控制操作; ---- SM的大小只受主存限制,SM段的访问及进程间的信息交换可以通过同步读写来完成。同步通常由信号灯来实现。SM非常适合进程之间大量数据的共享。 ---- (5) 信号灯 ---- 在UNIX中,信号灯是一组进程共享的数据结构,当几个进程竞争同一资源时(文件、共享内存或消息队列等),它们的操作便由信号灯来同步,以防止互相干扰。 ---- 信号灯保证了某一时刻只有一个进程访问某一临界资源,所有请求该资源的其它进程都将被挂起,一旦该资源得到释放,系统才允许其它进程访问该资源。信号灯通常配对使用,以便实现资源的加锁和解锁。 ---- 进程间通信的实现技术的特点是:操作系统提供实现机制和编程接口,由用户在程序中实现,保证进程间可以进行快速的信息交换和大量数据的共享。但是,上述方式主要适合在同一台计算机系统内部的进程之间的通信。 3 应用程序间的通信及其实现技术 ---- 同进程之间的相互制约一样,不同的应用程序之间也存在竞争和协作的关系。UNIX操作系统也提供一些可用于应用程序之间实现数据共享与信息交换的编程接口,程序员可以通过自己编程来实现。如远程过程调用和基于TCP/IP协议的套接字(Socket)编程。但是,相对普通程序员来说,它们涉及的技术比较深,编程也比较复杂,实现起来困难较大。 ---- 于是,一种新的技术应运而生——通过将有关通信的细节完全掩盖在某个独立软件内部,即底层的通讯工作和相应的维护管理工作由该软件内部来实现,用户只需要将通信任务提交给该软件去完成,而不必理会它的具体工作过程——这就是所谓的中间件技术。 ---- 我们在这里分别讨论这三种常用的应用程序间通信的实现技术——远程过程调用、会话编程技术和MQSeries消息队列技术。其中远程过程调用和会话编程属于比较低级的方式,程序员参与的程度较深,而MQSeries消息队列则属于比较高级的方式,即中间件方式,程序员参与的程度较浅。 ---- 4.1 远程过程调用(RPC)
-
多任务处理:第一课:我的线程旅程