C语言字符串处理及内存管理函数

    xiaoxiao2024-07-26  11

        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:复制内存内容(忽略\0)     详解地址: http://c.biancheng.net/cpp/html/155.html。与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“\0”而结束。     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函数简介

    转载请注明原文地址: https://ju.6miu.com/read-1291068.html
    最新回复(0)