当前位置: 首页 > news >正文

Linux中字符串拷贝函数strlcpy的实现

字符串拷贝函数strlcpy

size_t strlcpy(char *dest, const char *src, size_t size)
{size_t ret = strlen(src);if (size) {size_t len = (ret >= size) ? size-1 : ret;memcpy(dest, src, len);dest[len] = '\0';}return ret;
}
static inline void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__("rep ; movsl\n\t""testb $2,%b4\n\t""je 1f\n\t""movsw\n""1:\ttestb $1,%b4\n\t""je 2f\n\t""movsb\n""2:": "=&c" (d0), "=&D" (d1), "=&S" (d2):"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from): "memory");
return (to);
}

1. strlcpy函数功能概述

strlcpy 是一个安全的字符串拷贝函数,可以防止缓冲区溢出

1.1. 第一段:获取源字符串长度

size_t strlcpy(char *dest, const char *src, size_t size)
{size_t ret = strlen(src);
  • dest:目标缓冲区
  • src:源字符串
  • size:目标缓冲区大小
  • ret = strlen(src) 先计算源字符串的长度

1.2. 第二段:安全检查和非空缓冲区处理

        if (size) {size_t len = (ret >= size) ? size-1 : ret;
  • if (size) 检查目标缓冲区大小是否为0
  • 三元运算符计算实际拷贝长度:
    • 如果源字符串长度 >= 缓冲区大小:拷贝 size-1 个字符(留1字节给结束符)
    • 否则:拷贝整个源字符串长度

1.3. 第三段:内存拷贝和字符串终止

                memcpy(dest, src, len);dest[len] = '\0';}return ret;
}
  • memcpy(dest, src, len) 拷贝指定长度的字符
  • dest[len] = '\0' 确保目标字符串正确终止
  • return ret 返回源字符串长度(不是实际拷贝长度)

2. __memcpy 函数功能概述

这是一个用内联汇编优化的内存拷贝函数

2.1. 第一段:函数声明和变量定义

static inline void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
  • to:目标内存地址
  • from:源内存地址
  • n:要拷贝的字节数
  • d0, d1, d2:临时变量用于汇编约束

2.2. 第二段:主拷贝循环 - 按4字节拷贝

__asm__ __volatile__("rep ; movsl\n\t"
  • rep movsl 重复执行 movsl,每次拷贝4字节(双字)
  • ecx 寄存器控制重复次数(n/4
  • 这是最高效的拷贝方式,一次处理4字节

2.3. 第三段:处理剩余2字节

        "testb $2,%b4\n\t""je 1f\n\t""movsw\n"
  • testb $2,%b4 测试字节操作数4的低字节第1位(判断是否剩余2字节)
  • je 1f 如果没有剩余2字节,跳转到标签1
    • je: 当ZF=1时执行跳转,即testb结果为0时
  • movsw 拷贝2字节

2.4. 第四段:处理剩余1字节

        "1:\ttestb $1,%b4\n\t""je 2f\n\t""movsb\n""2:"
  • 1:\ttestb $1,%b4 标签1:测试是否剩余1字节,注意\t是制表符
  • je 2f 如果没有剩余1字节,跳转到标签2(结束)
  • movsb 拷贝1字节

2.5. 第五段:汇编约束条件

        : "=&c" (d0), "=&D" (d1), "=&S" (d2):"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from): "memory");

输出操作数:

  • "=&c" (d0)d0 绑定到 ecx 寄存器(& 表示早期破坏)
  • "=&D" (d1)d1 绑定到 edi 寄存器
  • "=&S" (d2)d2 绑定到 esi 寄存器

输入操作数:

  • "0" (n/4)n/4 使用与操作数0相同的约束(ecx,重复次数)
  • "q" (n)n 使用字节寄存器(a,b,c,d之一)
  • "1" ((long) to)to 使用与操作数1相同的约束(edi,目标指针)
  • "2" ((long) from)from 使用与操作数2相同的约束(esi,源指针)

破坏描述:

  • "memory":告诉编译器内存内容被修改

2.6. 第六段:函数返回

return (to);
}
  • 返回目标指针(标准memcpy行为)

3. 函数工作流程图

开始strlcpy
ret = len of src
size > 0?
直接返回ret
ret >= size?
len = size-1
len = ret
memcpy dest,src,len
destlen = '\0'

4. 寄存器使用说明

寄存器用途
ecx重复计数器(n/4)
edi目标指针(to)
esi源指针(from)
字节寄存器存储n用于位测试

5. 汇编指令详解

  • rep movsl:重复拷贝双字(4字节),ecx
  • testb:测试字节的特定位
  • je:等于零时跳转
  • movsw:拷贝字(2字节)
  • movsb:拷贝字节(1字节)

6. 拷贝策略分析

优化思路

  1. 批量处理:先用 movsl 按4字节批量拷贝
  2. 剩余处理:按2字节和1字节处理剩余部分
  3. 位测试:用位运算高效判断剩余字节数

字节数处理

n % 4 的可能情况:
0: 直接由movsl处理完
1: movsl + movsb
2: movsl + movsw  
3: movsl + movsw + movsb
http://www.dtcms.com/a/486875.html

相关文章:

  • PostgreSQL 18 发布
  • DrissionPage下载文件
  • 观澜做网站公司百度seo网站在线诊断
  • 电子商务网站建设题目男女直接做网站
  • 前端 Web 开发工具全流程指南,打造高效开发与调试体系
  • html网站中文模板下载seo营销型网站
  • 【编号220】中国国内生产总值历史数据汇编1952-2021合订本(PDF扫描版)
  • 百度多久收录一次网站北京企业网站建设飞沐
  • 特斯拉前AI总监开源的一款“小型本地版ChatGPT”,普通家用电脑就能运行!
  • 鸿蒙:创建公共事件、订阅公共事件和退订公共事件
  • 鸿蒙NEXT Function Flow Runtime开发指南:掌握下一代并发编程
  • 遥控器外壳设计网站推荐哈尔滨建设信息网官网
  • 哈夫曼树 红黑树 B树 B+树 WTF!M3?(树形查找)
  • 【Linux内核】DMABUF 与文件描述符(fd)的绑定过程
  • AngularJS 模型
  • 网页设计与网站建设毕业设计成全看免费观看
  • MySQL数据库操作全指南(一)
  • 【项目】年会抽奖系统
  • 烟台建站程序如何用电脑主机做网站
  • Spring Boot 统一异常处理机制:设计原理与最佳实践
  • 【jenkins】构建安卓
  • Spring Boot 集成 SpringDoc OpenAPI(Swagger)实战:从配置到接口文档落地
  • 基于目标信息最大化的高分辨率雷达波形设计——论文阅读
  • 网站建设毕业答辩ppt模板顶尖网站建设
  • MCP传输模式选择指南:Stdio与HTTP的终极对比
  • 网站建设实习招聘wordpress 问卷调查
  • 效果图制作网站有哪些医院网站制作公司
  • MySQL 连接类型介绍
  • 网站开发编程入门学习网站设计要考虑的因素
  • sk09.【scikit-learn基础】--『无监督学习』之K均值聚类