概述
0x00
这一节,我们介绍下常用的C语言字符串处理函数和内存管理函数。
0x01
字符串处理函数:
strstr:返回字符串中首次出现子串的地址
详解地址:http://c.biancheng.net/cpp/html/174.html。
strchr:查找某字符在字符串中首次出现的位置
详解地址:
http://c.biancheng.net/cpp/html/161.html
。
strncpy:复制字符串的前n个字符
详解地址:
http://c.biancheng.net/cpp/html/170.html。
strncat:在字符串的结尾追加n个字符
详解地址:
http://c.biancheng.net/cpp/html/169.html。
strcpy:复制字符串
详解地址:
http://c.biancheng.net/cpp/html/164.html。
strcat:连接字符串
详解地址:
http://c.biancheng.net/cpp/html/160.html。
strlen:返回字符串的长度
详解地址:
http://c.biancheng.net/cpp/html/167.html。
strcmp:比较字符串(区分大小写)
详解地址:
http://c.biancheng.net/cpp/html/162.html。
注意:上面例子中多次用到字符数组和字符串。
字符数组是可以被修改的,字符串是只读的,不能被修改。
0x02
内存管理函数:
memset:将内存的前n个字节设置为特定的值
详解地址:
http://c.biancheng.net/cpp/html/157.html。
memcpy:复制内存内容(忽略 )
详解地址:
http://c.biancheng.net/cpp/html/155.html。与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“ ”而结束。
0x03
下面我们重点讲一下内存管理函数mmap:
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.
- length: 将文件的多大长度映射到内存.
- prot: 映射区的保护方式, 可以是:
- PROT_EXEC: 映射区可被执行.
- PROT_READ: 映射区可被读取.
- PROT_WRITE: 映射区可被写入.
- PROT_NONE: 映射区不能存取.
- flags: 映射区的特性, 可以是:
- MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.
- MAP_PRIVATE: 对此区域所做的修改不会写回原文件, 且不允许其他映射该文件的进程共享.
- MAP_ANONYMOUS:匿名创建映射区域, fd为-1, offset为0.
- MAP_FIXED:后面介绍
- fd: 由open返回的文件描述符, 代表要映射的文件.
- offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.
返回值为映射后的虚拟地址:
1、如果addr为NULL,那么这个虚拟地址由系统指定。
2、如果addr不为NULL,并且flag不为MAP_FIXED,那么最后分配的虚拟地址尽量与设置的值相近。
3、如果addr不为NULL,并且flag为MAP_FIXED,那么最后分配的虚拟地址必须和addr保持一致,否则出错。
length为要映射的文件内容大小,如果大小大于4096(一页),小于8192(两页),那么会分配两页的内存。
如果大小不是页的整倍数,具体分三种情况来讨论:
情形一:一个文件的大小是5000字节,mmap函数从一个文件的起始位置开始,映射5000字节到虚拟内存中。
分析:因为单位物理页面的大小是4096字节,虽然被映射的文件只有5000字节,但是对应到进程虚拟地址区域的大小需要满足整页大小,因此mmap函数执行后,实际映射到虚拟内存区域8192个 字节,5000~8191的字节部分用零填充。映射后的对应关系如下图所示:
此时:
1、读/写前5000个字节(0~4999),会返回操作文件内容。
2、读字节5000~8191时,结果全为0。写5000~8191时,进程不会报错,但是所写的内容不会写入原文件中 。
3、读/写8192以外的磁盘部分,会返回一个SIGSECV错误。
情形二:一个文件的大小是5000字节,mmap函数从一个文件的起始位置开始,映射15000字节到虚拟内存中,即映射大小超过了原始文件的大小。
分析:由于文件的大小是5000字节,和情形一一样,其对应的两个物理页。那么这两个物理页都是合法可以读写的,只是超出5000的部分不会体现在原文件中。由于程序要求映射15000字节,而文件只占两个物理页,因此8192字节~15000字节都不能读写,操作时会返回异常。如下图所示:
此时:
1、进程可以正常读/写被映射的前5000字节(0~4999),写操作的改动会在一定时间后反映在原文件中。
2、对于5000~8191字节,进程可以进行读写过程,不会报错。但是内容在写入前均为0,另外,写入后不会反映在文件中。
3、对于8192~14999字节,进程不能对其进行读写,会报SIGBUS错误。
4、对于15000以外的字节,进程不能对其读写,会引发SIGSEGV错误。
情形三:一个文件初始大小为0,使用mmap操作映射了1000*4K的大小,即1000个物理页大约4M字节空间,mmap返回指针ptr。
分析:如果在映射建立之初,就对文件进行读写操作,由于文件大小为0,并没有合法的物理页对应,如同情形二一样,会返回SIGBUS错误。
但是如果,每次操作ptr读写前,先增加文件的大小,那么ptr在文件大小内部的操作就是合法的。
例如,文件扩充4096字节,ptr就能操作ptr ~ [ (char)ptr + 4095]的空间。只要文件扩充的范围在1000个物理页(映射范围)内,ptr都可以对应操作相同的大小。 这样,方便随时扩充文件空间,随时写入文件,不造成空间浪费。
关于mmap函数,更加详细的内容请参考:
1、
mmap(2) - Linux man page
2、
认真分析mmap:是什么 为什么 怎么用
3、
Linux mmap函数简介
最后
以上就是机灵保温杯为你收集整理的C语言字符串处理及内存管理函数的全部内容,希望文章能够帮你解决C语言字符串处理及内存管理函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复