get_memory(char* p,int num)

本文通过C语言中的一段内存分配代码及其反汇编过程,详细解析了如何使用malloc进行内存分配,并探讨了指针参数在函数调用过程中是如何被处理的。指出在函数内部修改指针本身不会影响外部调用者,但可以通过返回值来更新指针所指向的内容。

char* get_memory(char* p,int num)
{
    p=(char*)malloc(num*sizeof(char));
 
    return p;
}

 

 

 

 char *str = NULL;
 str = get_memory(str,12);
 strcpy(str,"helloWorld!");
 free(str);

 

反汇编

 

00411420    55              push    ebp
00411421    8BEC            mov     ebp, esp
00411423    81EC CC000000   sub     esp, 0CC
00411429    53              push    ebx
0041142A    56              push    esi
0041142B    57              push    edi
0041142C    8DBD 34FFFFFF   lea     edi, dword ptr [ebp-CC]
00411432    B9 33000000     mov     ecx, 33
00411437    B8 CCCCCCCC     mov     eax, CCCCCCCC
0041143C    F3:AB           rep     stos dword ptr es:[edi]
0041143E    C745 F8 0000000>mov     dword ptr [ebp-8], 0
00411445    6A 0C           push    0C
00411447    8B45 F8         mov     eax, dword ptr [ebp-8]        
0041144A    50              push    eax
0041144B    E8 2CFDFFFF     call    0041117C                            ;get_memory
00411450    83C4 08         add     esp, 8
00411453    8945 F8         mov     dword ptr [ebp-8], eax          ;返回eax给str
00411456    68 3C564100     push    0041563C                         ; ASCII "helloWorld!"
0041145B    8B45 F8         mov     eax, dword ptr [ebp-8]         
0041145E    50              push    eax
0041145F    E8 46FCFFFF     call    004110AA                             ;strcpy
00411464    83C4 08         add     esp, 8
00411467    8BF4            mov     esi, esp
00411469    8B45 F8         mov     eax, dword ptr [ebp-8]
0041146C    50              push    eax
0041146D    FF15 C4824100   call    dword ptr [<&MSVCR80D.free>]     ; MSVCR80D.free
00411473    83C4 04         add     esp, 4
00411476    3BF4            cmp     esi, esp
00411478    E8 BEFCFFFF     call    0041113B
0041147D    33C0            xor     eax, eax

 

我们看 call    0041117C                            ;get_memory

004113B0    55              push    ebp
004113B1    8BEC            mov     ebp, esp
004113B3    81EC C0000000   sub     esp, 0C0
004113B9    53              push    ebx
004113BA    56              push    esi
004113BB    57              push    edi
004113BC    8DBD 40FFFFFF   lea     edi, dword ptr [ebp-C0]
004113C2    B9 30000000     mov     ecx, 30
004113C7    B8 CCCCCCCC     mov     eax, CCCCCCCC
004113CC    F3:AB           rep     stos dword ptr es:[edi]
004113CE    8BF4            mov     esi, esp
004113D0    8B45 0C         mov     eax, dword ptr [ebp+C]
004113D3    50              push    eax                                                          ; size
004113D4    FF15 CC824100   call    dword ptr [<&MSVCR80D.malloc>]   ; MSVCR80D.malloc
004113DA    83C4 04         add     esp, 4
004113DD    3BF4            cmp     esi, esp
004113DF    E8 57FDFFFF     call    0041113B
004113E4    8945 08         mov     dword ptr [ebp+8], eax                       ;赋值
004113E7    8B45 08         mov     eax, dword ptr [ebp+8]

 

奇怪了, mov     dword ptr [ebp+8], eax 这里已经给str赋值了,那么

str=get_memory(str,12)可以这样写了

 

get_memory(str,12),我们再看看,出错了,

 

 mov     dword ptr [ebp+8], eax 这句的真正含义是  给str的复制值 写入eax

 

函数call的过程回顾一下

00411445    6A 0C           push    0C                                          //参数
00411447    8B45 F8         mov     eax, dword ptr [ebp-8]         //str的复制入栈
0041144A    50              push    eax

 

所以说 mov     dword ptr [ebp+8], eax  是对str的复制值写操作

0041144B    E8 2CFDFFFF     call    0041117C                            ;get_memory
00411450    83C4 08         add     esp, 8

 

这里add esp,8 就清空了

 

所以可以总结一下,函数中的指针参数在函数里不可改变,改变的是指针指向的内容。

 

 

可以给出详细的注释吗 。包括原理,参数等等,我是初学者,/****************************************************************************** * * Copyright (c) 2023 TP-LINK Technologies CO.,LTD. * All rights reserved. * * FILE NAME : at_utils.c * VERSION : 1.0 * DESCRIPTION : AT命令解析工具. * * AUTHOR : tangqilin (tangqilin@tp-link.com.hk) * CREATE DATE : 03/25/2023 * * HISTORY : * 01 03/25/2023 Tang Qilin Create. * ******************************************************************************/ #include "at_utils.h" #include <string.h> #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <stdarg.h> #include <sys/types.h> #include <arpa/inet.h> #include <sys/socket.h> /** * Starts tokenizing an AT response string * returns -1 if this is not a valid response string, 0 on success. * updates *p_cur with current position */ S32 at_tok_start(char **p_cur) { if(*p_cur == NULL) { return -1; } // skip prefix // consume "^[^:]:" *p_cur = strchr(*p_cur, ':'); if(*p_cur == NULL) { return -1; } (*p_cur)++; return 0; } /** return 1 if line starts with prefix, 0 if it does not */ S32 strStarwith(const char *line, const char *prefix) { for( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { if(*line != *prefix) { return 0; } } return *prefix == '\0'; } S32 at_tok_nextlonglong(char **p_cur, long long *p_out) { return at_tok_nextlonglong_base(p_cur, p_out, 10, 0); } S32 at_tok_nextlonglong_base(char **p_cur, long long *p_out, int base, int uns) { char *ret; if(*p_cur == NULL) { return -1; } ret = nextTok(p_cur); if(ret == NULL) { return -1; }else { long long l; char *end; if(uns) { l = strtoull(ret, &end, base); }else { l = strtoll(ret, &end, base); } *p_out = (long long)l; if(end == ret) { return -1; } } return 0; } /** * Parses the next base 10 integer in the AT response line * and places it in *p_out * returns 0 on success and -1 on fail * updates *p_cur */ S32 at_tok_nextint(char **p_cur, int *p_out) { return at_tok_nextint_base(p_cur, p_out, 10, 0); } /** * Parses the next integer in the AT response line and places it in *p_out * returns 0 on success and -1 on fail * updates *p_cur * "base" is the same as the base param in strtol */ S32 at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns) { char *ret; if(*p_cur == NULL) { return -1; } ret = nextTok(p_cur); if(ret == NULL) { return -1; }else { long l; char *end; if(uns) { l = strtoul(ret, &end, base); }else { l = strtol(ret, &end, base); } *p_out = (int)l; if(end == ret) { return -1; } } return 0; } void skipWhiteSpace(char **p_cur) { if (*p_cur == NULL)return; while(**p_cur != '\0' && isspace(**p_cur)) { (*p_cur)++; } } /** * Parses the next base 16 integer in the AT response line * and places it in *p_out * returns 0 on success and -1 on fail * updates *p_cur */ S32 at_tok_nexthexint(char** p_cur, int* p_out) { return at_tok_nextint_base(p_cur, p_out, 16, 1); } S32 at_tok_nextbool(char** p_cur, char* p_out) { int ret; int result; ret = at_tok_nextint(p_cur, &result); if (ret < 0) { return -1; } // booleans should be 0 or 1 if (!(result == 0 || result == 1)) { return -1; } if (p_out != NULL) { *p_out = (char)result; } return ret; } /** returns 1 on "has more tokens" and 0 if no */ S32 at_tok_hasmore(char** p_cur) { return !(*p_cur == NULL || **p_cur == '\0'); } S32 at_tok_count(const char* in_line) { int commas = 0; const char* p; if (!in_line) return 0; for (p = in_line; *p != '\0'; p++) { if (*p == ',') commas++; } return commas; } //fmt: d ~ int, x ~ hexint, b ~ bool, s ~ str S32 at_tok_scanf(const char* in_line, const char* fmt, ...) { int n = 0; int err; va_list ap; const char* p = fmt; void* d; void* dump; static char s_line[1024]; char* line = s_line; if (!in_line) return 0; strncpy(s_line, in_line, sizeof(s_line)); va_start(ap, fmt); err = at_tok_start(&line); if (err < 0) goto error; for (; *p; p++) { if (*p == ',' || *p == ' ') continue; if (*p != '%') { goto error; } p++; d = va_arg(ap, void*); if (!d) d = &dump; if (!at_tok_hasmore(&line)) break; if (*line == '-' && *(line + 1) == ',') { line += 2; n++; if (*p == 'd') * (int*)d = -1; continue; } switch (*p) { case 'd': err = at_tok_nextint(&line, (int*)d); if (err < 0) goto error; break; case 'x': err = at_tok_nexthexint(&line, (int*)d); if (err < 0) goto error; break; case 'b': err = at_tok_nextbool(&line, (char*)d); if (err < 0) goto error; break; case 's': err = at_tok_nextstr(&line, (char**)d); //if strdup(line), here return free memory to caller if (err < 0) goto error; break; case 'l': err = at_tok_nextlonglong(&line, (long long*)d); if(err < 0) goto error; break; default: goto error; break; } n++; } va_end(ap); error: //free(line); return n; } void skipNextComma(char **p_cur) { if(*p_cur == NULL) return; while(**p_cur != '\0' && **p_cur != ',') { (*p_cur)++; } if(**p_cur == ',') { (*p_cur)++; } } char *nextTok(char **p_cur) { char *ret = NULL; skipWhiteSpace(p_cur); if(*p_cur == NULL) { ret = NULL; } else if(**p_cur == '"') { (*p_cur)++; ret = strsep(p_cur, "\""); skipNextComma(p_cur); }else { ret = strsep(p_cur, ","); } return ret; } S32 at_tok_nextstr(char **p_cur, char **p_out) { if(*p_cur == NULL) { return -1; } *p_out = nextTok(p_cur); return 0; } char* skipLFCR(char *str) { char *p = NULL; int len = 0; int start = 0; if(NULL == str) { return NULL; } p = str; len = strlen(str); while (start < len) { if ('\r' == *p || '\n' == *p) { p++; start++; } else { break; } } if (start == len) { return NULL; } return p; } /* dot num ipv4 3 ipv4+mask 7 ipv6 15 ipv6+mask 31 */ int get_ip_mask(char *ip_and_mask, char* ip, char* mask) { int len = 0; int i = 0; int dot_num = 0; if(ip_and_mask == NULL || ip == NULL || mask == NULL) { return -1; } len = strlen(ip_and_mask); for(i = 0; i < len; i++) { if(ip_and_mask[i] == '.') { dot_num++; } } if(dot_num == 31) { dot_num = 0; for(i = 0; i < len; i++) { if(ip_and_mask[i] == '.') { dot_num++; if(dot_num == 16) { break; } } } memcpy(ip, ip_and_mask, i); memcpy(mask, &ip_and_mask[i+1], len-i-1); } else if(dot_num == 15) { memcpy(ip, ip_and_mask, strlen(ip_and_mask)); } else if(dot_num == 7) { dot_num = 0; for(i = 0; i < len; i++) { if(ip_and_mask[i] == '.') { dot_num ++; if(dot_num == 4) { break; } } } memcpy(ip, ip_and_mask, i); memcpy(mask, &ip_and_mask[i+1], len-i-1); } else if(dot_num == 3) { memcpy(ip, ip_and_mask, strlen(ip_and_mask)); } else { return -1; } return 0; } int is_ipv4(char *ip) { int len = 0; int i = 0; char *str = NULL; int dot_num = 0; if(ip == NULL) { return -1; } str = ip; for(i = 0, len = strlen(str); i < len; i++) { if(str[i] == '.') { dot_num ++; } } if(dot_num == 3) { return 1; } else if(dot_num == 15) { return 0; } else { return -1; } } int get_ipv4_gw(char * ip, char * gw) { int len =0; int i =0; char * str = NULL; int dot_num = 0; if(ip == NULL) { return -1; } str = ip; for( i = 0, len = strlen(str); i < len; i++) { if(str[i]=='.') { dot_num++; if(dot_num == 3) { i++; break; } } } if (dot_num != 3) { return -1; } int last_num = atoi(str+i); if (last_num < 0 || last_num > 255) { return -1; } memcpy(gw, str, len); memset(gw+i, 0, 4); /* 如果获取的IP地址最后一字节为255,则将网关的最后一字节设置为1 */ if(255 - last_num == 0) { snprintf(gw+i, 4, "%d", 1); }else { snprintf(gw+i, 4, "%d", 255-last_num); } return 0; } #ifdef CONFIG_IPV6 int charCountInStr(const char* str, char ch) { int i; int num = 0; for (i=0; str[i] != '\0'; i++) { if (str[i] == ch) { num ++; } } return num; } /* return 1 success * return 0 failed */ int convertDotNotation2Ipv4Uint (const char *source, unsigned int *addr, unsigned int *mask) { int i; int count = charCountInStr(source, '.'); char * end; for (i = 0; i <= count; i++) { if (i < 4) { addr[0] |= strtoul(source, &end, 10) << i * 8; } else if (i < 8) { mask[0] |= strtoul(source, &end, 10) << (i - 4) * 8; } if (i == count || *end == '\0') { //RLOGI(convertDotNotation2Ipv4Uint, "%s, count=%d", __FUNCTION__, count); //LOG_I( "%s, count=%d", "convertDotNotation2Ipv6Uint", count); return 1; } else if (*end != '.') { return 0; } source = end + 1; } return 0; } /* return 1 success * return 0 failed */ int convertDotNotation2Ipv6Uint (const char *source, unsigned int *addr, unsigned int *mask) { int i; int count = charCountInStr(source, '.'); char * end; for (i = 0; i <= count; i++) { if (i < 4) { addr[0] |= strtoul(source, &end, 10) << i * 8; } else if (i < 8) { addr[1] |= strtoul(source, &end, 10) << (i - 4) * 8; } else if (i < 12) { addr[2] |= strtoul(source, &end, 10) << (i - 8) * 8; } else if (i < 16) { addr[3] |= strtoul(source, &end, 10) << (i - 12) * 8; } else if (i < 20) { mask[0] |= strtoul(source, &end, 10) << (i - 16) * 8; } else if (i < 24) { mask[1] |= strtoul(source, &end, 10) << (i - 20) * 8; } else if (i < 28) { mask[2] |= strtoul(source, &end, 10) << (i - 24) * 8; } else if (i < 32) { mask[3] |= strtoul(source, &end, 10) << (i - 28) * 8; } if (i == count || *end == '\0') { //RLOGI(convertDotNotation2Ipv6Uint, "%s, count=%d", __FUNCTION__, count); //LOG_I( "%s, count=%d", "convertDotNotation2Ipv6Uint", count); return 1; } else if (*end != '.') { return 0; } source = end + 1; } return 0; } /* return 1 success * return 0 failed */ int convertDotNotation2IpUint(int af, const char *source, unsigned int *addr, unsigned int *mask) { if (af == AF_INET) { return convertDotNotation2Ipv4Uint(source, addr, mask); } else { return convertDotNotation2Ipv6Uint(source, addr, mask); } } /* return address family */ int convertDotNotation2IpString(const char *source, char *ipaddress, char *ipmask) { unsigned int addr[4]; unsigned int mask[4]; int af; int ret; int count = charCountInStr(source, '.'); memset(addr, 0, sizeof(addr)); memset(mask, 0, sizeof(mask)); if (count < 8) { af = AF_INET; } else if (count < 32) { af = AF_INET6; } else { return -1; } ret = convertDotNotation2IpUint(af, source, addr, mask); if (ret > 0) { if (ipaddress != NULL) { inet_ntop(af, addr, ipaddress, INET6_ADDRSTRLEN); } if (ipmask != NULL) { inet_ntop(af, mask, ipmask,INET6_ADDRSTRLEN); } } else { printf("%s, covert failed", "convertDotNotation2IpString"); return -1; } return af; } #endif
09-17
设计步骤 2.3.1 数据结构分析 为了实现存储资源的分配和回收,操作系统需要记录内存资源使用情况,即哪些区域尚未分配,哪些区域已经分配以及分配给哪些进程等。为此一般需要两个表,一个为分配表, 另外一个为空闲区域表。前者记录已经分配的区域, 后者记录着所有当前未被进程占用的空闲区域, 如图2-1所示。 显然, 没有记录于表中的区域即为已被进程所占用的非空闲区域,在实际的操作系统中,这些区域登记在进程的PCB中。而PCB中除了关于内存资源的信息外,还有其它大量信息。 由于本设计是对存储管理算法的模拟,所以用一个线程来代表一个进程,用线程驻留区域表来描述线程占用的内存空间,如图2-2所示。 线程名称 驻留区始址 驻留区大小 a 0 10 b 20 20 …… …… …… 图2-2 线程驻留区表 同时,需要一张表来记录各个线程对内存的请求信息,如图2-3所示。 线程名称 请求大小(KB) 预计驻留时间() thread_1 20 4 thread_2 10 5 …… …… …… 图2-3 内存申请表 2.3.2 算法分析 分配时取满足申请要求且长度最小的空闲区域。在实现时, 可将系统中所有的空闲区域按照长度由小到大的次序依次记录于空闲区域表中。与最先适应算法相类似, 当进程申请存储空间时, 系统由表的头部开始查找, 取第一个满足要求的表目。如果该表目所对应的区域长度恰好与所申请的区域长度相同, 则将该区域全部分配给申请者。否则将该区域分割为两部分, 一部分的长度与所申请的长度相同, 将其分配给申请者;另一部分即剩余部分的长度为原长度与分配长度之差, 由于剩余部分的长度已经改变,所以应重新将其按长度从小到大的顺序插入到空闲区域表中。 回收时,不仅要按回收区的首地址查询空闲区表,找到与回收区相临的空闲区,将其合并到相临区中,而且要把合并后的回收区按照长度递增的顺序插入到空闲区域表的适当位置。 2.3.3 设计并分析测试数据 假设初始内存布局如图2-4,图中的起始地址以及大小都以KB来衡量。 起始地址 0 10 20 40 70 80 85 145 160 180 占用者 a b c d e 大 小 10 10 20 30 10 5 60 15 20 20 图2-4初始内存布局 由图2-4可见,初始时共有五个线程驻留在内存,它们是a,b,c,d,e,线程驻留区表如图2-5;还有五个空闲区,空闲区域表如图2-6。 假设现在有三个线程提出内存申请,申请情况见图2-7。经过分析我们得到在每种分配算法下这三个线程所申请到的内存情况。图2-8是最佳适应算法分配情况。 2.3.4 程序设计 程序包含两个文件,一个是头文件variable_partition.h,另一个是源程序文件variable_partition.cpp。在头文件中定义了宏、数据结构、全局变量、函数声明,源程序中含有各个函数的实现。 在头文件中,结构体FREEAREA、REQUIRE_MEMORY、THREAD_RESIDENCE_MEMORY分别对应于图2-1、图2-2、图2-3中的一行,不同之处是为了构成链表在三个结构体中都有前向指针。数组init_free_area_table对应于图2-6,数组init_thread_require_memory_table对应于图2-5,数组init_thread_residence_memory_table对应于图2-7,为了实现动态分配与释放,用链表重新组织空闲区域表、线程驻留区表和内存申请表,全局变量p_free_area_list是空闲区链首,p_thread_require_memory_queue是内存申请队列的队首,p_thread_residence_memory_list是线程驻留区链首,tail_thread_residence_memory_list是线程驻留区链尾,由于线程驻留区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_THREAD_MEMORY_LIST来保护,同理,屏幕是所有线程共享的,所以用临界区变量CS_SCREEN来保护,空闲区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_FREEAREA_LIST来保护。h_thread是线程句柄数组,用来存放各个线程的句柄。 程序共包含13个函数,按照作用可以将它们分成五组。 第一组包括函数print_space()和函数display_thread_residence_memory(),前者用来显示若干个空格,后者用来显示线程驻留区表; 第二组共十一个函数,用来实现最佳适应分配法,它们的名称及功能如图2-9。 函数名称 函数功能 BF_initialize_freearea_list 初始化空闲区链表:按长度递增排序 BF_delete_freearea_list 删除空闲区链表 BF_initialize_require_memory_list 初始化内存申请链表 BF_delete_require_memory_list 删除内存申请链表 BF_initialize_thread_residence_memory_list 初始化线程驻留区链表 BF_delete_thread_residence_memory_list 删除线程驻留区链表 BF_thread 线程函数:申请内存;驻留内存;释放内存 BF_require_memory 申请一段内存,成功时返回起始地址,失败时返回空 BF_release_memory 释放一段内存 BF_insert_freearea 将空闲区按大小递增的次序插入到空闲区链表中 BF() 初始化函数:创建线程并等待它们结束 图2-9 最佳适应分配法的函数及其功能 2.3.5 参考源代码 下面是部分程序的源代码清单。 头文件 variable_partition.h 的清单 #include <windows.h> #include <conio.h> #include <stdlib.h> #include <stdio.h> #include <io.h> #include <string.h> #define MAX_THREAD 3 typedef struct freearea{ //表示空闲区域的数据结构 struct freearea *next; //指向下一个结点的指针 int start_address; //空闲区起始地址 int size; //空闲区大小 }FREEAREA; typedef struct require_memory{ //记录线程申请内存的数据结构 struct require_memory *next; //指向下一个结点的指针 char thread_name[10]; //线程名 int size; //申请内存大小(以KB为单位) int duration; //在内存的驻留时间(以秒为单位) }REQUIRE_MEMORY; typedef struct thread_residence_memory{ //描述线程驻留区的数据结构 struct thread_residence_memory *next; //指向下一个结点的指针 char thread_name[10]; //线程名 int start_address; //驻留区起始地址 int size; //驻留区大小 }THREAD_RESIDENCE_MEMORY; FREEAREA init_free_area_table[5]={ {NULL,10,10}, {NULL,40,30}, {NULL,80,5}, {NULL,145,15}, {NULL,180,20} }; //测试数据:初始空闲区表 REQUIRE_MEMORY init_thread_require_memory_table[3]={ {NULL,"thread_1",20,4}, {NULL,"thread_2",10,5}, {NULL,"thread_3",5,6} }; //测试数据:初始内存申请表 THREAD_RESIDENCE_MEMORY init_thread_residence_memory_table[5]={ {NULL,"a",0,10}, {NULL,"b",20,20}, {NULL,"c",70,10}, {NULL,"d",85,60}, {NULL,"e",160,20} };//测试数据:初始线程驻留区表 FREEAREA *p_free_area_list=NULL; //空闲区链首 REQUIRE_MEMORY *p_thread_require_memory_queue=NULL; //内存申请队列队首 THREAD_RESIDENCE_MEMORY *p_thread_residence_memory_list=NULL; //线程驻留链首 THREAD_RESIDENCE_MEMORY *tail_thread_residence_memory_list=NULL; //线程驻留区链尾 CRITICAL_SECTION CS_THREAD_MEMORY_LIST; //保护线程驻留区链表的临界区 CRITICAL_SECTION CS_SCREEN; //保护屏幕的临界区 CRITICAL_SECTION CS_FREEAREA_LIST; //保护空闲区链表的临界区 HANDLE h_thread[MAX_THREAD]; //线程句柄数组 void print_space(int num); //输出若干个空格 void display_thread_residence_memory_list(); //显示线程驻留区表 //最佳适应分配算法的函数 void BF_thread(void *data); //线程函数 void BF_delete_freearea_list(); //删除空闲区链表 REQUIRE_MEMORY *BF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num); //初始化内存申请链表 void BF_delete_require_memory_list(); //删除内存申请链表 THREAD_RESIDENCE_MEMORY *BF_initialize_thread_residence_memory_list (THREAD_RESIDENCE_MEMORY *init_table,int num); //初始化线程驻留区链表 void BF_delete_thread_residence_memory_list(); //删除线程驻留区链表 int BF_require_memory(int size); //内存申请函数 void BF_release_memory(int start_address,int size); //内存释放函数 void BF_insert_freearea(FREEAREA *free_node); //空闲区结点插入函数 void BF(); //初始化程序 void BF_initialize_freearea_list(FREEAREA *init_table,int num); //初始化空闲区链表 源程序文件 variable_partition.cpp 的清单 #include "variable_partition.h" void print_space(int num){ //显示若干个空格 int i; for(i=0;i<num;i++){ printf(" "); } } void display_thread_residence_memory_list(){ //显示驻留线程链表 THREAD_RESIDENCE_MEMORY *p; char buffer[20]; p=p_thread_residence_memory_list; printf("|-------------------|--------------------|------------------|\n"); printf("| thread_name | start_address(kB) | size(KB) |\n"); printf("|-------------------|--------------------|------------------|\n"); while(p!=NULL){ printf("| %s",p->thread_name); print_space(18-strlen(p->thread_name)); printf("| %d",p->start_address); itoa( p->start_address, buffer, 10 ); print_space(19-strlen(buffer)); printf("| %d",p->size); itoa(p->size, buffer, 10 ); print_space(17-strlen(buffer)); printf("|\n"); p=p->next; }; printf("|-------------------|--------------------|------------------|\n\n"); } //最佳适应分配法:删除空闲区链表 void BF_delete_freearea_list(){ FREEAREA *temp; temp=p_free_area_list; while(temp!=NULL){ temp=p_free_area_list->next; free(p_free_area_list); p_free_area_list=temp; } p_free_area_list=NULL; } //最佳适应分配法:初始化内存申请链表 REQUIRE_MEMORY *BF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num){ REQUIRE_MEMORY *temp; REQUIRE_MEMORY *head=NULL; REQUIRE_MEMORY *tail=NULL; int i; for(i=0;i<num;i++){ temp=(REQUIRE_MEMORY *)malloc(sizeof(REQUIRE_MEMORY)); strcpy(temp->thread_name,init_table[i].thread_name); temp->size=init_table[i].size; temp->duration=init_table[i].duration; temp->next=NULL; if(head==NULL) head=tail=temp; else{ tail->next=temp; tail=tail->next; } }; return head; } //最佳适应分配法:删除内存申请链表 void BF_delete_require_memory_list(){ REQUIRE_MEMORY *temp; temp=p_thread_require_memory_queue; while(temp!=NULL){ temp=p_thread_require_memory_queue->next; free(p_thread_require_memory_queue); p_thread_require_memory_queue=temp; } p_thread_require_memory_queue=NULL; } //最佳适应分配法:初始化线程驻留区链表 THREAD_RESIDENCE_MEMORY *BF_initialize_thread_residence_memory_list(THREAD_RESIDENCE_MEMORY *init_table,int num){ THREAD_RESIDENCE_MEMORY *temp; THREAD_RESIDENCE_MEMORY *head=NULL; THREAD_RESIDENCE_MEMORY *tail=NULL; int i; for(i=0;i<num;i++){ temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY)); strcpy(temp->thread_name,init_table[i].thread_name); temp->start_address=init_table[i].start_address; temp->size=init_table[i].size; temp->next=NULL; if(head==NULL) head=tail=temp; else{ tail->next=temp; tail=tail->next; } }; tail_thread_residence_memory_list=tail; return head; } //最佳适应分配法:删除线程驻留区链表 void BF_delete_thread_residence_memory_list(){ THREAD_RESIDENCE_MEMORY *temp=p_thread_residence_memory_list; temp=p_thread_residence_memory_list; while(temp!=NULL){ temp=p_thread_residence_memory_list->next; free(p_thread_residence_memory_list); p_thread_residence_memory_list=temp; } p_thread_residence_memory_list=NULL; } //最佳适应分配算法的线程:申请内存,驻留一段时间,释放内存 void BF_thread(void *data){ int start_address=-1; THREAD_RESIDENCE_MEMORY *temp; EnterCriticalSection(&CS_SCREEN); printf("create thread:%s\n",((REQUIRE_MEMORY *)(data))->thread_name); LeaveCriticalSection(&CS_SCREEN); //申请内存 while(1){ start_address=BF_require_memory(((REQUIRE_MEMORY *)(data))->size); if(start_address>=0) break; else Sleep(1000); } temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY)); strcpy(temp->thread_name,((REQUIRE_MEMORY *)(data))->thread_name); temp->start_address=start_address; temp->size=((REQUIRE_MEMORY *)(data))->size; temp->next=NULL; EnterCriticalSection(&CS_THREAD_MEMORY_LIST); //加入线程内存驻留区链表 tail_thread_residence_memory_list->next=temp; tail_thread_residence_memory_list=tail_thread_residence_memory_list->next; LeaveCriticalSection(&CS_THREAD_MEMORY_LIST); //显示线程内存驻留区链表 EnterCriticalSection(&CS_SCREEN); printf("after %s %s\n",((REQUIRE_MEMORY *)(data))->thread_name,"get memory:"); display_thread_residence_memory_list(); LeaveCriticalSection(&CS_SCREEN); Sleep(((REQUIRE_MEMORY *)(data))->duration); //释放内存 BF_release_memory(start_address,((REQUIRE_MEMORY *)(data))->size); } //最佳适应分配算法的内存申请函数 int BF_require_memory(int size){ //请读者自己实现这段代码 } //最佳适应分配算法的内存释放函数 void BF_release_memory(int start_address,int size){ //请读者自己实现这段代码 } //最佳分配算法的空闲区结点插入函数 void BF_insert_freearea(FREEAREA *free_node){ FREEAREA *p; FREEAREA *p_next; if(p_free_area_list==NULL) p_free_area_list=free_node; else{ p_next=p=p_free_area_list; while(p_next!=NULL&&p_next->size<free_node->size){ p=p_next; p_next=p_next->next; } if(p_next==NULL) //应插入到尾部 p->next=free_node; else if(p==p_next){ //应插入到头部 free_node->next=p; p_free_area_list=free_node; } else{ //应插入到p与p_next之间 free_node->next=p_next; p->next=free_node; } } } //最佳适应分配法:初始化空闲区链表 void BF_initialize_freearea_list(FREEAREA *init_table,int num){ FREEAREA *temp; int i; for(i=0;i<num;i++){ temp=(FREEAREA *)malloc(sizeof(FREEAREA)); temp->start_address=init_table[i].start_address; temp->size=init_table[i].size; temp->next=NULL; BF_insert_freearea(temp); } } //最佳分配算法的初始化程序 void BF( ) { int i=0; REQUIRE_MEMORY *p; HANDLE h_thread[MAX_THREAD]; InitializeCriticalSection(&CS_THREAD_MEMORY_LIST); InitializeCriticalSection(&CS_FREEAREA_LIST); InitializeCriticalSection(&CS_SCREEN); printf("最佳适应分配算法\n"); BF_initialize_freearea_list(init_free_area_table,5); p_thread_require_memory_queue=BF_initialize_require_memory_list(init_thread_require_memory_table,3); p_thread_residence_memory_list=BF_initialize_thread_residence_memory_list(init_thread_residence_memory_table,5); p=p_thread_require_memory_queue; while(p!=NULL){ h_thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(BF_thread),p,0,NULL); i++; p=p->next; }; //等待所有线程结束 WaitForMultipleObjects(MAX_THREAD,h_thread,TRUE,-1); //显示驻留线程链表 EnterCriticalSection(&CS_SCREEN); printf("after all threads have finished:\n"); display_thread_residence_memory_list(); LeaveCriticalSection(&CS_SCREEN); //删除各种链表 BF_delete_freearea_list(); BF_delete_require_memory_list(); BF_delete_thread_residence_memory_list(); getch(); printf("\n"); } void main( ){ BF( ); }根据上面的要求和部分代码,补充上面代码实现动态异长分区内存分配与去配算法的设计-最佳适应算法
05-28
bool HierSgmCudaImpl::Init(const ste_opt1_t& option) { const int width = option.width; const int height = option.height; const int min_disp = option.min_disp; const int max_disp = option.max_disp; const int num_layers = option.num_layers; if (width == 0 || height == 0) { return false; } is_print_timing_ = false; Release(); width_ = width; height_ = height; //ÿһ������ݷ��䡢�������㡢ƥ�����ʼ�� num_layers_ = std::max(1, num_layers); vision_stereo_ = new StereoCuda * [num_layers_](); layer_bytes_left_ = new unsigned char* [num_layers_](); layer_bytes_right_ = new unsigned char* [num_layers_](); layer_initial_disps_ = new short* [num_layers_](); layer_disps_left_ = new float* [num_layers_](); layer_disps_right_ = new float* [num_layers_](); layer_width_ = new int[num_layers_](); layer_height_ = new int[num_layers_](); for (int i = 0; i < num_layers_; i++) { vision_stereo_[i] = new StereoCuda; const int scale = static_cast<int>(pow(2.0, static_cast<double>(i))); const auto w = layer_width_[i] = width_ / scale; const auto h = layer_height_[i] = height_ / scale; #ifdef USING_PAGE_LOCKED_MEMORY StereoCuda::MallocPageLockedPtr(reinterpret_cast<void**>(&layer_bytes_left_[i]), w * h * sizeof(unsigned char)); StereoCuda::MallocPageLockedPtr(reinterpret_cast<void**>(&layer_bytes_right_[i]), w * h * sizeof(unsigned char)); if (i > 0) { StereoCuda::MallocPageLockedPtr(reinterpret_cast<void**>(&layer_disps_left_[i]), w * h * sizeof(float)); StereoCuda::MallocPageLockedPtr(reinterpret_cast<void**>(&layer_disps_right_[i]), w * h * sizeof(float)); } if (i < num_layers_ - 1) { StereoCuda::MallocPageLockedPtr(reinterpret_cast<void**>(&layer_initial_disps_[i]), w * h * sizeof(short)); } #else layer_bytes_left_[i] = new unsigned char[w * h](); layer_bytes_right_[i] = new unsigned char[w * h](); if (i > 0) { layer_disps_left_[i] = new float[w * h](); layer_disps_right_[i] = new float[w * h](); } if (i < num_layers_ - 1) { layer_initial_disps_[i] = new short[w * h](); } #endif CuSGMOption sgm_param; SetSgmParameters(option.do_lr_check,option.do_rm_peaks,option.do_smooth, sgm_param, i, num_layers_); if (!sgm_param.using_constant_p2) { sgm_param.p1 = 10; sgm_param.p2_init = 150; } //�����ӲΧ int disparity_min = min_disp / scale, disparity_max = max_disp / scale; int disparity_range = 32; if (i == num_layers_ - 1) { disparity_range = disparity_max - disparity_min; int k = 6; while (pow(2, k) < disparity_range) { k++; } disparity_range = pow(2, k); if (disparity_range > 2 * width) { disparity_range /= 2; } if (disparity_min >= width) { disparity_min = width - disparity_range; if (disparity_min < -width) { disparity_min = -width; } } } else { disparity_min = 0.0; disparity_max = StereoCuda::get_level_range(); disparity_range = StereoCuda::get_level_range(); } if (!vision_stereo_[i]->Init(layer_width_[i], layer_height_[i], disparity_min, disparity_range, sgm_param, is_print_timing_)) { return false; } } return true; } 注释上述代码
09-25
补充上个问题的信息:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <libubox/md5.h> #include "common.h" #include "ubus.h" #include "worker.h" #include "relay.h" #include "minor_stream.h" #include "double_talk.h" #include "chime_ctrl.h" #include "alarm.h" #include "preview.h" #include "cookie.h" #include "device.h" #include "iot_info.h" #include "snapshot.h" #include "tapocare.h" #include "ring.h" #include "storage.h" #ifdef HARDDISK_STORAGE #include "face_control.h" #endif #ifdef HUB_WEBRTC #include "webrtc.h" #endif #ifdef AI_ENHANCE #include "image_transmit.h" #endif #ifdef SDCARD_VIDEO_DOWNLOAD_SUPPORT #include "storage_local_download.h" #endif #ifdef PROTOCOL_SECURE #define HTTP_DIGEST_PWD_MD5 "1" #define HTTP_DIGEST_PWD_RSA "2" #define HTTP_DIGEST_PWD_SHA "3" #endif char tapo_user[128] = {0}; char tapo_passwd[128] = {0}; char tapo_nonce[128] = {0}; const int RELAY_CONSUMER_MAX_NUM[] = {0, 34, 26, 18, 20}; int relay_consumer_cur_max_num = 0; int relay_consumer_cur_left_num = 0; static unsigned char tapo_key[16] = {0}; static unsigned char tapo_iv[16] = {0}; static struct tpsocket_aes_key tapo_aes_key = {{0}}; static struct tpsocket_aes_key tapo_aes_dec_key = {{0}}; #ifdef HTTP_HMAC_HKDF_SUPPORT unsigned char tapo_key_hkdf[16] = {0}; unsigned char tapo_key_hkdf_hmac[16] = {0}; char tapo_salt[32 + 1] = {0}; struct tpsocket_aes_key tapo_aes_key_hkdf = {{0}}; struct tpsocket_aes_key tapo_aes_dec_key_hkdf = {{0}}; char *tapo_vod_get_salt() { return tapo_salt; } void generate_iv_nonce(unsigned char *nonce, int len) { int i = 0; for (i = 0; i < len; ++i) { nonce[i] = (unsigned char)(rand() % 256); } } int tapo_vod_hkdf_hamc_verify_decrypt(unsigned char *in, int inputlen, unsigned char *out, int *outputlen, unsigned char *iv_nonce, char *XHmac) { unsigned char hmac[32] = {0}; char base64_hmac[32*2] = {0}; int ret = 0; tpsocket_sha256_hmac(tapo_key_hkdf_hmac, 16, in, inputlen, hmac); tpsocket_base64_encode(hmac, sizeof(hmac), (unsigned char *)base64_hmac); if (!strncmp(base64_hmac, XHmac, strlen(base64_hmac))) { ret = tpsocket_aes_cbc_encrypt(in, out, inputlen, &tapo_aes_dec_key_hkdf, iv_nonce, 0); if (ret != 0) { DBG_ERR("tpsocket_aes_cbc_encrypt failed\n"); *outputlen = 0; goto exit; } *outputlen = inputlen; } else { DBG_ERR("Hmac verification failed\n"); *outputlen = 0; goto exit; } exit: return ret; } int tapo_vod_hkdf_hamc_encrypt(unsigned char *in, unsigned char *out, unsigned int len, unsigned char *iv_str, unsigned char *base64_hmac) { unsigned char iv_nonce[16] = {0}; unsigned char hmac[32] = {0}; int ret = 0; generate_iv_nonce(iv_nonce, 16); tpsocket_hex_encode(iv_nonce, 16, iv_str, 0); ret = tpsocket_aes_cbc_encrypt(in, out, len, &tapo_aes_key_hkdf, iv_nonce, 1); if (ret != 0) { DBG_ERR("Error happens on encrypting.\n"); ret = 0 ; goto exit; } tpsocket_sha256_hmac(tapo_key_hkdf_hmac, 16, out, len, hmac); tpsocket_base64_encode(hmac, sizeof(hmac), base64_hmac); exit: return len; } bool tapo_vod_get_hkdf_hamc(struct list_head *buf, char *XHmac, unsigned char *iv_nonce) { char *XHmac_tmp = NULL; char *XNonce = NULL; if ((XHmac_tmp = common_find_key_from_buf(buf, "X-Data-Hmac")) != NULL) { memset(XHmac, 0, HKDF_HMAC_LEN); memcpy(XHmac, XHmac_tmp, HKDF_HMAC_LEN); //DBG_ERR("X-Data-Hmac:%s\n", XHmac); free(XHmac_tmp); if ((XNonce = common_find_key_from_buf(buf, "X-Nonce")) != NULL) { tpsocket_hex_decode((const unsigned char *)XNonce, HKDF_IV_LEN * 2, iv_nonce); //DBG_ERR("X-Nonce:%s\n", XNonce); free(XNonce); return true; } } return false; } #endif static void _ubus_get_result( struct ubus_app *app, struct blob_attr *msg, int ret, void *priv) { if (msg && priv) { struct blob_buf *bBuf = (struct blob_buf *)priv; struct blob_attr *cur = NULL; int rem; blob_for_each_attr(cur, msg, rem) { blobmsg_add_blob(bBuf, cur); } } } #ifdef TAPO_CAMERA static MEDIA_ENCRYPT_STATUS gEncryptStatus = MEDIA_ENCRYPT_INVALID; //Note: indicate validation of encrypt key void set_media_encrypt_status(MEDIA_ENCRYPT_STATUS ENCRYPT_STATUS) { if (gEncryptStatus != ENCRYPT_STATUS) { gEncryptStatus = ENCRYPT_STATUS; } } MEDIA_ENCRYPT_STATUS get_media_encrypt_status() { return gEncryptStatus; } int get_media_encrypt_key(char *aes_key, char *aes_iv, int size) { if (!aes_key || !aes_iv || size < (2*MD5_HEX_LEN+1)) { return -1; } if (get_media_encrypt_status() != MEDIA_ENCRYPT_VALID) { return -1; } tpsocket_hex_encode(tapo_key, MD5_HEX_LEN, (unsigned char *)aes_key, 0); tpsocket_hex_encode(tapo_iv, MD5_HEX_LEN, (unsigned char *)aes_iv, 0); return 0; } #endif static void send_clip_start_event(ALARM_PRODUCER *producer) { struct blob_buf b = {0}; blobmsg_buf_init(&b); if (producer) { DEV_INFO *dev_info = get_dev_info((MEDIACENTER_CTX *)get_top_ctx(), producer->dev_id, producer->dev_ip); if (dev_info) { blobmsg_add_string(&b, "deviceId", dev_info->dev_id); ubus_app_event((struct ubus_app *)ubus_get_ubus_app(), "clip_start_timing", b.head); } } blob_buf_free(&b); } static inline void work_tapo_refresh_encrypt_key(void) { md5_ctx_t md5_ctx; char tmp[64] = {0}; //DBG_DBG("tapo_nonce: %s\n", tapo_nonce); //DBG_DBG("tapo_passwd: %s\n", tapo_passwd); md5_begin(&md5_ctx); md5_hash(tapo_nonce, strlen(tapo_nonce), &md5_ctx); md5_hash(":", strlen(":"), &md5_ctx); md5_hash(tapo_passwd, strlen(tapo_passwd), &md5_ctx); md5_end(tapo_key, &md5_ctx); md5_begin(&md5_ctx); md5_hash(tapo_user, strlen(tapo_user), &md5_ctx); md5_hash(":", strlen(":"), &md5_ctx); md5_hash(tapo_nonce, strlen(tapo_nonce), &md5_ctx); md5_end(tapo_iv, &md5_ctx); tpsocket_hex_encode(tapo_key, sizeof(tapo_key), (unsigned char *)tmp, 0); //DBG_DBG("tapo_key: %s\n", tmp); tpsocket_hex_encode(tapo_iv, sizeof(tapo_iv), (unsigned char *)tmp, 0); //DBG_DBG("tapo_iv: %s\n", tmp); tpsocket_aes_set_encrypt_key((unsigned char *)tapo_key, 128, &tapo_aes_key); tpsocket_aes_set_decrypt_key((unsigned char *)tapo_key, 128, &tapo_aes_dec_key); } void work_tapo_aec_encrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { unsigned char tmpiv[16]; memcpy(tmpiv, tapo_iv, sizeof(tapo_iv)); if (tpsocket_aes_cbc_encrypt(inputbuf, outbuf, inputlen, &tapo_aes_key, tmpiv, 1) == 0) *outputlen = inputlen; else *outputlen = 0; } static inline void work_tapo_aec_decrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { unsigned char tmpiv[16]; memcpy(tmpiv, tapo_iv, sizeof(tapo_iv)); if (tpsocket_aes_cbc_encrypt(inputbuf, outbuf, inputlen, &tapo_aes_dec_key, tmpiv, 0) == 0) *outputlen = inputlen; else *outputlen = 0; } #ifdef TAPO_CAMERA void work_tapo_refresh_nonce() { tpsocket_hex_random((unsigned char *)tapo_nonce, 32, 0); work_tapo_refresh_encrypt_key(); set_media_encrypt_status(MEDIA_ENCRYPT_VALID); } #endif char *tapo_vod_get_user() { return tapo_user; } char *tapo_vod_get_nonce() { return tapo_nonce; } void tapo_vod_aec_encrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_vod_aec_encrypt param error\n"); return; } return work_tapo_aec_encrypt(inputbuf, inputlen, outbuf, outputlen); } void tapo_vod_aec_decrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_vod_aec_decrypt param error\n"); return; } return work_tapo_aec_decrypt(inputbuf, inputlen, outbuf, outputlen); } void tapo_talk_aec_decrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_talk_aec_decrypt param error\n"); return; } return work_tapo_aec_decrypt(inputbuf, inputlen, outbuf, outputlen); } void tapo_img_trans_aec_encrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_img_trans_aec_encrypt param error, inputlen: %d, inbuf: %p, outbuf: %p, outlen: %p\n", inputlen, inputbuf, outbuf, outputlen); return; } return work_tapo_aec_encrypt(inputbuf, inputlen, outbuf, outputlen); } void tapo_img_trans_aec_decrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_img_trans_aec_decrypt param error\n"); return; } return work_tapo_aec_decrypt(inputbuf, inputlen, outbuf, outputlen); } void tapo_log_aec_decrypt(unsigned char *inputbuf, int inputlen, unsigned char *outbuf, int *outputlen) { if(!inputbuf || inputlen <= 0 || !outbuf || !outputlen) { DBG_ERR("tapo_log_aec_decrypt param error\n"); return; } return work_tapo_aec_decrypt(inputbuf, inputlen, outbuf, outputlen); }
最新发布
10-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值