홍 몽 경 커 널 정적 메모리 사용 분석

12534 단어 큰 은혜핵심
머리말
메모리 관리 모듈 관리 시스템 의 메모리 자원 은 운영 체제 의 핵심 모듈 중 하나 로 메모리 의 초기 화,분배 와 방출 을 포함한다.
시스템 이 실행 되 는 과정 에서 메모리 관리 모듈 은 메모리 에 대한 신청/방출 을 통 해 사용자 와 OS 가 메모리 에 대한 사용 을 관리 하고 메모리 의 이 용 률 과 사용 효율 을 최 우선 으로 하 는 동시에 시스템 의 메모리 파편 문 제 를 최대한 해결한다.
홍 몽 경 커 널 의 메모리 관 리 는 정적 메모리 관리 와 동적 메모리 관리 로 나 뉘 어 메모리 초기 화,분배,방출 등 기능 을 제공 합 니 다.
동적 메모리:동적 메모리 탱크 에 사용자 가 지정 한 크기 의 메모리 블록 을 분배 합 니 다.
장점:수요 에 따라 분배 한다단점:메모리 탱크 에 파편 이 생 길 수 있 습 니 다정적 메모리:정적 메모리 탱크 에서 사용자 초기 화 를 할당 할 때 미리 설정(고정)크기 의 메모리 블록 입 니 다.
4.567917.장점:분배 와 방출 효율 이 높 고 정적 메모리 탱크 에 조각 이 없다단점:미리 설 정 된 크기 의 메모리 블록 을 초기 화 할 때 까지 만 신청 할 수 있 고 필요 에 따라 신청 할 수 없습니다본 고 는 주로 홍 몽 경 커 널 정적 메모리(Memory Box)를 분석 하고 후속 시 리 즈 는 동적 메모 리 를 계속 분석 할 것 이다.정적 메모 리 는 실질 적 으로 정적 배열 입 니 다.정적 메모리 풀 안의 블록 크기 는 초기 화 할 때 설정 되 고 초기 화 된 블록 크기 는 변경 할 수 없습니다.정적 메모리 풀 은 제어 블록 과 같은 크기 의 메모리 블록 으로 구성 되 어 있다.제어 블록 은 메모리 탱크 의 머리 부분 에 위치 하여 메모리 블록 관리 에 사 용 됩 니 다.메모리 블록의 신청 과 방출 은 블록의 크기 를 입도 로 한다.
본 고 는 정적 메모리 모듈 의 소스 코드 를 분석 함으로써 독자 가 정적 메모리 의 사용 을 파악 하도록 도와 준다.본 논문 에서 언급 한 소스 코드 는 OpenHarmony LiteOS-M 커 널 을 예 로 들 면 모두 오픈 소스 사이트 에서 얻 을 수 있 습 니 다https://gitee.com/openharmony/kernel_liteos_m
다음은 정적 메모리 의 구조 체,정적 메모리 초기 화,정적 메모리 에서 자주 사용 되 는 소스 코드 를 살 펴 보 겠 습 니 다.
2.정적 메모리 구조 체 정의 와 자주 사용 되 는 매크로 정의
2.1 정적 메모리 구조 체 정의
정적 메모리 구조 체 는 파일 kernel\include\losmembox.h 에서 정의 합 니 다.소스 코드 는 다음 과 같다.(1)정적 메모리 노드 LOS 를 정의 한다.MEMBOX_NODE 구조 체,(2)에서 정 의 된 정적 메모리 의 구조 체 풀 정보 구조 체 는 LOS 이다.MEMBOX_INFO,구조 체 구성원 의 해석 은 주석 부분 을 참조한다.

⑴  typedef struct tagMEMBOX_NODE {
        struct tagMEMBOX_NODE *pstNext; /**<             ,          */
    } LOS_MEMBOX_NODE;

⑵  typedef struct LOS_MEMBOX_INFO {
        UINT32 uwBlkSize;               /**<             ,          */
        UINT32 uwBlkNum;                /**<              */
        UINT32 uwBlkCnt;                /**<                  */
    #if (LOSCFG_PLATFORM_EXC == 1)
        struct LOS_MEMBOX_INFO *nextMemBox; /**<            */
    #endif
        LOS_MEMBOX_NODE stFreeList;     /**<                 */
    } LOS_MEMBOX_INFO;
정적 메모리 에 대해 다음 과 같은 설명도 로 설명 하고 정적 메모리 영역 에 대해 머리 는 LOS 입 니 다.MEMBOX_INFO 정보,그 다음 에 각 메모리 블록,각 메모리 블록 크기 는 uwBlkSize 이 고 메모리 블록 노드 LOS 를 포함 합 니 다.MEMBOX_NODE 와 메모리 블록 데이터 영역.남 은 메모리 블록 노드 는 다음 남 은 메모리 블록 노드 를 가리킨다.

2.2 정적 메모리 상용 매크로 정의
정적 메모리 헤더 파일 에 중요 한 매크로 정의 도 제공 합 니 다.(1 곳 의 LOSMEMBOX_ALIGNED(memAddr)는 메모리 주 소 를 맞 추 는 데 사 용 됩 니 다.(2 곳 OSMEMBOX_NEXT(addr,blkSize)는 현재 노드 메모리 주소 addr 와 메모리 블록 크기 blkSize 에 따라 다음 메모리 블록의 메모리 주 소 를 가 져 옵 니 다.⑶ 곳 OSMEMBOX_NODE_HEAD_SIZE 는 메모리 블록 에 있 는 노드 의 고 개 를 끄 덕 이 는 크기 를 표시 합 니 다.메모리 블록 마다 메모리 노드 LOS 가 포함 되 어 있 습 니 다.MEMBOX_NODE 와 업무 의 데이터 영역 을 저장 합 니 다.(4)정적 메모리 의 총 크기 를 나타 내 고 메모리 풀 정보 구조 체 가 차지 하 는 크기 와 각 메모리 블록 이 차지 하 는 크기 를 포함한다.

⑴  #define LOS_MEMBOX_ALIGNED(memAddr) (((UINTPTR)(memAddr) + sizeof(UINTPTR) - 1) & (~(sizeof(UINTPTR) - 1)))

⑵  #define OS_MEMBOX_NEXT(addr, blkSize) (LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) + (blkSize))

⑶  #define OS_MEMBOX_NODE_HEAD_SIZE sizeof(LOS_MEMBOX_NODE)

⑷  #define LOS_MEMBOX_SIZE(blkSize, blkNum) \
    (sizeof(LOS_MEMBOX_INFO) + (LOS_MEMBOX_ALIGNED((blkSize) + OS_MEMBOX_NODE_HEAD_SIZE) * (blkNum)))
파일 kernel\src\mm\losmembox.c 에서 도 매크로 와 내 연 함 수 를 정의 했다.(1 곳 정의 OSMEMBOX_MAGIC 마술 글자,이 32 비트 마술 글자 의 뒷 8 비트 유지 보수 퀘 스 트 번호 정보,퀘 스 트 번호 위 치 는(2)의 매크로 로 정의 합 니 다.⑶ 처 홍 은 임무 번호 의 최대 치 를 정의 하고(4)처 의 홍 은 마술 글자 에서 임무 번호 정 보 를 추출 한다.
Br.내부 연결 함수 에 마술 글 자 를 설정 하고 메모리 블록 노드 가 정적 메모리 탱크 에서 분 배 된 후에 노드 포인터.pstNext 는 다음 남 은 메모리 블록 노드 를 가리 키 지 않 고 마술 문자 로 설정 합 니 다.직경 9337 의 내 연 함 수 는 마술 자 를 검사 하 는 데 쓰 인 다.93.38 곳 의 매크로 는 메모리 블록 의 노드 주소 에 따라 메모리 블록 의 데이터 구역 주 소 를 가 져 옵 니 다.9339 곳 의 매크로 는 메모리 블록 의 데이터 구역 주소 에 따라 메모리 블록 의 노드 주 소 를 가 져 옵 니 다.

⑴  #define OS_MEMBOX_MAGIC         0xa55a5a00

⑵  #define OS_MEMBOX_TASKID_BITS   8

⑶  #define OS_MEMBOX_MAX_TASKID    ((1 << OS_MEMBOX_TASKID_BITS) - 1)

⑷  #define OS_MEMBOX_TASKID_GET(addr) (((UINTPTR)(addr)) & OS_MEMBOX_MAX_TASKID)

⑸  STATIC INLINE VOID OsMemBoxSetMagic(LOS_MEMBOX_NODE *node)
    {
        UINT8 taskID = (UINT8)LOS_CurTaskIDGet();
        node->pstNext = (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID);
    }

⑹  STATIC INLINE UINT32 OsMemBoxCheckMagic(LOS_MEMBOX_NODE *node)
    {
        UINT32 taskID = OS_MEMBOX_TASKID_GET(node->pstNext);
        if (taskID > (LOSCFG_BASE_CORE_TSK_LIMIT + 1)) {
            return LOS_NOK;
        } else {
            return (node->pstNext == (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID)) ? LOS_OK : LOS_NOK;
        }
    }

⑺  #define OS_MEMBOX_USER_ADDR(addr) \
        ((VOID *)((UINT8 *)(addr) + OS_MEMBOX_NODE_HEAD_SIZE))

⑻  #define OS_MEMBOX_NODE_ADDR(addr) \
        ((LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) - OS_MEMBOX_NODE_HEAD_SIZE))
3.정적 메모리 상용 작업
사용자 가 고정 길이 의 메모 리 를 사용 해 야 할 때 정적 메모리 할당 방식 으로 메모 리 를 가 져 올 수 있 습 니 다.사용 이 완료 되면 정적 메모리 방출 함 수 를 통 해 사용 하 는 메모 리 를 반환 하여 중복 사용 할 수 있 습 니 다.
3.1 정적 메모리 풀 초기 화
정적 메모리 풀 함수 UINT 32 LOS 초기 화 분석MemboxInit(VOID*pool,UINT 32 poolSize,UINT 32 blkSize)의 코드 입 니 다.함수 인 자 를 살 펴 보 겠 습 니 다.VOID*pool 은 정적 메모리 풀 의 시작 주소 입 니 다.UINT 32 poolSize 는 초기 화 된 정적 메모리 풀 의 전체 크기 입 니 다.poolSize 는*pool 이 시작 하 는 메모리 구역 의 크기 보다 작 아야 합 니 다.그렇지 않 으 면 뒤의 메모리 영역 에 영향 을 줄 수 있 습 니 다.정적 메모리 보다 큰 머리 크기 sizeof(LOSMEMBOX_INFO)。길이 UINT 32 blk Size 는 정적 메모리 탱크 의 모든 메모리 블록 크기 입 니 다.
우 리 는 코드 를 보고(1)들 어 오 는 매개 변 수 를 검사 합 니 다.(2)정적 메모리 탱크 에 있 는 모든 메모리 블록 의 실제 크기 를 설정 하고 메모리 가 정렬 되 었 으 며 메모리 블록 에 있 는 노드 정보 도 포함한다.⑶ 메모리 풀 에 있 는 메모리 블록 의 총 수량 을 계산 한 다음 에 사용 한 메모리 블록 의 수량 을 설정 합 니 다.uwBlkCnt 는 0 입 니 다.
(4)사용 가능 한 메모리 블록 이 0 이면 초기 화 에 실 패 했 습 니 다.Br.메모리 풀 의 첫 번 째 남 은 메모리 블록 노드 를 가 져 옵 니 다.『9337』에서 남 은 메모리 블록 을 정적 메모리 풀 정보 구조 체 남 은 메모리 블록 링크 stFreeList.pstNext 에 마 운 트 한 다음 에 실행 합 니 다.

UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize)
{
    LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
    LOS_MEMBOX_NODE *node = NULL;
    UINT32 index;
    UINT32 intSave;

⑴  if (pool == NULL) {
        return LOS_NOK;
    }

    if (blkSize == 0) {
        return LOS_NOK;
    }

    if (poolSize < sizeof(LOS_MEMBOX_INFO)) {
        return LOS_NOK;
    }

    MEMBOX_LOCK(intSave);
⑵  boxInfo->uwBlkSize = LOS_MEMBOX_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE);
    if (boxInfo->uwBlkSize == 0) {
        MEMBOX_UNLOCK(intSave);
        return LOS_NOK;
    }
⑶  boxInfo->uwBlkNum = (poolSize - sizeof(LOS_MEMBOX_INFO)) / boxInfo->uwBlkSize;
    boxInfo->uwBlkCnt = 0;
⑷  if (boxInfo->uwBlkNum == 0) {
        MEMBOX_UNLOCK(intSave);
        return LOS_NOK;
    }

⑸  node = (LOS_MEMBOX_NODE *)(boxInfo + 1);

⑹  boxInfo->stFreeList.pstNext = node;

⑺  for (index = 0; index < boxInfo->uwBlkNum - 1; ++index) {
        node->pstNext = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize);
        node = node->pstNext;
    }

    node->pstNext = NULL;

#if (LOSCFG_PLATFORM_EXC == 1)
    OsMemBoxAdd(pool);
#endif

    MEMBOX_UNLOCK(intSave);

    return LOS_OK;
}
3.2 정적 메모리 블록 내용 삭제
우 리 는 함수 VOID LOS 를 사용 할 수 있다.Membox Clr(VOID*pool,VOID*box)는 정적 메모리 블록 에 있 는 데이터 영역 내용 을 지 우려 면 2 개의 인자 가 필요 합 니 다.VOID*pool 은 초기 화 된 정적 메모리 풀 주소 입 니 다.VOID*box 는 내용 을 지 워 야 하 는 정적 메모리 블록의 데이터 영역의 시작 주소 입 니 다.이것 은 메모리 블록의 노드 주소 가 아니 므 로 모든 메모리 블록의 노드 구역 은 지 울 수 없습니다.다음은 소스 코드 를 분석 하 겠 습 니 다.
(1)에서 매개 변 수 를 검사 하고(2)에서 memset 를 호출 한다.s()함수 가 메모리 블록의 데이터 영역 을 0 에 기록 합 니 다.쓰기 시작 주 소 는 메모리 블록 의 데이터 영역 시작 주소 VOID*box 이 며,쓰기 길 이 는 데이터 영역 길이 boxInfo->uwBlkSize-OS 입 니 다.MEMBOX_NODE_HEAD_SIZE。

VOID LOS_MemboxClr(VOID *pool, VOID *box)
{
    LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;

⑴  if ((pool == NULL) || (box == NULL)) {
        return;
    }

⑵  (VOID)memset_s(box, (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE), 0,
                   (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE));
}
3.3 정적 메모 리 를 신청,방출
정적 메모리 풀 을 초기 화하 면 함수 VOID*LOS 를 사용 할 수 있 습 니 다.Membox Alloc(VOID*pool)는 정적 메모 리 를 신청 합 니 다.다음은 소스 코드 를 분석 하 겠 습 니 다.
(1)정적 메모리 탱크 의 남 은 메모리 블록 체인 헤더 노드 를 가 져 옵 니 다.만약 에 링크 가 비어 있 지 않 으 면(2)를 실행 하고 다음 노드 를 nodeTmp 에 할당 합 니 다.⑶ 에서 체인 표 의 끝 점 을 다음 링크 노드 를 실행 한 다음 에(4)분 배 된 메모리 블록 을 마술 자 를 설정 한 다음 에 메모리 탱크 가 메모리 블록 수량 으로 1 을 추가 했다.Br.돌아 갈 때 매크로 OS 호출MEMBOX_USER_ADDR()은 메모리 블록의 데이터 영역 지질 을 계산한다.

VOID *LOS_MemboxAlloc(VOID *pool)
{
    LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
    LOS_MEMBOX_NODE *node = NULL;
    LOS_MEMBOX_NODE *nodeTmp = NULL;
    UINT32 intSave;

    if (pool == NULL) {
        return NULL;
    }

    MEMBOX_LOCK(intSave);
⑴  node = &(boxInfo->stFreeList);
    if (node->pstNext != NULL) {
⑵      nodeTmp = node->pstNext;
⑶      node->pstNext = nodeTmp->pstNext;
⑷      OsMemBoxSetMagic(nodeTmp);
        boxInfo->uwBlkCnt++;
    }
    MEMBOX_UNLOCK(intSave);

⑸  return (nodeTmp == NULL) ? NULL : OS_MEMBOX_USER_ADDR(nodeTmp);
}
신청 한 메모리 블록 을 사용 하면 함수 UINT 32 LOS 를 사용 할 수 있 습 니 다.Membox Free(VOID*pool,VOID*box)에서 정적 메모 리 를 방출 하려 면 2 개의 인자 가 필요 합 니 다.VOID*pool 은 초기 화 된 정적 메모리 풀 주소 입 니 다.VOID*box 는 풀 어야 할 정적 메모리 블록의 데이터 영역의 시작 주소 입 니 다.이것 은 메모리 블록의 노드 주소 가 아 닙 니 다.다음은 소스 코드 를 분석 하 겠 습 니 다.
(1)방출 할 메모리 블록 의 데이터 구역 주소 에 따라 노드 주소 node 를 가 져 오고(2)방출 할 메모리 블록 을 먼저 검사 합 니 다.⑶ 에서 방출 할 메모리 블록 을 메모리 탱크 의 남 은 메모리 블록 링크 에 걸 고(4)이미 사용 한 수량 을 1 로 줄인다.

LITE_OS_SEC_TEXT UINT32 LOS_MemboxFree(VOID *pool, VOID *box)
{
    LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
    UINT32 ret = LOS_NOK;
    UINT32 intSave;

    if ((pool == NULL) || (box == NULL)) {
        return LOS_NOK;
    }

    MEMBOX_LOCK(intSave);
    do {
⑴      LOS_MEMBOX_NODE *node = OS_MEMBOX_NODE_ADDR(box);
⑵      if (OsCheckBoxMem(boxInfo, node) != LOS_OK) {
            break;
        }

⑶      node->pstNext = boxInfo->stFreeList.pstNext;
        boxInfo->stFreeList.pstNext = node;
⑷      boxInfo->uwBlkCnt--;
        ret = LOS_OK;
    } while (0);
    MEMBOX_UNLOCK(intSave);

    return ret;
}
다음은 검사 함수 인 OsCheckBoxMem()을 다시 봅 시다.(1)메모리 탱크 의 블록 크기 가 0 이면 검사 에 실패 합 니 다.(2)방출 할 메모리 의 빠 른 노드 가 첫 번 째 메모리 블록 노드 의 오프셋 오프셋 오프셋 을 계산한다.⑶ 오프셋 을 제외 한 블록 수량 이 0 이 되 지 않 으 면 검사 에 실패 합 니 다.(4)만약 에 오프셋 을 제외 하고 내부 블록 수량 을 제외 한 업 체 가 메모리 블록 과 같은 수량 보다 많 으 면 검사 에 실패 합 니 다.⑥ 매크로 OsMemBox CheckMagic 을 호출 하여 마술 글 자 를 검사한다.

STATIC INLINE UINT32 OsCheckBoxMem(const LOS_MEMBOX_INFO *boxInfo, const VOID *node)
{
    UINT32 offset;

⑴  if (boxInfo->uwBlkSize == 0) {
        return LOS_NOK;
    }

⑵  offset = (UINT32)((UINTPTR)node - (UINTPTR)(boxInfo + 1));
⑶  if ((offset % boxInfo->uwBlkSize) != 0) {
        return LOS_NOK;
    }

⑷  if ((offset / boxInfo->uwBlkSize) >= boxInfo->uwBlkNum) {
        return LOS_NOK;
    }

⑸   return OsMemBoxCheckMagic((LOS_MEMBOX_NODE *)node);
}
소결
본 고 는 모 두 를 데 리 고 홍 몽 경 커 널 의 정적 메모리 모듈 의 소스 코드 를 분 석 했 는데 정적 메모리 의 구조 체,정적 메모리 풀 초기 화,정적 메모리 신청,방출,제거 내용 등 을 포함한다.홍 몽 경 커 널 코드 창 고 를 쉽게 찾기 위해 서 는 방문 을 권장 합 니 다https://gitee.com/openharmony/kernel_liteos_m
이상 은 홍 몽 경 커 널 정적 메모리 의 사용 에 대한 상세 한 내용 을 분석 하 는 것 입 니 다.홍 몽 경 커 널 정적 메모리 에 관 한 자 료 는 우리 의 다른 관련 글 에 관심 을 가 져 주 십시오!

좋은 웹페이지 즐겨찾기