提交 a7c24a4b 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

开始注解(OOM)内存不足时的处理.

搜索 @note_pic 方便理解画的字符图
搜索 @note_why 尚未看明白的地方,如果您看明白了,请告知完善
搜索 @note_thinking 一点思考和吐槽的地方
搜索 @note_#if0 由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的
搜索 @note_good 给源码点赞
上级 4a5331c7
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_OOM_H
#define _LOS_OOM_H
#include "los_typedef.h"
#define OOM_TASK_PRIORITY 9
#define OOM_TASK_STACK_SIZE 0x1000
#define OOM_CHECK_MIN 10 /* 0.1s */
#define OOM_DEFAULT_CHECK_INTERVAL 100 /* 1s */
#define OOM_CHECK_MAX 1000 /* 10s */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD 0x80000 /* 512KByte */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN 0 /* 0, means always no memory */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX 0x100000 /* 1MByte */
#define OOM_DEFAULT_RECLAIM_MEM_THRESHOLD 0x500000 /* 5MByte */
typedef UINT32 (*OomFn)(UINTPTR param);
typedef struct { //内存溢出控制块(描述符)
UINT32 lowMemThreshold; /* byte */ //最低运行内存
UINT32 reclaimMemThreshold; /* byte */ //回收内存起点
UINT32 checkInterval; /* microsecond */
OomFn processVictimCB; /* process victim process cb function */
OomFn scoreCB; /* out of memory, the process score function */
UINT16 swtmrID;
BOOL enabled; /* oom is enabled or not */
} OomCB;
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomEnable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomDisable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval);
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID);
#endif
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_OOM_H
#define _LOS_OOM_H
#include "los_typedef.h"
#define OOM_TASK_PRIORITY 9
#define OOM_TASK_STACK_SIZE 0x1000
#define OOM_CHECK_MIN 10 /* 0.1s */
#define OOM_DEFAULT_CHECK_INTERVAL 100 /* 1s */
#define OOM_CHECK_MAX 1000 /* 10s */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD 0x80000 /* 512KByte */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN 0 /* 0, means always no memory */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX 0x100000 /* 1MByte */
#define OOM_DEFAULT_RECLAIM_MEM_THRESHOLD 0x500000 /* 5MByte */
typedef UINT32 (*OomFn)(UINTPTR param);//内存溢出的回调函数定义
typedef struct { //内存溢出控制块(描述符)
UINT32 lowMemThreshold; /* byte */ //最低运行内存
UINT32 reclaimMemThreshold; /* byte */ //回收内存起点
UINT32 checkInterval; /* microsecond */
OomFn processVictimCB; /* process victim process cb function */
OomFn scoreCB; /* out of memory, the process score function */ //内存不足时,进程得分函数
UINT16 swtmrID; //定时器ID
BOOL enabled; /* oom is enabled or not *///是否启用了内存溢出监控
} OomCB;
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomEnable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomDisable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval);
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID);
#endif
......@@ -55,7 +55,7 @@ LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#define VM_PAGE_TO_PHYS(page) (page->physAddr)//获取页面物理地址
#define VM_PAGE_TO_PHYS(page) (page->physAddr)//获取物理页框的物理基地址
#define VM_ORDER_TO_PAGES(order) (1 << (order))//伙伴算法由order 定位到该块组的页面单位,例如:order=2时,page[4]
#define VM_ORDER_TO_PHYS(order) (1 << (PAGE_SHIFT + (order)))//通过order块组跳到物理地址
#define VM_PHYS_TO_ORDER(phys) (min(LOS_LowBitGet((phys) >> PAGE_SHIFT), VM_LIST_ORDER_MAX - 1))//通过物理地址定位到order
......
......@@ -491,7 +491,10 @@ LosVmPage *LOS_PhysPageAlloc(VOID)
{
return OsVmPhysPagesGet(ONE_PAGE);//分配一页物理页
}
/******************************************************************************
分配nPages页个物理页框,并将页框挂入list
返回已分配的页面大小,不负责一定能分配到nPages的页框
******************************************************************************/
size_t LOS_PhysPagesAlloc(size_t nPages, LOS_DL_LIST *list)
{
LosVmPage *page = NULL;
......@@ -506,7 +509,7 @@ size_t LOS_PhysPagesAlloc(size_t nPages, LOS_DL_LIST *list)
if (page == NULL) {
break;
}
LOS_ListTailInsert(list, &page->node);//从参数链表list尾部入新页面结点
LOS_ListTailInsert(list, &page->node);//从参数链表list尾部入新页面结点
count++;
}
......
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sys_config.h"
#include "los_oom.h"
#include "los_vm_dump.h"
#include "los_vm_lock.h"
#include "los_vm_phys.h"
#include "los_vm_filemap.h"
#include "los_process_pri.h"
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#include "los_swtmr_pri.h"
#endif
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS OomCB *g_oomCB = NULL;
static SPIN_LOCK_INIT(g_oomSpinLock);//内存溢出自旋锁
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomScoreProcess(LosProcessCB *candidateProcess)
{
UINT32 actualPm;
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxAcquire(&candidateProcess->vmSpace->regionMux);
#endif
/* we only consider actual physical memory here. */ //只考虑实际的物理内存
OsUProcessPmUsage(candidateProcess->vmSpace, NULL, &actualPm);
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxRelease(&candidateProcess->vmSpace->regionMux);
#endif
return actualPm;
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomKillProcess(UINTPTR param)
{
/* we will not kill process, and do nothing here */
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomForceShrinkMemory(VOID)
{
UINT32 i;
UINT32 reclaimMemPages = 0;
/*
* TryShrinkMemory maybe reclaim 0 pages in the first time from active list
* to inactive list, and in the second time reclaim memory from inactive list.
*/
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
reclaimMemPages += OsTryShrinkMemory(0);
}
return reclaimMemPages;
}
LITE_OS_SEC_TEXT_MINOR STATIC BOOL OomReclaimPageCache(VOID)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
BOOL isReclaimMemory = FALSE;
UINT32 reclaimMemPages;
UINT32 i;
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isReclaimMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->reclaimMemThreshold;
if (isReclaimMemory) {
/*
* we do force memory reclaim from page cache here.
* if we get memory, we will reclaim pagecache memory again.
* if there is no memory to reclaim, we will return.
*/
reclaimMemPages = OomForceShrinkMemory();
if (reclaimMemPages > 0) {
continue;
}
}
break;
}
return isReclaimMemory;
}
/*
* check is low memory or not, if low memory, try to kill process. //检查内存是否不足,如果内存不足,请尝试终止进程。
* return is kill process or not. //返回是否kill进程
*/
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID)
{
UINT32 totalPm;
UINT32 usedPm;
BOOL isLowMemory = FALSE;
/*
* spinlock the current core schedule, make sure oom process atomic //旋转锁定当前核心计划,确保oom进程原子化
* spinlock other place entering OomCheckProcess, make sure oom process mutex //旋转锁定其他进入OomCheckProcess的地方,确保oom进程互斥
*/
LOS_SpinLock(&g_oomSpinLock);
/* first we will check if we need to reclaim pagecache memory */
if (OomReclaimPageCache() == FALSE) {
goto NO_VICTIM_PROCESS;
}
/* get free bytes */
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isLowMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->lowMemThreshold;
if (isLowMemory) {
PRINTK("[oom] OS is in low memory state\n"
"total physical memory: %#x(byte), used: %#x(byte),"
"free: %#x(byte), low memory threshold: %#x(byte)\n",
totalPm << PAGE_SHIFT, usedPm << PAGE_SHIFT,
(totalPm - usedPm) << PAGE_SHIFT, g_oomCB->lowMemThreshold);
}
NO_VICTIM_PROCESS:
LOS_SpinUnlock(&g_oomSpinLock);
return isLowMemory;
}
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出监测任务开关
STATIC VOID OomWriteEvent(VOID) // OomTaskInit中创建的定时器回调
{
OsWriteResourceEvent(OS_RESOURCE_EVENT_OOM);//写内存溢出事件
}
#endif
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID) //打印内存溢出信息
{
PRINTK("[oom] oom loop task status: %s\n"
" oom low memory threshold: %#x(byte)\n"
" oom reclaim memory threshold: %#x(byte)\n"
" oom check interval: %d(microsecond)\n",
g_oomCB->enabled ? "enabled" : "disabled",
g_oomCB->lowMemThreshold, g_oomCB->reclaimMemThreshold,
g_oomCB->checkInterval);
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold)
{
if ((lowMemThreshold > OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX)) {
PRINTK("[oom] low memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x](byte)\n",
lowMemThreshold, OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN,
OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX);
} else {
g_oomCB->lowMemThreshold = lowMemThreshold;
PRINTK("[oom] set oom low memory threshold %#x(byte) successful\n",
g_oomCB->lowMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
if ((reclaimMemThreshold >= (totalPm << PAGE_SHIFT)) ||
(reclaimMemThreshold < g_oomCB->lowMemThreshold)) {
PRINTK("[oom] reclaim memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x)(byte)\n",
reclaimMemThreshold, g_oomCB->lowMemThreshold, (totalPm << PAGE_SHIFT));
} else {
g_oomCB->reclaimMemThreshold = reclaimMemThreshold;
PRINTK("[oom] set oom reclaim memory threshold %#x(byte) successful\n",
g_oomCB->reclaimMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval)
{
if ((checkInterval >= OOM_CHECK_MIN) && (checkInterval <= OOM_CHECK_MAX)) {
g_oomCB->checkInterval = checkInterval;
PRINTK("[oom] set oom check interval (%d)ms successful\n",
g_oomCB->checkInterval);
} else {
PRINTK("[oom] set oom check interval (%d)ms failed, should be in [%d, %d]\n",
g_oomCB->checkInterval, OOM_CHECK_MIN, OOM_CHECK_MAX);
}
}
//内存溢出任务初始化
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID)
{
g_oomCB = (OomCB *)LOS_MemAlloc(m_aucSysMem0, sizeof(OomCB));
if (g_oomCB == NULL) {
VM_ERR("oom task init failed, malloc OomCB failed.");
return LOS_NOK;
}
g_oomCB->lowMemThreshold = OOM_DEFAULT_LOW_MEM_THRESHOLD;
g_oomCB->reclaimMemThreshold = OOM_DEFAULT_RECLAIM_MEM_THRESHOLD;
g_oomCB->checkInterval = OOM_DEFAULT_CHECK_INTERVAL;
g_oomCB->processVictimCB = (OomFn)OomKillProcess;
g_oomCB->scoreCB = (OomFn)OomScoreProcess;
g_oomCB->enabled = FALSE;
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出检测开关
g_oomCB->enabled = TRUE;
UINT32 ret = LOS_SwtmrCreate(g_oomCB->checkInterval, LOS_SWTMR_MODE_PERIOD, (SWTMR_PROC_FUNC)OomWriteEvent,
&g_oomCB->swtmrID, (UINTPTR)g_oomCB);//创建检测定时器
if (ret != LOS_OK) {
return ret;
}
return LOS_SwtmrStart(g_oomCB->swtmrID);
#else
return LOS_OK;
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sys_config.h"
#include "los_oom.h"
#include "los_vm_dump.h"
#include "los_vm_lock.h"
#include "los_vm_phys.h"
#include "los_vm_filemap.h"
#include "los_process_pri.h"
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#include "los_swtmr_pri.h"
#endif
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS OomCB *g_oomCB = NULL; //全局内存溢出控制块
static SPIN_LOCK_INIT(g_oomSpinLock);//内存溢出自旋锁
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomScoreProcess(LosProcessCB *candidateProcess)
{
UINT32 actualPm;
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxAcquire(&candidateProcess->vmSpace->regionMux);
#endif
/* we only consider actual physical memory here. */ //只考虑实际的物理内存
OsUProcessPmUsage(candidateProcess->vmSpace, NULL, &actualPm);
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxRelease(&candidateProcess->vmSpace->regionMux);
#endif
return actualPm;
}
//内存不足时,进程
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomKillProcess(UINTPTR param)
{
/* we will not kill process, and do nothing here */
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomForceShrinkMemory(VOID)
{
UINT32 i;
UINT32 reclaimMemPages = 0;
/*
* TryShrinkMemory maybe reclaim 0 pages in the first time from active list
* to inactive list, and in the second time reclaim memory from inactive list.
*/
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
reclaimMemPages += OsTryShrinkMemory(0);
}
return reclaimMemPages;
}
LITE_OS_SEC_TEXT_MINOR STATIC BOOL OomReclaimPageCache(VOID)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
BOOL isReclaimMemory = FALSE;
UINT32 reclaimMemPages;
UINT32 i;
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isReclaimMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->reclaimMemThreshold;
if (isReclaimMemory) {
/*
* we do force memory reclaim from page cache here.
* if we get memory, we will reclaim pagecache memory again.
* if there is no memory to reclaim, we will return.
*/
reclaimMemPages = OomForceShrinkMemory();
if (reclaimMemPages > 0) {
continue;
}
}
break;
}
return isReclaimMemory;
}
/*
* check is low memory or not, if low memory, try to kill process. //检查内存是否不足,如果内存不足,请尝试终止进程。
* return is kill process or not. //返回是否kill进程
*/
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID)
{
UINT32 totalPm;
UINT32 usedPm;
BOOL isLowMemory = FALSE;
/*
* spinlock the current core schedule, make sure oom process atomic //旋转锁定当前核心计划,确保oom进程原子化
* spinlock other place entering OomCheckProcess, make sure oom process mutex //旋转锁定其他进入OomCheckProcess的地方,确保oom进程互斥
*/
LOS_SpinLock(&g_oomSpinLock);
/* first we will check if we need to reclaim pagecache memory */
if (OomReclaimPageCache() == FALSE) {
goto NO_VICTIM_PROCESS;
}
/* get free bytes */
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isLowMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->lowMemThreshold;
if (isLowMemory) {
PRINTK("[oom] OS is in low memory state\n"
"total physical memory: %#x(byte), used: %#x(byte),"
"free: %#x(byte), low memory threshold: %#x(byte)\n",
totalPm << PAGE_SHIFT, usedPm << PAGE_SHIFT,
(totalPm - usedPm) << PAGE_SHIFT, g_oomCB->lowMemThreshold);
}
NO_VICTIM_PROCESS:
LOS_SpinUnlock(&g_oomSpinLock);
return isLowMemory;
}
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出监测任务开关
STATIC VOID OomWriteEvent(VOID) // OomTaskInit中创建的定时器回调
{
OsWriteResourceEvent(OS_RESOURCE_EVENT_OOM);//写内存溢出事件
}
#endif
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID) //打印内存溢出信息
{
PRINTK("[oom] oom loop task status: %s\n"
" oom low memory threshold: %#x(byte)\n"
" oom reclaim memory threshold: %#x(byte)\n"
" oom check interval: %d(microsecond)\n",
g_oomCB->enabled ? "enabled" : "disabled",
g_oomCB->lowMemThreshold, g_oomCB->reclaimMemThreshold,
g_oomCB->checkInterval);
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold)
{
if ((lowMemThreshold > OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX)) {
PRINTK("[oom] low memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x](byte)\n",
lowMemThreshold, OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN,
OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX);
} else {
g_oomCB->lowMemThreshold = lowMemThreshold;
PRINTK("[oom] set oom low memory threshold %#x(byte) successful\n",
g_oomCB->lowMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
if ((reclaimMemThreshold >= (totalPm << PAGE_SHIFT)) ||
(reclaimMemThreshold < g_oomCB->lowMemThreshold)) {
PRINTK("[oom] reclaim memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x)(byte)\n",
reclaimMemThreshold, g_oomCB->lowMemThreshold, (totalPm << PAGE_SHIFT));
} else {
g_oomCB->reclaimMemThreshold = reclaimMemThreshold;
PRINTK("[oom] set oom reclaim memory threshold %#x(byte) successful\n",
g_oomCB->reclaimMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval)
{
if ((checkInterval >= OOM_CHECK_MIN) && (checkInterval <= OOM_CHECK_MAX)) {
g_oomCB->checkInterval = checkInterval;
PRINTK("[oom] set oom check interval (%d)ms successful\n",
g_oomCB->checkInterval);
} else {
PRINTK("[oom] set oom check interval (%d)ms failed, should be in [%d, %d]\n",
g_oomCB->checkInterval, OOM_CHECK_MIN, OOM_CHECK_MAX);
}
}
//内存溢出任务初始化
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID)
{
g_oomCB = (OomCB *)LOS_MemAlloc(m_aucSysMem0, sizeof(OomCB));
if (g_oomCB == NULL) {
VM_ERR("oom task init failed, malloc OomCB failed.");
return LOS_NOK;
}
g_oomCB->lowMemThreshold = OOM_DEFAULT_LOW_MEM_THRESHOLD;
g_oomCB->reclaimMemThreshold = OOM_DEFAULT_RECLAIM_MEM_THRESHOLD;
g_oomCB->checkInterval = OOM_DEFAULT_CHECK_INTERVAL;
g_oomCB->processVictimCB = (OomFn)OomKillProcess;
g_oomCB->scoreCB = (OomFn)OomScoreProcess;
g_oomCB->enabled = FALSE;
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出检测开关
g_oomCB->enabled = TRUE;
UINT32 ret = LOS_SwtmrCreate(g_oomCB->checkInterval, LOS_SWTMR_MODE_PERIOD, (SWTMR_PROC_FUNC)OomWriteEvent,
&g_oomCB->swtmrID, (UINTPTR)g_oomCB);//创建检测定时器
if (ret != LOS_OK) {
return ret;
}
return LOS_SwtmrStart(g_oomCB->swtmrID);
#else
return LOS_OK;
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
......@@ -212,7 +212,12 @@ STATIC VOID ShmPagesRefDec(struct shmIDSource *seg)
LOS_AtomicDec(&page->refCounts);
}
}
//分配共享页
/******************************************************************************
为共享段分配物理内存
例如:参数size = 4097, LOS_Align(size, PAGE_SIZE) = 8192
分配页数 size >> PAGE_SHIFT = 2页
******************************************************************************/
STATIC INT32 ShmAllocSeg(key_t key, size_t size, int shmflg)
{
INT32 i;
......@@ -224,9 +229,9 @@ STATIC INT32 ShmAllocSeg(key_t key, size_t size, int shmflg)
(size > g_shmInfo.shmmax)) {
return -EINVAL;
}
size = LOS_Align(size, PAGE_SIZE);
size = LOS_Align(size, PAGE_SIZE);//必须对齐
for (i = 0; i < g_shmInfo.shmmni; i++) {
for (i = 0; i < g_shmInfo.shmmni; i++) {//试图找到一个空闲段与参数key绑定
if (g_shmSegs[i].status & SHM_SEG_FREE) {//找到空闲段
g_shmSegs[i].status &= ~SHM_SEG_FREE;//变成非空闲状态
segNum = i;//标号
......@@ -240,17 +245,17 @@ STATIC INT32 ShmAllocSeg(key_t key, size_t size, int shmflg)
seg = &g_shmSegs[segNum];
count = LOS_PhysPagesAlloc(size >> PAGE_SHIFT, &seg->node);//分配共享页面,函数内部把node都挂好了.
if (count != (size >> PAGE_SHIFT)) {//异常释放
(VOID)LOS_PhysPagesFree(&seg->node);//
seg->status = SHM_SEG_FREE;//回归seg池
if (count != (size >> PAGE_SHIFT)) {//当未分配到足够的内存时,处理方式是:不稀罕给那么点,舍弃!
(VOID)LOS_PhysPagesFree(&seg->node);//释放节点上的物理页框
seg->status = SHM_SEG_FREE;//共享段变回空闲状态
return -ENOMEM;
}
ShmSetSharedFlag(seg);//node的每个页面设置为此乃共享页也
ShmSetSharedFlag(seg);//将node的每个页面设置为共享页
seg->status |= SHM_SEG_USED; //段已使用
seg->status |= SHM_SEG_USED; //共享段贴上已在使用的标签
seg->ds.shm_perm.mode = (unsigned int)shmflg & ACCESSPERMS; //使用权限
seg->ds.shm_perm.key = key;//
seg->ds.shm_segsz = size;
seg->ds.shm_perm.key = key;//保存参数key,如此 key 和 共享ID绑定在一块
seg->ds.shm_segsz = size; //共享段的大小
seg->ds.shm_perm.cuid = LOS_GetUserID(); //设置用户ID
seg->ds.shm_perm.uid = LOS_GetUserID(); //设置用户ID
seg->ds.shm_perm.cgid = LOS_GetGroupID(); //设置组ID
......@@ -285,10 +290,10 @@ STATIC INT32 ShmFindSegByKey(key_t key)
INT32 i;
struct shmIDSource *seg = NULL;
for (i = 0; i < g_shmInfo.shmmni; i++) {
for (i = 0; i < g_shmInfo.shmmni; i++) {//遍历共享段池,找到与key绑定的共享ID
seg = &g_shmSegs[i];
if ((seg->status & SHM_SEG_USED) &&
(seg->ds.shm_perm.key == key)) {
(seg->ds.shm_perm.key == key)) {//满足两个条件,找到后返回
return i;
}
}
......@@ -311,7 +316,7 @@ STATIC INT32 ShmSegValidCheck(INT32 segNum, size_t size, int shmFalg)
return segNum;
}
//通过ID找到资源
//通过ID找到共享内存资源
STATIC struct shmIDSource *ShmFindSeg(int shmid)
{
struct shmIDSource *seg = NULL;
......@@ -390,7 +395,7 @@ BOOL OsIsShmRegion(LosVmMapRegion *region)
{
return (region->regionFlags & VM_MAP_REGION_FLAG_SHM) ? TRUE : FALSE;
}
//使用共享段数量
//获取共享内存池中已被使用的段数量
STATIC INT32 ShmSegUsedCount(VOID)
{
INT32 i;
......@@ -399,16 +404,16 @@ STATIC INT32 ShmSegUsedCount(VOID)
for (i = 0; i < g_shmInfo.shmmni; i++) {
seg = &g_shmSegs[i];
if (seg->status & SHM_SEG_USED) {
if (seg->status & SHM_SEG_USED) {//找到一个
count++;
}
}
return count;
}
//共享内存权限检查
//对共享内存段权限检查
STATIC INT32 ShmPermCheck(struct shmIDSource *seg, mode_t mode)
{
INT32 uid = LOS_GetUserID();
INT32 uid = LOS_GetUserID();//当前进程的用户ID
UINT32 tmpMode = 0;
mode_t privMode = seg->ds.shm_perm.mode;
mode_t accMode;
......
git add -A
git commit -m '完善共享内存几个结构体的注解.
git commit -m '开始注解(OOM)内存不足时的处理.
搜索 @note_pic 方便理解画的字符图
搜索 @note_why 尚未看明白的地方,如果您看明白了,请告知完善
搜索 @note_thinking 一点思考和吐槽的地方
......
#include <stdio.h>
#include <stdarg.h>
#include "turing.h"
typedef unsigned int UINTPTR;
typedef unsigned char UINT8;
typedef unsigned long PTE_T;
typedef unsigned long VADDR_T;
#define IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1)))
typedef struct LOS_DL_LIST {
struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node */
struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node */
} LOS_DL_LIST;
LITE_OS_SEC_TEXT UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary)
{
if ((addr + boundary - 1) > addr) {
return (addr + boundary - 1) & ~((UINTPTR)(boundary - 1));
} else {
return addr & ~((UINTPTR)(boundary - 1));
}
}
void b(){
UINT8 w[3]={0};
PTE_T pte1BasePtr = 0x11100000;
VADDR_T vaddr = 0x80738903;
#define MMU_DESCRIPTOR_L1_SMALL_SIZE 0x100000 //1M
#define MMU_DESCRIPTOR_L1_SMALL_MASK (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1)
#define MMU_DESCRIPTOR_L1_SMALL_FRAME (~MMU_DESCRIPTOR_L1_SMALL_MASK)
#define MMU_DESCRIPTOR_L1_SMALL_SHIFT 20
#define MMU_DESCRIPTOR_L1_SECTION_ADDR(x) ((x) & MMU_DESCRIPTOR_L1_SMALL_FRAME)
#define OS_TSK_HIGH_BITS 3U
#define OS_TSK_LOW_BITS (32U - OS_TSK_HIGH_BITS) //29
#define OS_TSK_SORTLINK_LOGLEN OS_TSK_HIGH_BITS //3U
PTE_T l1Entry = pte1BasePtr + vaddr >> MMU_DESCRIPTOR_L1_SMALL_SHIFT;
printf("pte1BasePtr ad: %x\n",&pte1BasePtr);
printf("w[1] ad: %x\n",&w[1]);
......@@ -35,19 +23,12 @@ void b(){
printf("MMU_DESCRIPTOR_L1_SMALL_FRAME:%x\n",MMU_DESCRIPTOR_L1_SMALL_FRAME);
printf("pa: %x\n",MMU_DESCRIPTOR_L1_SECTION_ADDR(l1Entry) + (vaddr & (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1)));
}
void a(){
#define BITMAP_BITS_PER_WORD (sizeof(UINTPTR) * 8)
#define BITMAP_NUM_WORDS(x) (((x) + BITMAP_BITS_PER_WORD - 1) / BITMAP_BITS_PER_WORD)
printf("BITMAP_BITS_PER_WORD %d\n",BITMAP_BITS_PER_WORD);
printf("BITMAP_NUM_WORDS %d\n",BITMAP_NUM_WORDS(1UL << 8));
}
void round1(){
#define PAGE_SIZE (0x1000U) // 页大小4K
#define ROUNDUP(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#define ROUNDDOWN(a, b) ((a) & ~((b) - 1))
#define ROUNDOFFSET(a, b) ((a) & ((b) - 1))
int a = 0xFF;
//printf("a>> %d\n",a>>3);
//printf("a/ %d\n",a/8);
......@@ -77,13 +58,14 @@ void arg_test(int i, ...)
}
int main()
{
int size = 0;
printf("sizeof(int) %d\n",sizeof(int));
round1();
int size = 4097;
size = LOS_Align(size, PAGE_SIZE);//必须对齐
printf("sizeof(int) %d\n",size);
//round1();
//arg_test(99, 4,8,9);
//size = sizeof(LOS_DL_LIST) << OS_TSK_SORTLINK_LOGLEN;
//printf("LOS_DL_LIST %d\n",sizeof(LOS_DL_LIST *));
//printf("size %d\n",size);
return 0;
}
// gcc -o main main.c
typedef unsigned int UINTPTR;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef unsigned long PTE_T;
typedef unsigned long VADDR_T;
#define IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1)))
#define PAGE_SIZE (0x1000U) // 页大小4K
#define ROUNDUP(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#define ROUNDDOWN(a, b) ((a) & ~((b) - 1))
#define ROUNDOFFSET(a, b) ((a) & ((b) - 1))
#define MMU_DESCRIPTOR_L1_SMALL_SIZE 0x100000 //1M
#define MMU_DESCRIPTOR_L1_SMALL_MASK (MMU_DESCRIPTOR_L1_SMALL_SIZE - 1)
#define MMU_DESCRIPTOR_L1_SMALL_FRAME (~MMU_DESCRIPTOR_L1_SMALL_MASK)
#define MMU_DESCRIPTOR_L1_SMALL_SHIFT 20
#define MMU_DESCRIPTOR_L1_SECTION_ADDR(x) ((x) & MMU_DESCRIPTOR_L1_SMALL_FRAME)
#define OS_TSK_HIGH_BITS 3U
#define OS_TSK_LOW_BITS (32U - OS_TSK_HIGH_BITS) //29
#define OS_TSK_SORTLINK_LOGLEN OS_TSK_HIGH_BITS //3U
#define BITMAP_BITS_PER_WORD (sizeof(UINTPTR) * 8)
#define BITMAP_NUM_WORDS(x) (((x) + BITMAP_BITS_PER_WORD - 1) / BITMAP_BITS_PER_WORD)
#ifndef LITE_OS_SEC_TEXT
#define LITE_OS_SEC_TEXT /* __attribute__((section(".text.sram"))) */
#endif
typedef struct LOS_DL_LIST {
struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node */
struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node */
} LOS_DL_LIST;
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册