1.【插件介绍】点云处理插件COCKROACH
2.FANUC NC Guide V25.0数控仿真系统,源码学习FANUC技术必备神器
3.Routr-基于最新技术架构的工具开源软交换概论-1-Kamailio和OpenSIPS的可选方案
4.看看华为的ExaGear和ElTechs公司的ExaGear是不是一个东西
5.Android 10属性系统原理,检测与定制源码反检测
6.记一次源码追踪分析,源码从Java到JNI,工具再到JVM的源码C++:fileChannel.map()为什么快;源码分析map方法,put方法
【插件介绍】点云处理插件COCKROACH
COCKROACH插件是工具社区控制端源码一款开源的点云处理工具,由Petras Vestartas和Andrea Settimi共同开发。源码
此插件依托于Open3D、工具CGAL和Cilantro库,源码代码可在Github上找到:github.com/9and3/Cockro...
开源的工具初衷是为了打造一个面向.NET的开放源代码点云处理工具,开发者期望有更多人为其贡献,源码增添更多功能。工具
以下通过开发者提供的源码案例,详细解析COCKROACH插件的工具功能。
包括:拾取点云、源码输出点云信息;按点数降低点云采样;按Voxel大小采样,Voxel越大,点云数越小;以box裁剪点云,支持反向裁剪;以多段线裁剪点云;以平面去切点云;根据颜色和点大小显示点云;显示点云的法向量;用点云创建网格;网格修复;网格的中心骨架;把网格转成点云;布尔网格等。
插件下载方面,COCKROACH插件提供了多种方式。
1. 可通过Food4Rhino下载COCKROACH插件,搜索插件名称,找到对应版本即可下载。下载链接:food4rhino.com/en/app/c...
注意:下载Grasshopper版本时,请选择倒数第二个版本,以免下载错误。
2. 第二种方法仅支持Rhino版本安装,不支持Grasshopper版本。机构监控公式源码使用程序集管理包(PackageManager)进行下载,在犀牛7中执行_PackageManager指令,搜索COCKROACH插件直接安装。
3. 如果熟悉代码,还可以从github下载COCKROACH插件的源代码。github.com/9and3/Cockro...
Grasshopper版本安装完成后,即可使用。
FANUC NC Guide V.0数控仿真系统,学习FANUC技术必备神器
FANUC NC Guide模拟仿真系统V.0是一款针对FANUC数控系统的学习与调试工具,其功能包括模拟系统使用、学习调试PMC梯形图、编辑数控系统采集等。
该系统具有以下特点:1)操作程序运行与真机操作相同;2)支持FANUC PMC程序的仿真,有助于维修人员学习PMC;3)可仿真FANUC 0I MF TF MD TD、FANUC IA B和FANUC I B 0IF PLUS IB PLUS系统。
软件下载地址:软件制作中
NC guide功能包括:1)培训CNC和MANUAL GUIDE I;2)编辑加工程序和加工循环;3)MEM/MDI方式下的操作和自动运行;4)加工模拟;5)显示MDI单元并可用鼠标直接操作;6)支持8.4 .4彩色显示器和标准的ONG(M/T)的MDI单元;7)将各种CNC数据输入输出到电脑上的文件夹;8)支持网络认证,可在局域网连接的多台计算机上运行。
NC guideRro功能包括:1)在PC上执行PMC梯形图程序;2)结合CNC模拟功能进行梯形图的调试;3)结合FANUC LADDER III编辑和显示梯形图;4)模拟PMC轴控制;5)利用机床信号模拟功能在附近实际机床环境下调试梯形图;6)执行使用C语言执行器/宏执行器创建的个性化软件;7)进行C语言执行器陈谷源代码的调试。
Routr-基于最新技术架构的开源软交换概论-1-Kamailio和OpenSIPS的可选方案
探索未来软交换:Routr的革新架构与开源选择 在SIP平台的世界里,Kamailio和OpenSIPS两大巨头一直在技术较量中不断迭代。然而,当谈到简化部署与编程友好的解决方案时,Routr崭露头角。它专为对SIP协议和业务理解有限的开发者设计,提供轻量级的SIP代理服务,无论是在云部署还是本地集成,都能轻松胜任。 Routr的飞机跟踪软件源码核心组件包括CORE(EdgePort和Message Dispatcher)和CONNECT(SIP Connect v1.1,升级至v2.0的gRPC通信版),确保了会话兼容性和多域访问控制。EdgePort作为消息的接收和转发者,支持元数据和连接传输(如TCP、TLS),而Message Dispatcher则根据传输协议灵活路由消息。 数据安全与便捷性:Routr通过安全JWT验证保护WebRTC通信,同时支持多数据源。它的Node.js SDK使开发者能够轻松管理Connect服务器,通过docker、源代码和snap安装方式一键部署,确保友好的用户体验。 部署Routr的实战指南包括基本的docker-compose.yml配置,集成RTP和PostgreSQL,以及指定IP地址的启动和状态检查。Registry组件是必不可少的,负责outbound注册,而Requester service则可能成为未来功能扩展的关键。Node.js SDK提供了CRUD操作和命令行管理的便利。 深入功能详解:Connect Processor支持WebRTC,可能需要额外配置RTPRelay;routr-ctl工具则简化了管理,如登录、配置修改等。安装步骤包括使用rctl启动proxy、查看日志、拉取镜像、安装rctl,以及阿里云HK节点的bbiboll买卖公式源码特定安装方法,甚至可通过软电话进行agent呼叫测试,验证其性能。 尽管Routr的架构清晰,易于部署,但它在业务功能和实战验证上还有提升空间。想要深入了解SIP技术的朋友,可以参考SIPConnect v2.0的技术推荐文档、Routr的GitHub项目,以及Asterisk和SIP官方网站获取更多信息。 结论:Routr的革新之旅,不仅提供了新的技术架构选择,也为开发者带来更直观、易用的部署体验。无论是SIP平台的新手还是经验丰富的开发者,Routr都展示了其在简化SIP管理与集成方面的潜力。继续关注Routr的发展,探索其在SIP软交换领域的无限可能。看看华为的ExaGear和ElTechs公司的ExaGear是不是一个东西
华为的ExaGear与俄罗斯ElTechs公司的产品之间引起了热议,华为自称为自主研发,但其技术与ElTechs的ExaGear存在诸多相似之处。年华为发布的ExaGear是一个动态二进制指令翻译工具,旨在优化ARM CPU上的Linux和x游戏运行性能。而ElTechs的ExaGear早在年便已商业化,以高效率著称,能在ARM平台上实现%的性能提升。 有人通过readelf工具对比Huawei ExaGear的.rodata字符串与ElTechs的软件,发现大量相同字符串,这暗示着可能存在共同的源码计算过程源代码基础。尽管有人质疑这种对比方法的准确性,但ElTechs的ExaGear自发布以来已经在实际应用中经受了考验。华为是否真的自研,还是如外界所猜测的那样,从ElTechs的技术中改进而来,这是一个引人关注的话题。 为了更直观地分析,过滤了非ASCII字符和重复字符串后,经过对比,两者共有个完全相同的字符串。这个发现促使我们深入研究这些共同的代码元素,它们可能涉及的程序逻辑和性能优化策略。以下是部分关键字符串的分析,它们揭示了潜在的技术关联:代码片段1:lkv_SubstitutedPathsListEntry::create: 强调路径管理和虚拟文件处理的共同点。
问题2:ExaGear personality flag READ_IMPLIES_EXEC的处理方式,可能暗示了对兼容性的考虑。
注意3:ExaGear对SUID/SGID文件的处理方式,可能是为了适应不同环境的兼容性需求。
代码片段4:lkv_SubstitutedPathsListEntry::create: 遇到的目录操作错误,提示两个项目在处理路径逻辑上有相似之处。
尽管这些字符串对比不能作为最终结论,但它们引发了关于知识产权和技术创新的讨论。华为与ElTechs的技术路径是否重叠,以及华为如何处理这些可能的渊源,将是未来讨论的重点。 然而,值得注意的是,尽管存在相似之处,每个公司都有其独特的优化策略和专长。华为的ExaGear或许是在ElTechs的基础上进行了定制和升级,以适应其自身的产品定位和性能目标。这个案例提醒我们,技术进步往往源于既有成果的迭代和创新,而真正的创新者往往会将这些基础转化为独特的竞争优势。 总的来说,华为ExaGear与ElTechs ExaGear之间的关系,是一个技术融合与创新的探讨,它展示了技术领域中开源精神和商业策略的微妙平衡。Android 属性系统原理,检测与定制源码反检测
本文基于看雪论坛精华内容,由作者飞翔的猫咪探讨Android 属性系统的深层次理解,包括检测与反检测策略。这些属性在Android系统中扮演着设备信息和运行时配置的关键角色,对于改机和设备指纹收集至关重要。
Android属性系统的基础构建在键值对上,每个属性都有类型(如string、int、bool),并由SELinux上下文保护。初始化和修改属性的过程涉及init进程通过mmap映射/dev/__properties__目录下的文件到进程的虚拟内存区域,以共享内存方式实现进程间通信。只有init进程能创建和修改属性,其他进程通过socket与init通信,而普通app受限于权限,无法直接操作。
属性主要分为ro(只读)、persist(持久化)、ctl(控制)和selinux.restorecon_recursive,各有不同的处理逻辑。为了提升效率,Android在文件格式设计上考虑了频繁获取的场景,并使用属性缓存机制,这对改机技术构成挑战。
属性同步通过包装futex系统调用实现,getprop工具则用于获取属性值,提供参数选项以获取上下文和类型信息。属性的核心API在bionic libc的头文件中定义,需通过特定宏定义来正确包含。
系统开发者倾向于通过预定义的接口使用属性,而非直接调用,如__system_property_set_value和__system_property_find等,它们分别用于设置和查找属性。设置权限由selinux策略通过set_prop宏管理,如system_app域可设置特定属性。
属性系统通过__system_property_read_callback和缓存机制提高效率,如CachedProperty.h文件中的函数。遍历属性和等待属性变化的功能分别由system_property_foreach和WaitForProperty实现。部分接口已废弃,但仍在部分框架代码中使用。
总结来说,属性系统的核心是init进程管理和响应其他进程的通信请求,而普通app在权限和策略的限制下,操作受限。理解这些原理对于深入研究和安全定制Android系统至关重要。
记一次源码追踪分析,从Java到JNI,再到JVM的C++:fileChannel.map()为什么快;源码分析map方法,put方法
前言
在系统IO相关的系统调用有read/write,mmap,sendfile等这些。
其中read/write是普通的读写,每次都需要将buffer从用户空间拷贝到内核空间;
而mmap使用的是内存映射,会将磁盘文件对应的页映射(拷贝)到内核空间的page cache,并记录到用户进程的页表中,使得用户空间也可以像操作用户空间一样操作该文件的映射,最后再由操作系统来讲该映射(脏页)回写到磁盘;
sendfile则使用的是零拷贝技术,在mmap的基础上,当发送数据的时候只拷贝fd和offset等元数据信息,而将数据主体直接拷贝至protocol buffer,实现了内核数据零冗余的零拷贝技术
本文地址:/post//
问题/目的问题1Java中哪些API使用到了mmap问题2怎么知道该API使用到了mmap,如何追踪程序的系统调用目的1源码中分析验证,从Java到JNI,再到C++:fileChannel.map()使用的是系统调用mmap目的2源码验证分析:调用mmapedByteBuffer.put(Byte[])时JVM在搞些什么?mmap比普通的read/write快在哪?揭晓答案1mmap在Java NIO中的体现/使用看一个例子
// 1GBpublic static final int _GB = 1**;File file = new File("filename");FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();MappedByteBuffer mmapedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, _GB);for (int i = 0; i < _GB; i++) { count++;mmapedByteBuffer.put((byte)0);}其中fileChannel.map()底层使用的就是系统调用mmap,函数签名为: public abstract MappedByteBuffer map(MapMode mode,long position, long size)throws IOException
答案2程序执行的系统调用追踪/** * @author Tptogiar * @description * @date /5/ - : */public class TestMappedByteBuffer{ public static final int _4kb = 4*;public static final int _GB= 1**;public static void main(String[] args) throws IOException, InterruptedException { // 为了方便在日志中找到本段代码的开始位置和结束位置,这里利用文件io来打开始标记FileInputStream startInput = null;try { startInput = new FileInputStream("start1.txt");startInput.read();} catch (IOException e) { e.printStackTrace();}File file = new File("filename");FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, _GB); //我们想分析的语句问题2for (int i = 0; i < _GB; i++) { map.put((byte)0); // 下文中需要分析的语句目的2}// 打结束标记FileInputStream endInput = null;try { endInput = new FileInputStream("end.txt");endInput.read();} catch (IOException e) { e.printStackTrace();}}}把上面这段代码编译后把“.class”文件拉到linux执行,并用linux上的strace工具记录其系统调用日志,拿到日志文件我们可以在日志中看到以下信息(关于怎么拿到日志可以参照我的博文:无(代写)):
注:日志有多行,这里只选取我们关注的
// ...// 看到了我们打的开始标志openat(AT_FDCWD, "start1.txt", O_RDONLY) = -1 ENOENT (No such file or directory)// ... // 打开文件,文件描述符fd为6openat(AT_FDCWD, "filename", O_RDWR|O_CREAT, ) = 6// 判断文件状态fstat(6, { st_mode=S_IFREG|, st_size=, ...}) = 0// ... // 判断文件状态fstat(6, { st_mode=S_IFREG|, st_size=, ...}) = 0// 进行内存映射mmap(NULL, , PROT_READ|PROT_WRITE, MAP_SHARED, 6, 0) = 0x7f2fd6cd// ...// 程序退出exit(0)// 看到了我们打的结束标志openat(AT_FDCWD, "end.txt", O_RDONLY) = -1 ENOENT (No such file or directory)在上面程序的系统调用日志中我们确实看到了我们打的开始标志,结束标志。在开始标志和结束标志之间我们看到了我们的文件"filename"确实被打开了,文件描述符fd = 6;在打开文件后紧接着又执行了系统调用mmap,这一点我们Java代码一致,这样,我们就验证了我们答案1中的结论,可以开始我们的下文了
源码追踪分析,从Java到JNI,再到JVM的C++目的1寻源之旅:fileChannel.map()我们知道我们执行Java代码fileChannel.map()确实会在底层调用系统调用,那怎么在源码中得到验证呢?怎么落脚于源码进行分析呢?下面开始我们的寻源之旅
FileChannelImpl.map() 注:由于代码较长,这里代码中略去了一些我们不关注的,比如异常捕获等
public MappedByteBuffer map(MapMode mode, long position, long size)throws IOException{ // ...try { // ...synchronized (positionLock) { // ...long mapPosition = position - pagePosition;mapSize = size + pagePosition;try { // !我们要找的语句就在这!addr = map0(imode, mapPosition, mapSize);} catch (OutOfMemoryError x) { // 如果内存不足,先尝试进行GCSystem.gc();try { Thread.sleep();} catch (InterruptedException y) { Thread.currentThread().interrupt();}try { // 再次试着mmapaddr = map0(imode, mapPosition, mapSize);} catch (OutOfMemoryError y) { // After a second OOME, failthrow new IOException("Map failed", y);}}} // ...} finally { // ...}}上面函数源码中真正执行mmap的语句是在addr = map0(imode, mapPosition, mapSize),于是我们寻着这里继续追踪
FileChannelImpl.map0()
// Creates a new mappingprivate native long map0(int prot, long position, long length)throws IOException;可以看到,该方法是一个native方法,所以后面的源码我们需要到这个FileChannelImpl.class对应的fileChannelImpl.c中去看,所以我们需要去找到JDK的源码
在JDK源码中我们找到fileChannelImpl.c文件
fileChannelImpl.c 根据JNI的对应规则,我们找到该文件内对应的Java_sun_nio_ch_FileChannelImpl_map0方法,其源码如下:
JNIEXPORT jlong JNICALLJava_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, jint prot, jlong off, jlong len){ void *mapAddress = 0;jobject fdo = (*env)->GetObjectField(env, this, chan_fd);jint fd = fdval(env, fdo);int protections = 0;int flags = 0;if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { protections = PROT_READ;flags = MAP_SHARED;} else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { protections = PROT_WRITE | PROT_READ;flags = MAP_SHARED;} else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { protections =PROT_WRITE | PROT_READ;flags = MAP_PRIVATE;}// !我们要找的语句就在这里!mapAddress = mmap(0,/* Let OS decide location */len,/* Number of bytes to map */protections,/* File permissions */flags,/* Changes are shared */fd, /* File descriptor of mapped file */off); /* Offset into file */if (mapAddress == MAP_FAILED) { if (errno == ENOMEM) { JNU_ThrowOutOfMemoryError(env, "Map failed");return IOS_THROWN;}return handle(env, -1, "Map failed");}return ((jlong) (unsigned long) mapAddress);}我们要找的语句就上面代码中的mapAddress = mmap(0,len,protections,flags,fd,off),至于为什么不是直接的mmap,而是mmap,是因为这里的mmap是一个宏,在文件上方有其定义,如下:
#define mmap mmap至此,我们就在源码中得到验证了我们问题2中的结论:fileChannelImpl.map()底层使用的是mmap系统调用
目的2寻源之旅:mmapedByteBuffer.put(Byte[ ])接着我们来看看当我们调用mmapedByteBuffer.put(Byte[])JVM底层在搞些什么动作
MappedByteBuffer ?首先我们得知道,当我们执行MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, _GB)时,实际返回的对象是DirectByteBuffer类的实例,因为MappedByteBuffer为抽象类,且只有DirectByteBuffer继承了它,看下面两图就明白了
DirectByteBuffer 于是我们找到DirectByteBuffer内的put(Byte[ ])方法
public ByteBuffer put(byte x) { unsafe.putByte(ix(nextPutIndex()), ((x)));return this;}可以看到该方法内实际是调用Unsafe类内的putByte方法来实现功能的,所以我们还得去看Unsafe类
Unsafe.class
public native voidputByte(long address, byte x);该方法在Unsafe内是一个native方法,所以所以我们还得去看unsafe.cpp文件内对应的实现
unsafe.cpp
在JDK源码中,我们找到unsafe.cpp
在这份源码内,没有使用JNI内普通加前缀的方法来形成对应关系
不过我们还是能顺着源码的蛛丝轨迹找到我们要找的方法
注意到源码中有这样的注册机制,所以我们可以知道我们要找的代码就是上图中标注的代码
顺藤摸瓜,我们就找到了该方法的定义
UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \UnsafeWrapper("Unsafe_SetNative"#Type); \JavaThread* t = JavaThread::current(); \t->set_doing_unsafe_access(true); \void* p = addr_from_java(addr); \*(volatile native_type*)p = x; \t->set_doing_unsafe_access(false); \UNSAFE_END \该方法内主要的逻辑语句就是以下两句:
/** * @author Tptogiar * @description * @date /5/ - : */public class TestMappedByteBuffer{ public static final int _4kb = 4*;public static final int _GB= 1**;public static void main(String[] args) throws IOException, InterruptedException { // 为了方便在日志中找到本段代码的开始位置和结束位置,这里利用文件io来打开始标记FileInputStream startInput = null;try { startInput = new FileInputStream("start1.txt");startInput.read();} catch (IOException e) { e.printStackTrace();}File file = new File("filename");FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, _GB); //我们想分析的语句问题2for (int i = 0; i < _GB; i++) { map.put((byte)0); // 下文中需要分析的语句目的2}// 打结束标记FileInputStream endInput = null;try { endInput = new FileInputStream("end.txt");endInput.read();} catch (IOException e) { e.printStackTrace();}}}0至此,我们就知道:其实我们调用mmapedByteBuffer.put(Byte[ ])时,JVM底层并不需要涉及到系统调用(这里也可以用strace工具追踪从而得到验证)。也就是说通过mmap映射的空间在内核空间和用户空间是共享的,我们在用户空间只需要像平时使用用户空间那样就行了————获取地址,设置值,而不涉及用户态,内核态的切换
总结fileChannelImpl.map()底层用调用系统函数mmap
fileChannelImpl.map()返回的其实不是MappedByteBuffer类对象,而是DirectByteBuffer类对象
在linux上可以通过strace来追踪系统调用
JNI中“.class”文件内方法与“.cpp”文件内函数的对应关系不止是前缀对应的方法,还可以是注册的方式,这一点的追寻代码的时候有很大帮助
directByteBuffer.put()方法底层并没有涉及系统调用,也就不需要涉及切态的性能开销(其底层知识执行获取地址,设置值的操作),所以mmap的性能就比普通读写read/write好
...
原文:/post/