libplctag开源库的API介绍

文章目录

    • 1 开源库概要
    • 2 API介绍
      • 2.1 Tag Model(标签模型)
      • 2.2 Status Codes(状态码)
      • 2.3 Versions and Checking Library Compatibility(版本和检查库的兼容性)
      • 2.4 Tag Life Cycle(标签生命周期)
      • 2.5 Callbacks(回调)
        • 2.5.1 Event Callback(事件回调)
        • 2.5.2 Log Callback(日志回调)
      • 2.6 Aborting an Operation(中止操作)
      • 2.7 Reading a Tag(读标签)
      • 2.8 Retrieving Tag Status(获取标签状态)
      • 2.9 Writing a Tag(写标签)
      • 3.0 Retrieving/Setting Tag Size(获取/设置标签大小)
        • 3.0.1 获取标签大小
        • 3.0.2 设置标签大小
      • 3.1 Getting Tag Data Elements(获取标签数据元素)
      • 3.2 Tag Internal Attribute Functions(标签内部属性函数)
      • 3.3 Debugging(调试)

1 开源库概要

  1. libplctag是一个开源的用于与PLC(可编程逻辑控制器)通信的库,它提供了一组函数和工具,可以方便地读写PLC数据。libplctag是用C语言编写的,广泛用于工业自动化、机器人控制等领域。
  2. 以下是libplctag库的一些特别:
    • 多种通信协议支持:libplctag可以与多种常用的PLC通信协议进行通信,包括Modbus TCP、Ethernet/IP等;
    • 简单易用的API:libplctag提供了简洁的API,使得开发人员可以轻松地读取和写入PLC的数据。库中封装了一系列函数,用于连接PLC、读取标签值、写入标签值等操作;
    • 跨平台支持:libplctag可以在多个操作系统上运行,包括Linux、Windows、Mac等。这使得开发人员可以在不同的环境中使用相同的库进行PLC通信开发。
    • 开源和社区支持:libplctag是一个开源项目,代码托管在GitHub上,可以自由获取和修改。同时也有活跃的社区支持,开发人员可以参与讨论、报告问题和贡献代码。
  3. 开源库的GitHub网址:

https://github.com/libplctag/libplctag

2 API介绍

此部分本人会简要介绍一下常用API,用于个人记录。更详细的说明请自行移步2.5.0 API文档网址:

https://github.com/libplctag/libplctag/wiki/API#tag-life-cycle

2.1 Tag Model(标签模型)

  1. 在介绍API之前,需要对模型进行简要说明。开源库将每个标签或标签中的字段作为一个单独的句柄,供程序使用。没有PLC的公开概念。只有标签。
  2. 标签是对PLC内存区域的本地引用。根据PLC类型和协议的不同,该区域可能会被命名。对于某些协议,区域只是一个类型和寄存器编号(如Modbus)。对于其他协议,则是一个名称、可能的数组元素、字段名称等(如基于CIP的PLC)。
  3. 你的程序直接控制句柄的生存期。可以通过plc_tag_create()打开PLC标签的句柄,通过plc_tag_destroy()释放与函数一起使用的资源。

2.2 Status Codes(状态码)

  1. 大多数函数返回状态码,详情如下(括号内为对应数值):
  • PLCTAG_STATUS_PENDING (1) - 操作正在进行中。不是错误。
  • PLCTAG_STATUS_OK (0) - 无错误。操作成功或标签状态良好。
  • PLCTAG_ERR_ABORT (-1) - 操作已中止。
  • PLCTAG_ERR_BAD_CONFIG (-2) - 由于配置不正确,操作失败。通常从远程系统返回。
  • PLCTAG_ERR_BAD_CONNECTION (-3) - 由于某种原因,连接失败。例如,这可能意味着远程 PLC 已重新通电。
  • PLCTAG_ERR_BAD_DATA (-4) - 从远程 PLC 接收的数据无法破译或无法处理。也可以从无法处理发送给它的数据的远程系统返回。
  • PLCTAG_ERR_BAD_DEVICE (-5) - 当寻址的内容不存在时,通常从远程系统返回。
  • PLCTAG_ERR_BAD_GATEWAY (-6) - 通常在库无法连接到远程系统时返回。
  • PLCTAG_ERR_BAD_PARAM (-7) - 当标签创建属性字符串不正确时返回的常见错误。
  • PLCTAG_ERR_BAD_REPLY (-8) - 通常在远程系统返回意外响应时返回。
  • PLCTAG_ERR_BAD_STATUS (-9) - 通常由远程系统在状态不佳时返回。
  • PLCTAG_ERR_CLOSE (-10) - 尝试关闭某些资源时出错。
  • PLCTAG_ERR_CREATE (-11) - 尝试创建某些内部资源时出错。
  • PLCTAG_ERR_DUPLICATE (-12) - 当某些内容(即重复的连接 ID)被错误复制时,远程系统返回的错误。
  • PLCTAG_ERR_ENCODE (-13) - 尝试对某些数据(如标签名称)进行编码时返回错误。
  • PLCTAG_ERR_MUTEX_DESTROY (-14) - 内部库错误。看到这种情况是非常不寻常的。
  • PLCTAG_ERR_MUTEX_INIT (-15) - 同上。
  • PLCTAG_ERR_MUTEX_LOCK (-16) - 同上。
  • PLCTAG_ERR_MUTEX_UNLOCK (-17) - 同上。
  • PLCTAG_ERR_NOT_ALLOWED (-18) - 当不允许操作时,通常从远程系统返回。
  • PLCTAG_ERR_NOT_FOUND (-19) - 通常在找不到某些内容时从远程系统返回。
  • PLCTAG_ERR_NOT_IMPLEMENTED (-20) - 未实现有效操作时返回。
  • PLCTAG_ERR_NO_DATA (-21) - 当预期数据不存在时返回。
  • PLCTAG_ERR_NO_MATCH (-22) - 类似于NOT_FOUND。
  • PLCTAG_ERR_NO_MEM (-23) - 内存分配失败时由库返回。
  • PLCTAG_ERR_NO_RESOURCES (-24) - 当某些资源分配失败时,由远程系统返回。
  • PLCTAG_ERR_NULL_PTR (-25) - 通常是内部错误,但在 API 调用中使用无效句柄时可能会返回。
  • PLCTAG_ERR_OPEN (-26) - 打开套接字等资源时出错时返回。
  • PLCTAG_ERR_OUT_OF_BOUNDS (-27) - 通常在尝试将值写入标签数据边界之外的标签或读取标签数据边界之外的值时返回。
  • PLCTAG_ERR_READ (-28) - 在读取操作期间发生错误时返回。通常与套接字问题有关。
  • PLCTAG_ERR_REMOTE_ERR (-29) - 未指定或无法转换的远程错误会导致此问题。
  • PLCTAG_ERR_THREAD_CREATE (-30) - 内部库错误。如果你看到这一点,很可能一切都要崩溃了。
  • PLCTAG_ERR_THREAD_JOIN (-31) - 另一个内部库错误。你不太可能看到这一点。
  • PLCTAG_ERR_TIMEOUT (-32) - 操作花费的时间过长且超时。
  • PLCTAG_ERR_TOO_LARGE (-33) - 返回的数据比预期的要多。
  • PLCTAG_ERR_TOO_SMALL (-34) - 从远程系统返回的数据不足。
  • PLCTAG_ERR_UNSUPPORTED (-35) - 远程系统上不支持该操作。
  • PLCTAG_ERR_WINSOCK (-36) - 发生特定于 Winsock 的错误(仅在 Windows 上)。
  • PLCTAG_ERR_WRITE (-37) - 尝试写入(通常是套接字)时出错。
  • PLCTAG_ERR_PARTIAL (-38) - 收到部分数据或某些内容意外不完整。
  • PLCTAG_ERR_BUSY (-39) - 无法执行该操作,因为正在执行其他操作。
  1. 可以通过如下API函数打印出状态码。它只是把上面的状态码数值转化为等效的字符串。函数返回静态C样式字符串,可以复制它,但不要尝试在程序中释放它。

const char *plc_tag_decode_error(int err);

2.3 Versions and Checking Library Compatibility(版本和检查库的兼容性)

  1. libplctag开源库的版本由三个部分组成:
    • 主要版本(major version):这表示高级API版本。不同的主要版本不保证相互兼容。
    • 次要版本(minor version):这表示API的功能级别。API功能不会在此版本升级时被删除。高版本兼容低版本。
    • 补丁版本(patch version):记录非API功能的增补或修改。该项添加可能非常重要,比如:增加对Modbus TCP的支持。所以使用时也需要注意。
    • 举例:库版本为2.1.9,则2对应主要版本、1对应次要版本、9对应补丁版本。
  2. 可以使用plc_tag_check_lib_version()函数来确认库版本是否满足需求。如果满足需求,函数返回PLCTAG_STATUS_OK;如果不符合,则返回PLCTAG_ERR_UNSUPPORTED
#define REQUIRED_VERSION 2,1,0 //程序需要的版本为2,1,0/* check the library version. */
if(plc_tag_check_lib_version(REQUIRED_VERSION) != PLCTAG_STATUS_OK) {fprintf(stderr, "Required compatible library version %d.%d.%d not available!", REQUIRED_VERSION);exit(1);}
//根据此模块判断是否满足需要
  1. plc_tag_check_lib_version()函数判断的内部逻辑如下:
    • 程序需要的主要版本与库的主要版本完全相同
    • 程序需要的次要版本小于或等于库的次要版本
    • 如果所需的次要版本等于库的版本,则补丁版本小于或等于库的版本;如果所需的次要版本低于库的版本,则忽略。
    • 函数如下所示:
int plc_tag_check_lib_version(int req_major, int req_minor, int req_patch);

2.4 Tag Life Cycle(标签生命周期)

  1. 创建标签句柄。需要知道使用的协议以及该协议所需的参数。访问标签的整套信息包含在一个字符串中,该字符串会被传递给plc_tag_create()函数。该字符串的格式与URL类似,由键-值对组成,用&符号分开。注意:创建或打开PLC中已存在的标签或字段的句柄,而不是在PLC中创建一个标签。(plc_tag_create_ex()函数可看API文档)
int32_t plc_tag_create(const char *attrib_str, int timeout);
//attrib_str:字符串(以NULL字符结尾),包含创建标签所需的所有信息
//timeout:等待句柄创建完成的值(以毫秒为单位)。如果该值为0,则函数可能会在PLC连接之前返回。//举例:
int32_t tag = plc_tag_create("protocol=ab_eip&gateway=192.168.1.42&path=1,0&cpu=LGX&elem_count=10&name=myDINTArray[0]", 1000);
  1. 销毁标签。标签句柄使用的是内部资源,必须要释放。不能使用free()函数。因为标签在内部并非一个内存块,所以要释放标签,需要调用下面的函数。程序要负责标签的创建和销毁。

int plc_tag_destroy(int32_t tag);
//返回状态码
  1. 关闭库。某些系统在卸载库或关闭程序时,无法触发POSIX或Windows函数。所以,我们需要调用下面的函数。该函数返回后,库会清理所有内部线程和资源,但可以通过创建标签来再次启动库。注意:调用该函数前,必须销毁所有标签。

void plc_tag_shutdown(void);

2.5 Callbacks(回调)

2.5.1 Event Callback(事件回调)
  1. 事件回调API包括三个函数:
int plc_tag_register_callback(int32_t tag_id, void (*tag_callback_func)(int32_t tag_id, int event, int status));
int plc_tag_register_callback_ex(int32_t tag_id, void (*tag_callback_func)(int32_t tag_id, int event, int status, void *userdata), void *userdata);
int plc_tag_unregister_callback(int32_t tag_id);
  1. 每个标签可以注册0个或1个回调函数。

    • 如果在已使用回调的标签上再注册,将返回PLCTAG_ERR_DUPLICATE。注册成功返回PLCTAG_STATUS_OK
    • 如果在没有回调的标签上取消注册,将返回PLCTAG_ERR_NOT_FOUND。移除成功返回PLCTAG_STATUS_OK
  2. 库提供了一个在标签上注册回调的函数。以下事件会产生对回调函数的调用:

  • PLCTAG_EVENT_CREATED (7) - 标签创建完成后调用回调。创建的最终状态也会传递给回调。在某些情况下,这不太受支持,因此仅依赖于普通标签,而不是像@tags这样的标签。
  • PLCTAG_EVENT_READ_STARTED (1) - 已请求读取标记。在调用基础协议实现之前立即调用回调。
  • PLCTAG_EVENT_READ_COMPLETED (2) - 读取完成后调用回调。读取的最终状态也会传递给回调。
  • PLCTAG_EVENT_WRITE_STARTED (3) - 与读取一样,在请求写入时调用回调。回调可以更改标签中的数据,更改将发送到 PLC。
  • PLCTAG_EVENT_WRITE_COMPLETED (4) - 当 PLC 指示写入已完成时调用回调。写入状态将传递给回调。
  • PLCTAG_EVENT_ABORTED (5) - 当某些东西调用标签上的 plc_tag_abort() 时调用回调函数。
  • PLCTAG_EVENT_DESTROYED (6) - 销毁标记时调用回调函数。此时对标记调用任何 API 函数是不安全的。这纯粹是为了回调来管理任何应用程序状态。
  1. 本部分理解不全面,具体请读者自行看API文档理解。
2.5.2 Log Callback(日志回调)
  1. 可以将所有日志记录重定向到自己提供的回调函数。两个API如下:
//注册函数
//tag_id:标签句柄
//debug_level:调试级别。不同的调试级别,对应不同的详细程度。具体内容见本文的调试部分。
//message:日志信息的文本字符串。由库管理,不归程序所有,不要释放字符串。如果要存储或更改,需要在副本上操作。
int plc_tag_register_logger(void (*log_callback_func)(int32_t tag_id, int debug_level, const char *message));//删除注册
int plc_tag_unregister_logger(void);
  1. 只能注册一个。整个库将使用这个回调来输出日志,而不是默认输出到stderr
  2. 注意事项:
    • 日志回调将从多个线程调用,甚至同时调用。所以代码必须能感知线程和线程安全。
    • 日志回调将使用一个或多个互斥锁。不能调用除plc_tag_decode_error()以外的任何标签API函数。否则,库可能会挂起。
    • 日志记录信息来自库的核心程序。其中许多对延迟非常敏感,不要阻止或延迟将日志回调返回到库的操作。
    • message的管理。详见上面的注释。

2.6 Aborting an Operation(中止操作)

  1. 在某些情况下,使用库的程序可能会决定终止对标签的待定操作。例如,如果标签操作没有设超时值,那么程序会自行超时,并调用plc_tag_abort()函数来停止任何正在进行的操作。
int plc_tag_abort(int32_t tag);

2.7 Reading a Tag(读标签)

  1. 读取标签会把读到的数据导入运行库的PC本地内存。数据不会自动更新。如果需要定期查找数据,则需要定期读取标签。
int plc_tag_read(int32_t tag, int timeout);
//tag:标签句柄。
//timeout:以毫秒为单位。如果值为0,该函数将设置读取请求并立即返回。如果超时值大于0,则函数等待该毫秒数,以便读取操作完成。如果超时,则中止操作,返回PLCTAG_ERR_TIMEOUT。
  1. 函数返回状态码(见2.2)。
    • 操作成功,返回PLCTAG_STATUS_OK
    • timeout为0,通常返回PLCTAG_STATUS_PENDING
    • 操作失败,返回相应状态码

2.8 Retrieving Tag Status(获取标签状态)

  1. 可以使用下面函数获取标签状态。
int plc_tag_status(int32_t tag);
//返回当前标签状态的状态码

2.9 Writing a Tag(写标签)

  1. 可以通过plc_tag_write()函数写入目标PLC。但写之前,要通过plc_tag_set_X()函数设置数据。
int plc_tag_write(int32_t tag, int timeout);

3.0 Retrieving/Setting Tag Size(获取/设置标签大小)

3.0.1 获取标签大小
  1. 下面的函数能获取标签的大小。
int plc_tag_get_size(int32_t tag);
  1. 函数返回标签数据的大小(以字节为单位),或错误状态码(负值)。
3.0.2 设置标签大小
  1. 该函数设置标签的基础缓存区大小(以字节为单位)。这是高级API函数调用,通常不使用,除非你使用的是原始CIP标签。
int plc_tag_set_size(int32_t tag, int new_size);
  1. 如果新size大于旧size,则添加的元素可能包含垃圾数据。如果新size小于旧size,则较高的偏移量将被切断,并且该数据永久丢失。
  2. 函数返回标签内部数据缓冲区的旧size(以字节为单位),或错误状态码(负值)。

3.1 Getting Tag Data Elements(获取标签数据元素)

  1. get函数:从标签数据的字节偏移量处获取函数名中大小的值。示例如下:
//tag:标签句柄
//offset:字节偏移量。比如,64字节的数据,要获取2字节开始的32位数据,则offset为2。
//函数返回32位(4字节)int值
int32_t plc_tag_get_int32(int32_t tag, int offset);
  1. set函数:执行get函数的相反操作,并将传递的值(使用适当的字节数)放在标签数据中传递的字节偏移量处。
int plc_tag_set_int32(int32_t, int offset, int32_t val);
  1. get函数:无符号(函数名)get函数出错时,返回UINT_MAX值,比如:get_uint16(),错误返回65535。有符号get出错时,返回INT_MIN值。可以用plc_tag_status判断错误或正确。
  2. set函数:正常返回PLCTAG_STATUS_OK,错误返回状态码。
  3. 各种位数的访问函数、bit操作、string操作、raw byte操作等详见API文档。

3.2 Tag Internal Attribute Functions(标签内部属性函数)

  1. 函数如下:
int plc_tag_get_int_attribute(int32_t tag, const char *attrib_name, int default_value);
int plc_tag_set_int_attribute(int32_t tag, const char *attrib_name, int new_value);
  1. get函数:必须提供标签句柄、属性名称、找不到属性时返回的默认值。
  2. set函数:
    • 操作正常,函数返回PLCTAG_STATUS_OK
    • 如果标签不支持该属性,则返回PLCTAG_ERR_NOT_FOUND
    • 如果新属性值为非法值,则返回PLCTAG_ERR_OUT_OF_BOUNDS
  3. 目前支持以下属性。表格第一列是属性名称,第二列表示该属性可读/可写,第三列表示该属性属于库还是标签,第四列大概说明属性意义。
属性R/W标签/库
意义
debugR/W获取/设置标签的调试级别。该功能与plc_tag_set_debug_level()重复。
version_majorR获取库版本的主版本。例如,库版本为2.5.1,则该属性返回2。
version_minorR获取库版本的次版本。例如,库版本为2.5.1,则该属性返回5。
version_patchR获取库版本的补丁版本。例如,库版本为2.5.1,则该属性返回1。
sizeR标签获取标签使用的大小(以字节为单位)。该功能与plc_tag_get_size()重复。
read_cache_msR/W标签获取/设置缓存读取结果的时间量(以毫秒为单位)。
elem_sizeR标签获取标签单个元素的大小(以字节为单位)。类比,将标签视为数组,则大小返回1。
elem_countR标签如果标签是数组,则返回标签大小(以元素数为单位),否则返回1。

3.3 Debugging(调试)

  1. 使用该库时,有三种方法可以设置调试级别(出于版本历史原因),不过首选第三个:

    • 创建标签时向属性字符串添加调试属性:“protocol=XXX&…&debug=4”
    • 使用plc_tag_set_int_attribute() debug函数设置属性
    • 使用plc_tag_set_debug_level()函数
  2. 调试级别如下,数字越大,输出信息越详细越多。请选择合适级别。

  • PLCTAG_DEBUG_NONE (0) - 禁用调试输出
  • PLCTAG_DEBUG_ERROR (1) - 仅输出错误。一般来说,这些错误对图书馆的运作是致命的。
  • PLCTAG_DEBUG_WARN (2) - 输出警告,例如在检查格式错误的标记属性字符串或从 PLC 报告意外问题时发现错误。
  • PLCTAG_DEBUG_INFO (3) - 输出有关库中内部调用的诊断信息。包括一些数据包转储。
  • PLCTAG_DEBUG_DETAIL (4) - 输出有关库中执行的代码的详细诊断信息,包括数据包转储。
  • PLCTAG_DEBUG_SPEW (5) - 输出非常详细的信息。除非您尝试调试有关每个互斥锁和释放的详细信息,否则不要使用它。每毫秒将输出多行输出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109861.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【STM32】---存储器,电源核时钟体系

一、STM32的存储器映像 1 文中的缩写 2 系统构架(原理图) 3. 存储器映像 (1)STM32是32位CPU,数据总线是32位的 (2)STM232的地址总线是32位的。(其实地址总线是32位不是由数据总线是…

EV SSL数字证书贵吗

EVSSL证书通常适用于具有高需求的网站和企业,特别是涉及在线交易、金融服务、电子商务平台等需要建立用户信任的场景。大型企业、金融机构、电子商务平台等可以受益于使用EV证书来提升品牌形象和安全性。 申请EVSSL证书(Extended Validation SSL certifi…

极光笔记 | 发送功能使用技巧分享

在全球化竞争激烈的商业环境中,高效的消息通知解决方案是企业成功的关键。EngageLab作为一家专注于海外市场的消息服务平台,为全球企业提供了一体化的消息通知解决方案。其中,EngageLab的国际邮件发送是其强大而灵活的产品服务之一。本文将与…

5.覆盖增强技术——PUCCHPUSCH

PUSCH增强方案的标准化工作 1.PUSCH重复传输类型A增强,包括两种增强机制:增加最大重复传输次数,以及基于可用上行时隙的重复传输次数技术方式。 2.基于频域的解决方案,包括时隙间/时隙内跳频的增强 3.支持跨多个时隙的传输块&…

苹果10月24日推送iOS 17.1:修复iPhone 12辐射超标问题 信号会更差

前段时间在iPhone 15系列发布的当天,法国突然宣布iPhone 12不能在该国销售,理由是iPhone 12超过了当地无线电频率暴露的法定范围。 根据法国监管机构ANFR(国家频率管理局)发布的最新消息,苹果将会在10月24日推送iOS 17.1正式版,届…

jmeter(三十三):阶梯线程组Stepping Thread Group,并发线程Concurrency Thread Group

Stepping Thread Group参数详解 this group will start:表示总共要启动的线程数;若设置为 100,表示总共会加载到 100 个线程first,wait for:从运行之后多长时间开始启动线程;若设置为 0 秒,表示运行之后立即启动线程then start:初次启动多少个线程;若设置为 0 个,表示…

php如何在header增加key,sign,timestamp?怎么鉴权?

在PHP中,您可以通过在HTTP请求的Header中增加Key、Sign和Timestamp等信息来进行安全性鉴权。 以下是一种基本的思路和示例,用于说明如何实现这种鉴权机制: 生成Key和Sign: 服务端和客户端之间共享一个密钥(Key&#x…

移远通信携手MIKROE推出搭载LC29H系列模组的Click boards开发板,为物联网应用带来高精定位服务

近日,移远通信与MikroElektronika(以下简称“MIKROE”)展开合作,基于移远LC29H系列模组推出了多款支持实时动态载波相位差分技术(RTK)和惯性导航(DR)技术的Click Boards™ 开发板&am…

MySQL 8.0 OCP认证精讲视频、环境和题库之四 多实例启动 缓存、事务、脏读

一、配置第一个mysqld服务 1、编辑选项文件,指定以下选项: [mysqld] basedir/mysql80 datadir/mysql80/data1 socket/mysql80/data1/mysqld.sock pid-file/mysql80/data1/mysqld.pid log-error/mysql80/dat…

【计算机毕业设计】python在线课程培训学习考试系统637r7-PyCharm项目

使用说明 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 使用PyCharm 导入项目,修改配置,运行项目; 将项目中config.ini配置文件中的数据库配置改为自己的配置,…

文本识别工具 TextSniper 免激活for Mac

TextSniper 是一款 macOS 平台上的文本提取工具,它可以将屏幕上的文字内容快速转换为可编辑的文本。无论是从图像、视频、PDF 文件还是其他类型的文档中提取文字,TextSniper 都提供了便捷的功能。 以下是 TextSniper 的一些主要特点和功能: …

云原生SIEM解决方案

云原生(Cloud Native)是一种基于云计算的软件开发和部署方法论,它强调将应用程序和服务设计为云环境下的原生应用,以实现高可用性、可扩展性和灵活性。 云原生的优势有哪些 高可用性:云原生可以实现应用程序的高可用…

XTU-OJ 1295-Flawless Prime

题目描述 如果一个素数,依次去掉最高位得到一个数,这个数无前导0,并仍是素数的话,我们称其为“无瑕素数”。 比如317是素数,去掉最高位3得到17仍然是素数,再去掉最高位1得到7,仍然是素数&#x…

一篇文章讲明白double、float丢失精度的问题

1.背景 1.10.1 1.2000000000000002 发现上面计算的值竟然和数学计算不一致 2. 问题 计算机是通过二进制计算的,如果我们在二进制的视角来看待上面问题,就很容易发现问题了。 例如:把「0.1」转成二进制的表示,然后还原成十进制&…

java监控目录实时上传HDFS

背景描述&#xff1a; 为了满足linux服务器上特定目录的非结构化文件的实时监控&#xff0c;并上传HDFS 使用的方法 Apache的Commons-IO&#xff0c;来实现文件的监控功能 所需要的pom <dependencies><dependency><groupId>org.apache.hadoop</groupI…

选择什么电容笔比较好?平板手写笔推荐

由于苹果Pencil的热销&#xff0c;让华国内市场上&#xff0c;也出现了不少的平替式电容笔&#xff0c;这些产品&#xff0c;有好有坏&#xff0c;价格也很公道。不过&#xff0c;也有很多产品的价格都很平价。我是一个拥有多年经验的数码发烧友&#xff0c;在前几年就开始用上…

嵌入式Linux运行一定需要MMU吗

为什么需要MMU &#xff1f; 我们知道应用程序是不能随意访问内存的&#xff0c;如果让应用程序直接访问物理内存&#xff0c;那么计算机是很危险的&#xff0c;计算机内存的所有内容将被完全暴露出来。 所以出现了mmu&#xff0c;mmu是内存管理单元&#xff0c;应用程序访问…

docker load and build过程的一些步骤理解

docker load 命令执行原理 “docker load” command, the following steps are followed to load an image from a specified tar file to the local image repository: Parsing the tar file: Docker first parses the tar file to check its integrity and verify the form…

Spring Boot关掉APR

在Spring Boot中&#xff0c;可以通过设置环境变量或配置文件来关闭APR&#xff08;Apache Portable Runtime&#xff09;。下面是两种常用的方法&#xff1a; 方法一&#xff1a;设置环境变量 在启动Spring Boot应用程序时&#xff0c;可以通过设置-DuseApr环境变量来控制是…

链表 oj2 (7.31)

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 我们通过头插来实现 将链表上的节点取下来&#xff08;取的时候需要记录下一个节点&#xff09;&#xff0c;形成新的链表&#xff0c;对新的链表进行头插。 /*** Definition for singly-linked list.* struct ListNode…