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

注解支持doxygen格式,基本修改完成

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    博客输出站点(国内):http://weharmonyos.com
    博客输出站点(国外):https://weharmony.github.io
    注解文件系统:https://gitee.com/weharmony/third_party_NuttX
    注解协议栈:https://gitee.com/weharmony/third_party_lwip
    注解编译子系统:https://gitee.com/weharmony/build_lite
上级 e3ea607a
......@@ -338,7 +338,7 @@ UINT32 OsArmSharedPageFault(UINT32 excType, ExcContext *frame, UINT32 far, UINT3
/// 异常类型
STATIC VOID OsExcType(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
{
/* undefinited exception handling or software interrupt */ //未定义的异常处理或软件中断
/* undefinited exception handling or software interrupt | 未定义的异常处理或软件中断 */
if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI))
{
if ((excBufAddr->regCPSR & INSTR_SET_MASK) == 0)
......@@ -644,8 +644,13 @@ STATIC VOID OsDumpProcessUsedMemNode(UINT16 vmmFalgs)
return;
}
#endif
//dump 上下文内存,注意内核异常不能简单的映射理解为应用的异常,异常对内核来说是一个很常见操作,
//比如任务的切换对内核来说就是一个异常处理
/** 打印异常上下文
* @brief dump 上下文内存,注意内核异常不能简单的映射理解为应用的异常,异常对内核来说是一个很常见操作,
\n 比如任务的切换对内核来说就是一个异常处理
* @param excBufAddr
* @return VOID
*/
VOID OsDumpContextMem(const ExcContext *excBufAddr)
{
UINT32 count = 0;
......@@ -814,7 +819,7 @@ STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end
return found;
}
/* Search in the task stacks */ //找任务的内核态栈
/* Search in the task stacks | 找任务的内核态栈*/
for (index = 0; index < g_taskMaxNum; index++)
{
taskCB = &g_taskCBArray[index];
......
......@@ -49,13 +49,13 @@ extern "C" {
/**
* @ingroup los_hwi
* Count of interrupts.
*/ //中断次数,每个CPU都会记录响应中断的次数
extern size_t g_intCount[];
*/
extern size_t g_intCount[];///< 中断次数,每个CPU都会记录响应中断的次数
/**
* @ingroup los_hwi
* An interrupt is active.
*/ //中断处于活动状态
* An interrupt is active. | 中断处于活动状态
*/
#define OS_INT_ACTIVE ({ \
size_t intCount; \
UINT32 intSave_ = LOS_IntLock(); \
......@@ -66,36 +66,36 @@ extern size_t g_intCount[];
/**
* @ingroup los_hwi
* An interrupt is inactive.
*/ //中断处于非活动状态
* An interrupt is inactive. | 中断处于非活动状态
*/
#define OS_INT_INACTIVE (!(OS_INT_ACTIVE))
/**
* @ingroup los_hwi
* Highest priority of a hardware interrupt.
*/ //硬件中断的最高优先级
* Highest priority of a hardware interrupt. | 硬件中断的最高优先级
*/
#define OS_HWI_PRIO_HIGHEST 0
/**
* @ingroup los_hwi
* Lowest priority of a hardware interrupt.
*/ //硬件中断的最低优先级
* Lowest priority of a hardware interrupt. | 硬件中断的最低优先级
*/
#define OS_HWI_PRIO_LOWEST 31
/**
* @ingroup los_hwi
* Max name length of a hardware interrupt.
*/ //硬件中断的最大名称长度
* Max name length of a hardware interrupt. | 硬件中断的最大名称长度
*/
#define OS_HWI_MAX_NAMELEN 10
/**
* @ingroup los_hwi
* Hardware interrupt error code: Invalid interrupt number.
* Hardware interrupt error code: Invalid interrupt number. | 创建或删除中断时,传入了无效中断号
*
* Value: 0x02000900
*
* Solution: Ensure that the interrupt number is valid.
*/ //创建或删除中断时,传入了无效中断号
*/
#define OS_ERRNO_HWI_NUM_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x00)
/**
......
......@@ -434,7 +434,7 @@ static CHAR GPTPartitionTypeRecognition(const CHAR *parBuf)
{
const CHAR *buf = parBuf;
const CHAR *fsType = "FAT";
const CHAR *str = "\xEB\x52\x90" "NTFS "; /* NTFS Boot entry point */ //NTFS 引导入口点
const CHAR *str = "\xEB\x52\x90" "NTFS "; /* NTFS Boot entry point | NTFS 引导入口点*/
if (((LD_DWORD_DISK(&buf[BS_FILSYSTEMTYPE32]) & BS_FS_TYPE_MASK) == BS_FS_TYPE_VALUE) ||
(strncmp(&buf[BS_FILSYSTYPE], fsType, strlen(fsType)) == 0)) {//识别FAT的方法
......@@ -1276,7 +1276,7 @@ static VOID DiskCacheDeinit(los_disk *disk)
}
}
#endif
//磁盘结构体初始化,初始化 los_disk 结构体
///磁盘结构体初始化,初始化 los_disk 结构体
static VOID DiskStructInit(const CHAR *diskName, INT32 diskID, const struct geometry *diskInfo,
struct Vnode *blkDriver, los_disk *disk)
{
......
......@@ -64,7 +64,7 @@ extern "C" {
#define MBR_PRIMARY_PART_NUM 4
#define JUMP_CODE "\xEB\xFE\x90"
/* Partiton type */ //分区类型
/* Partiton type | 分区类型*/
#define FAT12 0x01 /* FAT12 as primary partition in first physical 32MB */
#define FAT16 0x04 /* FAT16 with less than 65536 sectors(32MB) */
#define EXTENDED_PARTITION_CHS 0x05
......@@ -74,13 +74,13 @@ extern "C" {
#define EXTENDED_PARTITION_LBA 0x0F
#define GPT_PROTECTIVE_MBR 0xEE
/* volume boot record type */ //卷引导记录类型
/* volume boot record type | 卷引导记录类型 */
#define VBR_FAT 0
#define VBR_BS_NOT_FAT 2
#define VBR_NOT_BS 3
#define VBR_DISK_ERR 4
/* Limit and boundary */ //限制和边界
/* Limit and boundary | 限制和边界*/
#define FAT_MAX_CLUSTER_SIZE 64 /* (sectors) */
#define FAT32_MAX_CLUSTER_SIZE 128 /* (sectors) */
#define FAT32_ENTRY_SIZE 4 /* (bytes) */
......@@ -89,7 +89,7 @@ extern "C" {
#define SFD_START_SECTOR 63
#define MAX_BLOCK_SIZE 32768 /* (sectors) */
/* Sector */ //扇区
/* Sector | 扇区*/
#define FAT32_RESERVED_SECTOR 32
#define FAT_RESERVED_SECTOR 1
......
......@@ -49,7 +49,7 @@
#else
#define STORAGE_TYPE "emmc"
#endif
//分区信息
///分区信息
struct PartitionInfo {
const CHAR *partName; //分区名称
const CHAR *cmdlineArgName; //命令行参数名称
......
......@@ -82,7 +82,10 @@ typedef unsigned short fmode_t;
#define FMODE_READ ((fmode_t)0x1)
struct ProcFile;
//真正最后能操作pro file的接口,proc本质是个内存文件系统, vfs - > ProcFileOperations
/**
* @brief 真正最后能操作pro file的接口,proc本质是个内存文件系统, vfs - > ProcFileOperations
*/
struct ProcFileOperations {
char *name;
ssize_t (*write)(struct ProcFile *pf, const char *buf, size_t count, loff_t *ppos);
......@@ -90,33 +93,40 @@ struct ProcFileOperations {
int (*release)(struct Vnode *vnode, struct ProcFile *pf);
int (*read)(struct SeqBuf *m, void *v);
};
//proc 目录/文件项, @notethinking 直接叫 ProcEntry不香吗 ?
struct ProcDirEntry {//这才是能操作 /proc的 真正结构体
/**
* @brief proc 目录/文件项, @notethinking 直接叫 ProcEntry不香吗 ?
* \n 操作 /proc的 真正结构体
*/
struct ProcDirEntry {
uint uid;
uint gid;
mode_t mode; //模式(读|写...)
int flags; //标签
const struct ProcFileOperations *procFileOps;//驱动程序,每个 /proc 下目录的驱动程序都不一样
struct ProcFile *pf;//proc文件指针
struct ProcDirEntry *next, *parent, *subdir;//当前目录项的关系项
mode_t mode; ///<模式(读|写...)
int flags; ///<标签
const struct ProcFileOperations *procFileOps; ///< 驱动程序,每个 /proc 下目录的驱动程序都不一样
struct ProcFile *pf; ///<proc文件指针
struct ProcDirEntry *next, *parent, *subdir; ///<当前目录项的关系项
void *data;
atomic_t count; /* open file count */ //打开文件的数量
atomic_t count; /* open file count | 打开文件的数量*/
spinlock_t pdeUnloadLock;
int nameLen;
struct ProcDirEntry *pdirCurrent;//当前目录
struct ProcDirEntry *pdirCurrent; ///<当前目录
char name[NAME_MAX];
enum VnodeType type; //节点类型
enum VnodeType type; ///<节点类型
};
//Proc文件结构体,对标 FILE 结构体
/**
* @brief Proc文件结构体,对标 FILE 结构体
*/
struct ProcFile {
fmode_t fMode; //操作文件的模式
spinlock_t fLock; //自旋锁
atomic_t fCount; //原子操作
struct SeqBuf *sbuf;//序列号BUF
struct ProcDirEntry *pPDE;//目录项
unsigned long long fVersion;//版本号
loff_t fPos; //文件操作偏移位
char name[NAME_MAX];//文件名
fmode_t fMode; ///< 操作文件的模式
spinlock_t fLock; ///< 自旋锁
atomic_t fCount; ///< 原子操作
struct SeqBuf *sbuf; ///< 序列号BUF
struct ProcDirEntry *pPDE; ///< 目录项
unsigned long long fVersion; ///< 版本号
loff_t fPos; ///<文件操作偏移位
char name[NAME_MAX]; ///<文件名
};
struct ProcStat {
......
......@@ -134,7 +134,7 @@ INT32 LOS_SetSyncThreadPrio(UINT32 prio, const CHAR *name)
return ret;
}
#endif
//红黑树找块
///红黑树找块
static OsBcacheBlock *RbFindBlock(const OsBcache *bc, UINT64 num)
{
OsBcacheBlock *block = NULL;
......
......@@ -40,7 +40,7 @@
#ifdef LOSCFG_KERNEL_VM
static struct file_map g_file_mapping = {0};//用于挂载所有文件的file_map
static struct file_map g_file_mapping = {0}; ///< 用于挂载所有文件的file_map
#if 0
定义见于 ..\third_party\NuttX\include\nuttx\fs\fs.h
......@@ -135,11 +135,15 @@ static struct page_mapping *find_mapping_nolock(const char *fullpath)
return NULL;
}
/**************************************************************************************************
增加一个文件映射,这个函数被do_open()函数调用,每打开一次文件就会调用一次
/**
* @brief 增加一个文件映射,这个函数被do_open()函数调用,每打开一次文件就会调用一次
注意不同的进程打开同一个文件,拿到的file是不一样的。
https://blog.csdn.net/cywosp/article/details/38965239
**************************************************************************************************/
* @param filep
* @param fullpath
*/
void add_mapping(struct file *filep, const char *fullpath)
{
int path_len;
......@@ -190,12 +194,14 @@ out:
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
}
/******************************************************************************
删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系.
以无锁的方式删除映射
******************************************************************************/
/**
* @brief 删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系.
以无锁的方式删除映射
* @param mapping
* @return int
*/
int remove_mapping_nolock(struct page_mapping *mapping)
{
struct file_map *fmap = NULL;
......
......@@ -41,21 +41,27 @@
#include "sys/statfs.h"
#include "unistd.h"
#include "vnode.h"
/********************************************************
* VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,
* 为用户提供统一的类Unix文件操作接口。
* 由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。
* 而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用
* 关心底层的存储介质和文件系统类型,提高开发效率。
/**
* @file vfs_init.c
* @brief
* @verbatim
VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,
为用户提供统一的类Unix文件操作接口。
* OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。
* 设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能:
* 查找节点。
* 统一调用(标准)。
由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。
而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用
关心底层的存储介质和文件系统类型,提高开发效率。
OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。
设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能:
查找节点。
统一调用(标准)。
http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/VFS.html
* @endverbatim
*/
* https://weharmony.gitee.io/openharmony/zh-cn/device-dev/kernel/VFS.html
********************************************************/
void los_vfs_init(void)//只能调用一次,多次调用将会造成文件系统异常
{
uint retval;
......
......@@ -36,7 +36,7 @@
#ifdef LOSCFG_NET_LWIP_SACK
#include "lwip/sockets.h"
#endif
//对进程文件表操作上锁
///对进程文件表操作上锁
void FileTableLock(struct fd_table_s *fdt)
{
/* Take the semaphore (perhaps waiting) */
......
......@@ -1490,13 +1490,18 @@ static inline void print_rm_usage(void)
{
PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
}
/*****************************************************************
rm命令用来删除文件或文件夹。rm [-r] [dirname / filename]
rm命令一次只能删除一个文件或文件夹。
rm -r命令可以删除非空目录。
rm log1.txt ; rm -r sd
*****************************************************************/
/**
* @brief
* @verbatim rm命令用来删除文件或文件夹。rm [-r] [dirname / filename]
rm命令一次只能删除一个文件或文件夹。
rm -r命令可以删除非空目录。
rm log1.txt ; rm -r sd
@endverbatim
* @param argc
* @param argv
* @return int
*/
int osShellCmdRm(int argc, const char **argv)
{
int ret = 0;
......
......@@ -35,6 +35,7 @@
/**
* @brief
* @ver
*/
LIST_HEAD g_vnodeFreeList; /* free vnodes list | 空闲节点链表*/
......
......@@ -1424,10 +1424,10 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
/*
* Description : Process pending signals tagged by others cores
*/
/******************************************************
/*!
由其他CPU核触发阻塞进程的信号
函数由汇编代码调用 ..\arch\arm\arm\src\los_dispatch.S
******************************************************/
*/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID)
{
UINT32 intSave, ret;
......
......@@ -51,18 +51,22 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**************************************************************************************************
磁盘高速缓存是一种软件机制,它允许系统把通常存放在磁盘上的一些数据保留在 RAM 中,以便对那些数据的
进一步访问不用再访问磁盘而能尽快得到满足。
页高速缓存中的信息单位是一个完整的页。
一个页包含的磁盘块在物理上不一定相邻,所以不能用设备号和块号标识,而是通过页的所有者和所有者数据中的索引来识别。
页高速缓存可以缓存以下内容
A.普通文件数据
B.含有目录的页
C.直接从快设备读取的页
D.用户进程数据的页
E.特殊文件系统的文件页
**************************************************************************************************/
/**
* @brief
* @verbatim
磁盘高速缓存是一种软件机制,它允许系统把通常存放在磁盘上的一些数据保留在 RAM 中,以便对那些数据的
进一步访问不用再访问磁盘而能尽快得到满足。
页高速缓存中的信息单位是一个完整的页。
一个页包含的磁盘块在物理上不一定相邻,所以不能用设备号和块号标识,而是通过页的所有者和所有者数据中的索引来识别。
页高速缓存可以缓存以下内容
A.普通文件数据
B.含有目录的页
C.直接从快设备读取的页
D.用户进程数据的页
E.特殊文件系统的文件页
* @endverbatim
*
*/
#if 0 //@note_#if0
//page_mapping描述的是一个文件在内存中被映射了多少页,<文件,文件页的关系>
/* file mapped in VMM pages */
......@@ -86,134 +90,134 @@ struct file_map { //为在内核层面文件在内存的身份证,每个需映
#endif
//文件页结构体
/// 文件页结构体
typedef struct FilePage {
LOS_DL_LIST node; //节点,节点挂到page_mapping.page_list上,链表以 pgoff 从小到大方式排序.
LOS_DL_LIST lru; //lru节点, 结合 LosVmPhysSeg: LOS_DL_LIST lruList[VM_NR_LRU_LISTS] 理解
LOS_DL_LIST i_mmap; /* list of mappings */ //链表记录文件页被哪些进程映射 MapInfo.node挂上来
UINT32 n_maps; /* num of mapping */ //记录被进程映射的次数
struct VmPhysSeg *physSeg; /* physical memory that file page belongs to */ //物理段:物理页框 = 1:N
struct VmPage *vmPage; //物理页框
struct page_mapping *mapping; //此结构由文件系统提供,用于描述装入点 见于 ..\third_party\NuttX\include\nuttx\fs\fs.h
VM_OFFSET_T pgoff; //页标,文件被切成一页一页读到内存
UINT32 flags; //标签
UINT16 dirtyOff; //脏页的页内偏移地址
UINT16 dirtyEnd; //脏页的结束位置
LOS_DL_LIST node; ///< 节点,节点挂到page_mapping.page_list上,链表以 pgoff 从小到大方式排序.
LOS_DL_LIST lru; ///< lru节点, 结合 LosVmPhysSeg: LOS_DL_LIST lruList[VM_NR_LRU_LISTS] 理解
LOS_DL_LIST i_mmap; /* list of mappings | 链表记录文件页被哪些进程映射 MapInfo.node挂上来*/
UINT32 n_maps; /* num of mapping | 记录被进程映射的次数*/
struct VmPhysSeg *physSeg; /* physical memory that file page belongs to | 物理段:物理页框 = 1:N */
struct VmPage *vmPage; ///< 物理页框
struct page_mapping *mapping; ///< 此结构由文件系统提供,用于描述装入点 见于 ..\third_party\NuttX\include\nuttx\fs\fs.h
VM_OFFSET_T pgoff; ///< 页标,文件被切成一页一页读到内存
UINT32 flags; ///< 标签
UINT16 dirtyOff; ///< 脏页的页内偏移地址
UINT16 dirtyEnd; ///< 脏页的结束位置
} LosFilePage;
//虚拟地址和文件页的映射信息
typedef struct MapInfo {//在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作.
LOS_DL_LIST node; //节点,挂到page->i_mmap链表上.链表上记录要操作文件页的进程对这个page的映射信息
VADDR_T vaddr; //虚拟地址.每个进程访问同一个文件页的虚拟地址都是不一样的
LosFilePage *page; //文件页中只记录物理地址,是不会变的.但它是需要被多个进程访问,和映射的.
LosArchMmu *archMmu;//mmu完成vaddr和page->vmPage->physAddr物理地址的映射
/// 虚拟地址和文件页的映射信息,在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作.
typedef struct MapInfo {
LOS_DL_LIST node; ///< 节点,挂到page->i_mmap链表上.链表上记录要操作文件页的进程对这个page的映射信息
VADDR_T vaddr; ///< 虚拟地址.每个进程访问同一个文件页的虚拟地址都是不一样的
LosFilePage *page; ///< 文件页中只记录物理地址,是不会变的.但它是需要被多个进程访问,和映射的.
LosArchMmu *archMmu; ///< mmu完成vaddr和page->vmPage->physAddr物理地址的映射
} LosMapInfo;
//Flags由 bitmap 管理
/// Flags由 bitmap 管理
enum OsPageFlags {
FILE_PAGE_FREE, //空闲页
FILE_PAGE_LOCKED, //被锁页
FILE_PAGE_REFERENCED, //被引用页
FILE_PAGE_DIRTY, //脏页
FILE_PAGE_LRU, //LRU置换页
FILE_PAGE_ACTIVE, //活动页
FILE_PAGE_SHARED, //共享页
FILE_PAGE_FREE, ///< 空闲页
FILE_PAGE_LOCKED, ///< 被锁页
FILE_PAGE_REFERENCED, ///< 被引用页
FILE_PAGE_DIRTY, ///< 脏页
FILE_PAGE_LRU, ///< LRU置换页
FILE_PAGE_ACTIVE, ///< 活动页
FILE_PAGE_SHARED, ///< 共享页
};
#define PGOFF_MAX 2000
#define MAX_SHRINK_PAGECACHE_TRY 2
#define VM_FILEMAP_MAX_SCAN (SYS_MEM_SIZE_DEFAULT >> PAGE_SHIFT) //扫描文件映射页最大数量
#define VM_FILEMAP_MIN_SCAN 32 //扫描文件映射页最小数量
//给页面贴上被锁的标签
#define VM_FILEMAP_MAX_SCAN (SYS_MEM_SIZE_DEFAULT >> PAGE_SHIFT) ///< 扫描文件映射页最大数量
#define VM_FILEMAP_MIN_SCAN 32 ///< 扫描文件映射页最小数量
/// 给页面贴上被锁的标签
STATIC INLINE VOID OsSetPageLocked(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_LOCKED);
}
///给页面撕掉被锁的标签
/// 给页面撕掉被锁的标签
STATIC INLINE VOID OsCleanPageLocked(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_LOCKED);
}
///给页面贴上数据被修改的标签
/// 给页面贴上数据被修改的标签
STATIC INLINE VOID OsSetPageDirty(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_DIRTY);
}
///给页面撕掉数据被修改的标签
/// 给页面撕掉数据被修改的标签
STATIC INLINE VOID OsCleanPageDirty(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_DIRTY);
}
///给页面贴上活动的标签
/// 给页面贴上活动的标签
STATIC INLINE VOID OsSetPageActive(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_ACTIVE);
}
///给页面撕掉活动的标签
/// 给页面撕掉活动的标签
STATIC INLINE VOID OsCleanPageActive(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_ACTIVE);
}
///给页面贴上置换页的标签
/// 给页面贴上置换页的标签
STATIC INLINE VOID OsSetPageLRU(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_LRU);
}
///给页面贴上被释放的标签
/// 给页面贴上被释放的标签
STATIC INLINE VOID OsSetPageFree(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_FREE);
}
///给页面撕掉被释放的标签
/// 给页面撕掉被释放的标签
STATIC INLINE VOID OsCleanPageFree(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_FREE);
}
///给页面贴上被引用的标签
/// 给页面贴上被引用的标签
STATIC INLINE VOID OsSetPageReferenced(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_REFERENCED);
}
///给页面撕掉被引用的标签
/// 给页面撕掉被引用的标签
STATIC INLINE VOID OsCleanPageReferenced(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_REFERENCED);
}
///页面是否活动
/// 页面是否活动
STATIC INLINE BOOL OsIsPageActive(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_ACTIVE);
}
///页面是否被锁
/// 页面是否被锁
STATIC INLINE BOOL OsIsPageLocked(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_LOCKED);
}
///页面是否被引用,只被一个进程引用的页叫私有页,多个进程引用就是共享页,此为共享内存的本质所在
/// 页面是否被引用,只被一个进程引用的页叫私有页,多个进程引用就是共享页,此为共享内存的本质所在
STATIC INLINE BOOL OsIsPageReferenced(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_REFERENCED);
}
///页面是否为脏页,所谓脏页就是页内数据是否被更新过,只有脏页才会有写时拷贝
/// 页面是否为脏页,所谓脏页就是页内数据是否被更新过,只有脏页才会有写时拷贝
STATIC INLINE BOOL OsIsPageDirty(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_DIRTY);
}
///文件页是否映射过了
/// 文件页是否映射过了
STATIC INLINE BOOL OsIsPageMapped(LosFilePage *page)
{
return (page->n_maps != 0);//由映射的次数来判断
}
/* The follow three functions is used to SHM module */
STATIC INLINE VOID OsSetPageShared(LosVmPage *page)//给页面贴上共享页标签
/*! The follow three functions is used to SHM module | 给页面贴上共享页标签*/
STATIC INLINE VOID OsSetPageShared(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_SHARED);//设为共享页面,共享页位 置0
}
///给页面撕掉共享页标签
/// 给页面撕掉共享页标签
STATIC INLINE VOID OsCleanPageShared(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_SHARED);//共享页位 置0
}
///是否为共享页
/// 是否为共享页
STATIC INLINE BOOL OsIsPageShared(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_SHARED);
......
......@@ -79,8 +79,8 @@ struct page_mapping {
/* If the kernel malloc size is less than 16k, use heap, otherwise use physical pages */
#define KMALLOC_LARGE_SIZE (PAGE_SIZE << 2)
typedef struct VmMapRange {
VADDR_T base; /**< vm region base addr */ //线性区基地址
UINT32 size; /**< vm region size */ //线性区大小
VADDR_T base; /**< vm region base addr | 线性区基地址*/
UINT32 size; /**< vm region size | 线性区大小*/
} LosVmMapRange;
struct VmMapRegion;
......@@ -89,31 +89,31 @@ struct VmFileOps;
typedef struct VmFileOps LosVmFileOps;
struct VmSpace;
typedef struct VmSpace LosVmSpace;
//缺页结构信息体
/// 缺页结构信息体
typedef struct VmFault {
UINT32 flags; /* FAULT_FLAG_xxx flags */ //缺页标识
unsigned long pgoff; /* Logical page offset based on region */ //基于线性区的逻辑页偏移量
VADDR_T vaddr; /* Faulting virtual address */ //产生缺页的虚拟地址
VADDR_T *pageKVaddr; /* KVaddr of pagefault's vm page's paddr */ //page cache中的虚拟地址
UINT32 flags; /*! FAULT_FLAG_xxx flags | 缺页标识*/
unsigned long pgoff; /*! Logical page offset based on region | 基于线性区的逻辑页偏移量*/
VADDR_T vaddr; /*! Faulting virtual address | 产生缺页的虚拟地址*/
VADDR_T *pageKVaddr; /*! KVaddr of pagefault's vm page's paddr | page cache中的虚拟地址*/
} LosVmPgFault;
//虚拟内存文件操作函数指针,上层开发可理解为 class 里的方法,注意是对线性区的操作
struct VmFileOps {// 文件操作 见于g_commVmOps
void (*open)(struct VmMapRegion *region); //打开
void (*close)(struct VmMapRegion *region);//关闭
int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault);//缺页,OsVmmFileFault
void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset);//删除 OsVmmFileRemove
/// 虚拟内存文件操作函数指针,上层开发可理解为 class 里的方法,注意是对线性区的操作 , 文件操作 见于g_commVmOps
struct VmFileOps {
void (*open)(struct VmMapRegion *region); ///< 打开
void (*close)(struct VmMapRegion *region); ///< 关闭
int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault); ///< 缺页,OsVmmFileFault
void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset); ///< 删除 OsVmmFileRemove
};
struct VmMapRegion {//线性区描述符,内核通过线性区管理虚拟地址,而线性地址就是虚拟地址
LosRbNode rbNode; /**< region red-black tree node \n 红黑树节点,通过它将本线性区挂在VmSpace.regionRbTree*/
/// 线性区描述符,内核通过线性区管理虚拟地址,而线性地址就是虚拟地址
struct VmMapRegion {
LosRbNode rbNode; /**< region red-black tree node | 红黑树节点,通过它将本线性区挂在VmSpace.regionRbTree*/
LosVmSpace *space; ///< 所属虚拟空间,虚拟空间由多个线性区组成
LOS_DL_LIST node; /**< region dl list \n 链表节点,通过它将本线性区挂在VmSpace.regions上*/
LosVmMapRange range; /**< region address range \n 记录线性区的范围*/
VM_OFFSET_T pgOff; /**< region page offset to file \n 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射。*/
UINT32 regionFlags; /**< region flags: cow, user_wired \n 线性区标签*/
UINT32 shmid; /**< shmid about shared region \n shmid为共享线性区id,id背后就是共享线性区*/
UINT8 forkFlags; /**< vm space fork flags: COPY, ZERO, \n fork的方式*/
UINT8 regionType; /**< vm region type: ANON, FILE, DEV \n 映射类型是匿名,文件,还是设备,所谓匿名可理解为内存映射*/
LOS_DL_LIST node; /**< region dl list | 链表节点,通过它将本线性区挂在VmSpace.regions上*/
LosVmMapRange range; /**< region address range | 记录线性区的范围*/
VM_OFFSET_T pgOff; /**< region page offset to file | 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射。*/
UINT32 regionFlags; /**< region flags: cow, user_wired | 线性区标签*/
UINT32 shmid; /**< shmid about shared region | shmid为共享线性区id,id背后就是共享线性区*/
UINT8 forkFlags; /**< vm space fork flags: COPY, ZERO, | fork的方式*/
UINT8 regionType; /**< vm region type: ANON, FILE, DEV | 映射类型是匿名,文件,还是设备,所谓匿名可理解为内存映射*/
union {
struct VmRegionFile {//文件映射
int f_oflags;
......@@ -121,38 +121,38 @@ struct VmMapRegion {//线性区描述符,内核通过线性区管理虚拟地址
const LosVmFileOps *vmFOps;///< 文件处理各操作接口
} rf;
struct VmRegionAnon {//匿名映射可理解为就是物理内存
LOS_DL_LIST node; /**< region LosVmPage list \n 线性区虚拟页链表*/
LOS_DL_LIST node; /**< region LosVmPage list | 线性区虚拟页链表*/
} ra;
struct VmRegionDev {//设备映射
LOS_DL_LIST node; /**< region LosVmPage list \n 线性区虚拟页链表*/
LOS_DL_LIST node; /**< region LosVmPage list | 线性区虚拟页链表*/
const LosVmFileOps *vmFOps; ///< 设备也是一种文件
} rd;
} unTypeData;
};
typedef struct VmSpace {
LOS_DL_LIST node; /**< vm space dl list \n 节点,通过它挂到全局虚拟空间 g_vmSpaceList 链表上*/
LosRbTree regionRbTree; /**< region red-black tree root \n 采用红黑树方式管理本空间各个线性区*/
LosMux regionMux; /**< region list mutex lock \n 虚拟空间的互斥锁*/
VADDR_T base; /**< vm space base addr \n 虚拟空间的基地址,常用于判断地址是否在内核还是用户空间*/
UINT32 size; /**< vm space size \n 虚拟空间大小*/
VADDR_T heapBase; /**< vm space heap base address \n 用户进程专用,堆区基地址,表堆区范围起点*/
VADDR_T heapNow; /**< vm space heap base now \n 用户进程专用,堆区结束地址,表堆区范围终点,do_brk()直接修改堆的大小返回新的堆区结束地址, heapNow >= heapBase*/
LosVmMapRegion *heap; /**< heap region \n 堆区是个特殊的线性区,用于满足进程的动态内存需求,大家熟知的malloc,realloc,free其实就是在操作这个区*/
VADDR_T mapBase; /**< vm space mapping area base \n 虚拟空间映射区基地址,L1,L2表存放在这个区 */
UINT32 mapSize; /**< vm space mapping area size \n 虚拟空间映射区大小,映射区是个很大的区。*/
LosArchMmu archMmu; /**< vm mapping physical memory \n MMU记录<虚拟地址,物理地址>的映射情况 */
LOS_DL_LIST node; /**< vm space dl list | 节点,通过它挂到全局虚拟空间 g_vmSpaceList 链表上*/
LosRbTree regionRbTree; /**< region red-black tree root | 采用红黑树方式管理本空间各个线性区*/
LosMux regionMux; /**< region list mutex lock | 虚拟空间的互斥锁*/
VADDR_T base; /**< vm space base addr | 虚拟空间的基地址,常用于判断地址是否在内核还是用户空间*/
UINT32 size; /**< vm space size | 虚拟空间大小*/
VADDR_T heapBase; /**< vm space heap base address | 用户进程专用,堆区基地址,表堆区范围起点*/
VADDR_T heapNow; /**< vm space heap base now | 用户进程专用,堆区结束地址,表堆区范围终点,do_brk()直接修改堆的大小返回新的堆区结束地址, heapNow >= heapBase*/
LosVmMapRegion *heap; /**< heap region | 堆区是个特殊的线性区,用于满足进程的动态内存需求,大家熟知的malloc,realloc,free其实就是在操作这个区*/
VADDR_T mapBase; /**< vm space mapping area base | 虚拟空间映射区基地址,L1,L2表存放在这个区 */
UINT32 mapSize; /**< vm space mapping area size | 虚拟空间映射区大小,映射区是个很大的区。*/
LosArchMmu archMmu; /**< vm mapping physical memory | MMU记录<虚拟地址,物理地址>的映射情况 */
#ifdef LOSCFG_DRIVERS_TZDRIVER
VADDR_T codeStart; /**< user process code area start */
VADDR_T codeEnd; /**< user process code area end */
VADDR_T codeStart; /**< user process code area start | 用户进程代码区开始位置 */
VADDR_T codeEnd; /**< user process code area end | 用户进程代码区结束位置 */
#endif
} LosVmSpace;
#define VM_MAP_REGION_TYPE_NONE (0x0)///< 初始化使用
#define VM_MAP_REGION_TYPE_ANON (0x1)///< 匿名映射线性区
#define VM_MAP_REGION_TYPE_FILE (0x2)///< 文件映射线性区
#define VM_MAP_REGION_TYPE_DEV (0x4)///< 设备映射线性区
#define VM_MAP_REGION_TYPE_MASK (0x7)///< 映射线性区掩码
#define VM_MAP_REGION_TYPE_NONE (0x0) ///< 初始化使用
#define VM_MAP_REGION_TYPE_ANON (0x1) ///< 匿名映射线性区
#define VM_MAP_REGION_TYPE_FILE (0x2) ///< 文件映射线性区
#define VM_MAP_REGION_TYPE_DEV (0x4) ///< 设备映射线性区
#define VM_MAP_REGION_TYPE_MASK (0x7) ///< 映射线性区掩码
/* the high 8 bits(24~31) should reserved, shm will use it */
#define VM_MAP_REGION_FLAG_CACHED (0<<0) ///< 缓冲区
......@@ -180,7 +180,7 @@ typedef struct VmSpace {
#define VM_MAP_REGION_FLAG_FIXED (1<<17)
#define VM_MAP_REGION_FLAG_FIXED_NOREPLACE (1<<18)
#define VM_MAP_REGION_FLAG_INVALID (1<<19) /* indicates that flags are not specified */
//从外部权限标签转化为线性区权限标签
/// 从外部权限标签转化为线性区权限标签
STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
{
UINT32 regionFlags = 0;
......@@ -202,69 +202,69 @@ STATIC INLINE BOOL LOS_IsKernelAddress(VADDR_T vaddr)
return ((vaddr >= (VADDR_T)KERNEL_ASPACE_BASE) &&
(vaddr <= ((VADDR_T)KERNEL_ASPACE_BASE + ((VADDR_T)KERNEL_ASPACE_SIZE - 1))));
}
///给定范围是否在内核空间中
/// 给定范围是否在内核空间中
STATIC INLINE BOOL LOS_IsKernelAddressRange(VADDR_T vaddr, size_t len)
{
return (vaddr + len > vaddr) && LOS_IsKernelAddress(vaddr) && (LOS_IsKernelAddress(vaddr + len - 1));
}
///获取区的结束地址
/// 获取区的结束地址
STATIC INLINE VADDR_T LOS_RegionEndAddr(LosVmMapRegion *region)
{
return (region->range.base + region->range.size - 1);
}
///线性区大小
/// 线性区大小
STATIC INLINE size_t LOS_RegionSize(VADDR_T start, VADDR_T end)
{
return (end - start + 1);
}
///是否为文件映射区
/// 是否为文件映射区
STATIC INLINE BOOL LOS_IsRegionTypeFile(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_FILE;
}
///permanent 用户进程常量区
/// permanent 用户进程常量区
STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region)
{
return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
(VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
}
///是否为私有线性区
/// 是否为私有线性区
STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region)
{
return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
}
///设置线性区为文件映射
/// 设置线性区为文件映射
STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_FILE;
}
///是否为设备映射线性区 /dev/...
/// 是否为设备映射线性区 /dev/...
STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_DEV;
}
///设为设备映射线性区
/// 设为设备映射线性区
STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_DEV;
}
///是否为匿名swap映射线性区
/// 是否为匿名swap映射线性区
STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_ANON;
}
///设为匿名swap映射线性区
/// 设为匿名swap映射线性区
STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_ANON;
}
///虚拟地址是否在用户空间
/// 虚拟地址是否在用户空间
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
{
return ((vaddr >= USER_ASPACE_BASE) &&
(vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
}
///虚拟地址[vaddr,vaddr + len]是否在用户空间
/// 虚拟地址[vaddr,vaddr + len]是否在用户空间
STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
{
return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
......@@ -276,7 +276,7 @@ STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr)
return ((vaddr >= VMALLOC_START) &&
(vaddr <= (VMALLOC_START + (VMALLOC_SIZE - 1))));
}
///是否为一个空线性区
/// 是否为一个空线性区
STATIC INLINE BOOL OsIsVmRegionEmpty(LosVmSpace *vmSpace)
{
if (vmSpace->regionRbTree.ulNodes == 0) {
......
......@@ -247,7 +247,7 @@ STATIC VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *
UINT32 msgDataSize;
UINT16 queuePosition;
/* get the queue position */ //先找到队列的位置
/* get the queue position | 先找到队列的位置*/
switch (OS_QUEUE_OPERATE_GET(operateType)) {//获取操作类型
case OS_QUEUE_READ_HEAD://从列队头开始读
queuePosition = queueCB->queueHead;//拿到头部位置
......@@ -307,11 +307,18 @@ STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueID
}
return LOS_OK;
}
/************************************************
队列操作.是读是写由operateType定
本函数是消息队列最重要的一个函数,可以分析出读取消息过程中
发生的细节,涉及任务的唤醒和阻塞,阻塞链表任务的相互提醒.
************************************************/
/**
* @brief 队列操作.是读是写由operateType定
本函数是消息队列最重要的一个函数,可以分析出读取消息过程中
发生的细节,涉及任务的唤醒和阻塞,阻塞链表任务的相互提醒.
* @param queueID
* @param operateType
* @param bufferAddr
* @param bufferSize
* @param timeout
* @return UINT32
*/
UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout)
{
LosQueueCB *queueCB = NULL;
......
......@@ -247,10 +247,10 @@ int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset)
}
SCHEDULER_LOCK(intSave);
spcb = OsCurrTaskGet();
/* If requested, copy the old mask to user. */ //如果需要,请将旧掩码复制给用户
/* If requested, copy the old mask to user. | 如果需要,请将旧掩码复制给用户*/
oldSigprocmask = spcb->sig.sigprocmask;
/* If requested, modify the current signal mask. */ //如有要求,修改当前信号屏蔽
/* If requested, modify the current signal mask. | 如有要求,修改当前信号屏蔽*/
if (setl != NULL) {
/* Okay, determine what we are supposed to do */
switch (how) {
......
......@@ -68,11 +68,18 @@ VOID ResetPageCacheHitInfo(int *try, int *hit)
#endif
#ifdef LOSCFG_KERNEL_VM
/**************************************************************************************************
增加文件页到页高速缓存(page cache)
LosFilePage将一个文件切成了一页一页,因为读文件过程随机seek,所以文件页也不会是连续的,
pgoff记录文件的位置,并确保在cache的文件数据是按顺序排列的.
**************************************************************************************************/
/**
* @brief
@verbatim
增加文件页到页高速缓存(page cache)
LosFilePage将一个文件切成了一页一页,因为读文件过程随机seek,所以文件页也不会是连续的,
pgoff记录文件的位置,并确保在cache的文件数据是按顺序排列的.
@endverbatim
* @param page
* @param mapping
* @param pgoff
* @return STATIC
*/
STATIC VOID OsPageCacheAdd(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
LosFilePage *fpage = NULL;
......@@ -371,10 +378,10 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
/**************************************************************************************************
/*!
文件缺页时的处理,先读入磁盘数据,再重新读页数据
被 OsDoReadFault(...),OsDoCowFault(...),OsDoSharedFault(...) 等调用
**************************************************************************************************/
*/
INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
{
INT32 ret;
......@@ -522,10 +529,10 @@ INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
return ENOERR;
}
/******************************************************************************
/*!
有名映射,可理解为文件映射,跟匿名映射相对应
参数filep是广义的文件,在鸿蒙内核,目录/普通文件/字符设备/块设备/网络套接字/管道/链接 都是文件
******************************************************************************/
*/
STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
{
struct Vnode *vnode = NULL;
......@@ -579,11 +586,11 @@ LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
}
/* need mutex & change memory to dma zone. */
/**************************************************************************************************
/*!
以页高速缓存方式分配一个文件页 LosFilePage
Direct Memory Access(存储器直接访问)指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。
整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU只需在数据传输开始和结束时做一点处理(开始和结束时候要做中断处理)
**************************************************************************************************/
*/
LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
VOID *kvaddr = NULL;
......
......@@ -130,10 +130,10 @@ ULONG_T OsRegionRbCmpKeyFn(const VOID *pNodeKeyA, const VOID *pNodeKeyB)
}
return RB_EQUAL;
}
/**************************************************************************
/*!
初始化虚拟空间,必须提供L1表的虚拟内存地址
VADDR_T *virtTtb:L1表的地址,TTB表地址
**************************************************************************/
*/
STATIC BOOL OsVmSpaceInitCommon(LosVmSpace *vmSpace, VADDR_T *virtTtb)
{
LOS_RbInitTree(&vmSpace->regionRbTree, OsRegionRbCmpKeyFn, OsRegionRbFreeFn, OsRegionRbGetKeyFn);//初始化虚拟存储空间-以红黑树组织方式
......@@ -503,10 +503,10 @@ PADDR_T LOS_PaddrQuery(VOID *vaddr)
}
}
/**************************************************************************************************
/*!
* 这里不是真的分配物理内存,而是逻辑上画一个连续的区域,标记这个区域可以拿用,表示内存已经归你了。
但真正的物理内存的占用会延迟到使用的时候才由缺页中断调入内存
**************************************************************************************************/
*/
LosVmMapRegion *LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff)
{
VADDR_T rstVaddr;
......@@ -547,10 +547,10 @@ OUT:
(VOID)LOS_MuxRelease(&vmSpace->regionMux);//释放互斥锁
return newRegion;
}
/**************************************************************************************************
/*!
* 删除匿名页,匿名页就是内存映射页
* 1.解除映射关系 2.释放物理内存
**************************************************************************************************/
*/
STATIC VOID OsAnonPagesRemove(LosArchMmu *archMmu, VADDR_T vaddr, UINT32 count)
{
status_t status;
......@@ -619,7 +619,7 @@ STATIC VOID OsFilePagesRemove(LosVmSpace *space, LosVmMapRegion *region)
}
}
#endif
//释放线性区
////释放线性区
STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region)
{
if ((space == NULL) || (region == NULL)) {
......@@ -1130,7 +1130,7 @@ PADDR_T LOS_PaddrQuery(VOID *vaddr)
return (PADDR_T)VMM_TO_DMA_ADDR((VADDR_T)vaddr);
}
#endif
//内核空间内存分配
///内核空间内存分配
VOID *LOS_KernelMalloc(UINT32 size)
{
VOID *ptr = NULL;
......
......@@ -62,10 +62,10 @@ STATIC INLINE VOID OsVmPageOrderListInit(LosVmPage *page, size_t nPages)
(pa) += PAGE_SIZE; \
} while (0)
/******************************************************************************
/*!
完成对物理内存整体初始化,本函数一定运行在实模式下
1.申请大块内存g_vmPageArray存放LosVmPage,按4K一页划分物理内存存放在数组中.
******************************************************************************/
*/
VOID OsVmPageStartup(VOID)
{
struct VmPhysSeg *seg = NULL;
......
......@@ -243,14 +243,19 @@ VOID *OsShrinkHeap(VOID *addr, LosVmSpace *space)
return addr;
}
/******************************************************************
用户进程向内核申请空间,进一步说用于扩展用户堆栈空间,或者回收用户堆栈空间
扩展当前进程的堆空间
一个进程所有的线性区都在进程指定的线性地址范围内,
线性区之间是不会有地址的重叠的,开始都是连续的,随着进程的运行出现了释放再分配的情况
由此出现了断断续续的线性区,内核回收线性区时会检测是否和周边的线性区可合并成一个更大
的线性区用于分配。
******************************************************************/
/**
* @brief
@verbatim
用户进程向内核申请空间,进一步说用于扩展用户堆栈空间,或者回收用户堆栈空间
扩展当前进程的堆空间
一个进程所有的线性区都在进程指定的线性地址范围内,
线性区之间是不会有地址的重叠的,开始都是连续的,随着进程的运行出现了释放再分配的情况
由此出现了断断续续的线性区,内核回收线性区时会检测是否和周边的线性区可合并成一个更大
的线性区用于分配。
@endverbatim
* @param addr
* @return VOID*
*/
VOID *LOS_DoBrk(VOID *addr)
{
LosVmSpace *space = OsCurrProcessGet()->vmSpace;
......
......@@ -224,11 +224,15 @@ STATIC VOID ShmPagesRefDec(struct shmIDSource *seg)
}
}
/******************************************************************************
为共享段分配物理内存
/**
* @brief 为共享段分配物理内存
例如:参数size = 4097, LOS_Align(size, PAGE_SIZE) = 8192
分配页数 size >> PAGE_SHIFT = 2页
******************************************************************************/
* @param key
* @param size
* @param shmflg
* @return STATIC
*/
STATIC INT32 ShmAllocSeg(key_t key, size_t size, INT32 shmflg)
{
INT32 i;
......@@ -770,12 +774,14 @@ ERROR:
return -1;
}
/******************************************************************************
当对共享存储的操作已经结束时,则调用shmdt与该存储段分离
/**
* @brief 当对共享存储的操作已经结束时,则调用shmdt与该存储段分离
如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值减1
注意:这并不从系统中删除共享存储的标识符以及其相关的数据结构。共享存储的仍然存在,
* @attention 注意:这并不从系统中删除共享存储的标识符以及其相关的数据结构。共享存储的仍然存在,
直至某个进程带IPC_RMID命令的调用shmctl特地删除共享存储为止
******************************************************************************/
* @param shmaddr
* @return INT32
*/
INT32 ShmDt(const VOID *shmaddr)
{
LosVmSpace *space = OsCurrProcessGet()->vmSpace;//获取进程空间
......
......@@ -1006,7 +1006,7 @@ ERROUT:
return VFS_ERROR;
}
/* console device driver function structure */ //控制台设备驱动程序,对统一的vfs接口的实现
/*! console device driver function structure | 控制台设备驱动程序,对统一的vfs接口的实现 */
STATIC const struct file_operations_vfs g_consoleDevOps = {
.open = ConsoleOpen, /* open */
.close = ConsoleClose, /* close */
......@@ -1019,10 +1019,14 @@ STATIC const struct file_operations_vfs g_consoleDevOps = {
.poll = ConsolePoll,
#endif
};
/*
termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,
/**
* @brief termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,
通过设置termios类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。
*/
* @param consoleCB
* @param deviceName
* @return STATIC
*/
STATIC VOID OsConsoleTermiosInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
{
struct termios consoleTermios = {0};
......@@ -1081,8 +1085,8 @@ ERROUT:
/*
* Initialized console control platform so that when we operate /dev/console
* as if we are operating /dev/ttyS0 (uart0).
*///初始化控制台以此来控制平台,以便在操作/dev/console时,就好像我们在操作/dev/ttyS0(uart0)
* as if we are operating /dev/ttyS0 (uart0). | 初始化控制台以此来控制平台,以便在操作/dev/console时,就好像我们在操作/dev/ttyS0(uart0)
*/
STATIC INT32 OsConsoleDevInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
{
INT32 ret;
......@@ -1153,13 +1157,13 @@ ERROUT:
set_errno(ret);
return LOS_NOK;
}
///控制台设备去初始化
/// 控制台设备去初始化
STATIC UINT32 OsConsoleDevDeinit(const CONSOLE_CB *consoleCB)
{
return unregister_driver(consoleCB->name);//注销驱动
}
//创建一个控制台循环buf
/// 创建一个控制台循环buf
STATIC CirBufSendCB *ConsoleCirBufCreate(VOID)
{
UINT32 ret;
......@@ -1194,7 +1198,7 @@ ERROR_WITH_SENDCB:
(VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);
return NULL;
}
///删除循环buf
/// 删除循环buf
STATIC VOID ConsoleCirBufDelete(CirBufSendCB *cirBufSendCB)
{
CirBuf *cirBufCB = &cirBufSendCB->cirBufCB;
......@@ -1204,7 +1208,7 @@ STATIC VOID ConsoleCirBufDelete(CirBufSendCB *cirBufSendCB)
(VOID)LOS_EventDestroy(&cirBufSendCB->sendEvent);//销毁事件
(VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);//释放循环buf发送控制块
}
///控制台缓存初始化,创建一个 发送任务
/// 控制台缓存初始化,创建一个 发送任务
STATIC UINT32 OsConsoleBufInit(CONSOLE_CB *consoleCB)
{
UINT32 ret;
......@@ -1237,7 +1241,7 @@ STATIC UINT32 OsConsoleBufInit(CONSOLE_CB *consoleCB)
return LOS_OK;
}
///控制台buf去初始化
/// 控制台buf去初始化
STATIC VOID OsConsoleBufDeinit(CONSOLE_CB *consoleCB)
{
CirBufSendCB *cirBufSendCB = consoleCB->cirBufSendCB;
......@@ -1245,7 +1249,7 @@ STATIC VOID OsConsoleBufDeinit(CONSOLE_CB *consoleCB)
consoleCB->cirBufSendCB = NULL;
(VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_EXIT);//写任务退出事件 ConsoleSendTask将会收到事件,退出死循环
}
///控制台描述符初始化
/// 控制台描述符初始化
STATIC CONSOLE_CB *OsConsoleCBInit(UINT32 consoleID)
{
CONSOLE_CB *consoleCB = (CONSOLE_CB *)LOS_MemAlloc((VOID *)m_aucSysMem0, sizeof(CONSOLE_CB));//内核空间分配控制台描述符
......@@ -1265,14 +1269,14 @@ STATIC CONSOLE_CB *OsConsoleCBInit(UINT32 consoleID)
}
return consoleCB;
}
///释放控制台描述符初始化时所占用的内核空间
/// 释放控制台描述符初始化时所占用的内核空间
STATIC VOID OsConsoleCBDeinit(CONSOLE_CB *consoleCB)
{
(VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB->name);//释放控制台名称占用的内核内存
consoleCB->name = NULL;
(VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB);//释放控制台描述符所占用的内核内存
}
///创建一个控制台,这个函数的goto语句贼多
/// 创建一个控制台,这个函数的goto语句贼多
STATIC CONSOLE_CB *OsConsoleCreate(UINT32 consoleID, const CHAR *deviceName)
{
INT32 ret;
......@@ -1329,7 +1333,7 @@ ERR_WITH_NAME:
OsConsoleCBDeinit(consoleCB);//控制块取消初始化
return NULL;
}
///删除控制台
/// 删除控制台
STATIC UINT32 OsConsoleDelete(CONSOLE_CB *consoleCB)
{
UINT32 ret;
......
......@@ -51,14 +51,14 @@ extern "C" {
#ifdef LOSCFG_FS_VFS
/* Define two fixed console id for Console ID. */ //两种固定的控制台id
#define CONSOLE_SERIAL 1 //串行方式
#define CONSOLE_TELNET 2 //远程登录
/* Define two fixed console id for Console ID. | 两种固定的控制台id */
#define CONSOLE_SERIAL 1 ///< 串行方式
#define CONSOLE_TELNET 2 ///< 远程登录
//POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代表 0、1、2
#define LOSCFG_PLATFORM_CONSOLE
#define STDIN 0 //标准输入
#define STDOUT 1 //标准输出
#define STDERR 2 //错误
#define STDIN 0 ///< 标准输入
#define STDOUT 1 ///< 标准输出
#define STDERR 2 ///< 错误
/**********************************************************
https://www.cnblogs.com/sparkdev/p/11460821.html
......@@ -74,45 +74,52 @@ TTY 是 Teletype 或 Teletypewriter 的缩写,字符设备的通称,原来是
#define CONSOLE_NAMELEN 16
#define CONSOLE_RD_BLOCK 1
#define CONSOLE_RD_NONBLOCK 0
#define CONSOLE_SHELL_KEY_EVENT 0x112 //shell 键盘事件
#define CONSOLE_SHELL_EXITED 0x400 //shell 退出事件
#define CONSOLE_FIFO_SIZE 0x400 //1K
#define CONSOLE_SHELL_KEY_EVENT 0x112 ///< shell 键盘事件
#define CONSOLE_SHELL_EXITED 0x400 ///< shell 退出事件
#define CONSOLE_FIFO_SIZE 0x400 ///< 1K
#define CONSOLE_NUM 2
#define CONSOLE_CIRCBUF_SIZE 0x400 //大小 1K
#define CONSOLE_CIRCBUF_SIZE 0x400 ///< 大小 1K
typedef struct {//发送环形buf控制块,通过事件发送
CirBuf cirBufCB; /* Circular buffer CB */ //循环缓冲控制块
EVENT_CB_S sendEvent; /* Inform telnet send task */ //通知telnet发送任务事件
/**
* @brief 发送环形buf控制块,通过事件发送
*/
typedef struct {
CirBuf cirBufCB; /* Circular buffer CB | 循环缓冲控制块 */
EVENT_CB_S sendEvent; /* Inform telnet send task | 通知telnet发送任务事件*/
} CirBufSendCB;
//控制台控制块(描述符)
/**
* @brief 控制台控制块(描述符)
*/
typedef struct {
UINT32 consoleID; //控制台ID
UINT32 consoleType; //控制台类型
UINT32 consoleSem; //控制台信号量
UINT32 consoleMask; //控制台掩码
struct Vnode *devVnode; //索引节点
CHAR *name; //名称
INT32 fd; //系统文件句柄
UINT32 refCount; //引用次数
UINT32 shellEntryId;//shell 入口ID,一般为任务ID
INT32 pgrpId; //进程组ID
BOOL isNonBlock;//是否无锁方式
UINT32 consoleID; ///< 控制台ID
UINT32 consoleType; ///< 控制台类型
UINT32 consoleSem; ///< 控制台信号量
UINT32 consoleMask; ///< 控制台掩码
struct Vnode *devVnode; ///< 索引节点
CHAR *name; ///< 名称
INT32 fd; ///< 系统文件句柄
UINT32 refCount; ///< 引用次数
UINT32 shellEntryId; ///< shell 入口ID,一般为任务ID
INT32 pgrpId; ///< 进程组ID
BOOL isNonBlock; ///< 是否无锁方式
#ifdef LOSCFG_SHELL
VOID *shellHandle; //shell句柄,本质是 shell控制块 ShellCB
VOID *shellHandle; ///< shell句柄,本质是 shell控制块 ShellCB
#endif
UINT32 sendTaskID; //发送任务ID
UINT32 sendTaskID; ///< 发送任务ID
/*--以下为 一家子 start---------*/
CirBufSendCB *cirBufSendCB; //循环缓冲发送控制块
UINT8 fifo[CONSOLE_FIFO_SIZE]; //控制台缓冲区大小 1K
UINT32 fifoOut; //对fifo的标记,输出位置
UINT32 fifoIn; //对fifo的标记,输入位置
UINT32 currentLen; //当前fifo位置
/*---以上为 一家子 end-------*///https://man7.org/linux/man-pages/man3/tcflow.3.html
struct termios consoleTermios; //termios 函数描述了一个通用的终端接口用于控制异步通信端口
CirBufSendCB *cirBufSendCB; ///< 循环缓冲发送控制块
UINT8 fifo[CONSOLE_FIFO_SIZE]; ///< 控制台缓冲区大小 1K
UINT32 fifoOut; ///< 对fifo的标记,输出位置
UINT32 fifoIn; ///< 对fifo的标记,输入位置
UINT32 currentLen; ///< 当前fifo位置
/*---以上为 一家子 end------- https://man7.org/linux/man-pages/man3/tcflow.3.html */
struct termios consoleTermios; ///< vtermios 函数描述了一个通用的终端接口用于控制异步通信端口
} CONSOLE_CB;
/*
termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,通过设置termios类型的数据结构中的值和使用一小组函数调用,
/**
* @brief termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,通过设置termios类型的数据结构中的值和使用一小组函数调用,
你就可以对终端接口进行控制。可以被调整来影响终端的值按照不同的模式被分为如下几组:
1.输入模式
2.输出模式
......@@ -120,7 +127,8 @@ termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中
4.本地模式
5.特殊控制模式
https://blog.csdn.net/wumenglu1018/article/details/53098794
*/
*/
extern INT32 system_console_init(const CHAR *deviceName);
extern INT32 system_console_deinit(const CHAR *deviceName);
extern BOOL SetSerialNonBlock(const CONSOLE_CB *consoleCB);
......
......@@ -286,7 +286,7 @@ STATIC VOID SystemInit(VOID)
#else
extern VOID SystemInit(VOID);
#endif
//创建系统初始任务并申请调度
///创建系统初始任务并申请调度
STATIC UINT32 OsSystemInitTaskCreate(VOID)
{
UINT32 taskID;
......
......@@ -36,27 +36,33 @@
#include "los_vm_lock.h"
#include "los_vm_phys.h"
#include "los_process_pri.h"
/**************************************************************************************
基本概念:
VDSO(Virtual Dynamic Shared Object,虚拟动态共享库)相对于普通的动态共享库,区别在于
其so文件不保存在文件系统中,存在于系统镜像中,由内核在运行时确定并提供给应用程序,故称为虚拟动态共享库。
OpenHarmony系统通过VDSO机制实现上层用户态程序可以快速读取内核相关数据的一种通道方法,
可用于实现部分系统调用的加速,也可用于实现非系统敏感数据(硬件配置、软件配置)的快速读取。
运行机制:
VDSO其核心思想就是内核看护一段内存,并将这段内存映射(只读)进用户态应用程序的地址空间,
应用程序通过链接vdso.so后,将某些系统调用替换为直接读取这段已映射的内存从而避免系统调用达到加速的效果。
VDSO总体可分为数据页与代码页两部分:
数据页提供内核映射给用户进程的内核时数据;
代码页提供屏蔽系统调用的主要逻辑;
/**
* @file
* @brief
* @verbatim
基本概念:
VDSO(Virtual Dynamic Shared Object,虚拟动态共享库)相对于普通的动态共享库,区别在于
其so文件不保存在文件系统中,存在于系统镜像中,由内核在运行时确定并提供给应用程序,故称为虚拟动态共享库。
OpenHarmony系统通过VDSO机制实现上层用户态程序可以快速读取内核相关数据的一种通道方法,
可用于实现部分系统调用的加速,也可用于实现非系统敏感数据(硬件配置、软件配置)的快速读取。
@note_link http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-bundles-share.html
运行机制:
VDSO其核心思想就是内核看护一段内存,并将这段内存映射(只读)进用户态应用程序的地址空间,
应用程序通过链接vdso.so后,将某些系统调用替换为直接读取这段已映射的内存从而避免系统调用达到加速的效果。
VDSO总体可分为数据页与代码页两部分:
数据页提供内核映射给用户进程的内核时数据;
代码页提供屏蔽系统调用的主要逻辑;
参考:http://lishiwen4.github.io/linux/vdso-and-syscall
https://vvl.me/2019/06/linux-syscall-and-vsyscall-vdso-in-x86/
@note_link http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-bundles-share.html
参考:http://lishiwen4.github.io/linux/vdso-and-syscall
https://vvl.me/2019/06/linux-syscall-and-vsyscall-vdso-in-x86/
#cat /proc/self/maps
* @endverbatim
*/
#cat /proc/self/maps
**************************************************************************************/
LITE_VDSO_DATAPAGE VdsoDataPage g_vdsoDataPage __attribute__((__used__));//使用这个数据区
STATIC size_t g_vdsoSize;
......@@ -73,8 +79,8 @@ UINT32 OsVdsoInit(VOID)
}
LOS_MODULE_INIT(OsVdsoInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
//映射,这里先通过内核地址找到 vdso的物理地址,再将物理地址映射到进程的线性区.
//结论是每个进程都可以拥有自己的 vdso区,映射到同一个块物理地址.
/// 映射,这里先通过内核地址找到 vdso的物理地址,再将物理地址映射到进程的线性区.
/// 结论是每个进程都可以拥有自己的 vdso区,映射到同一个块物理地址.
STATIC INT32 OsVdsoMap(LosVmSpace *space, size_t len, PADDR_T paddr, VADDR_T vaddr, UINT32 flag)
{
STATUS_T ret;
......
......@@ -229,12 +229,12 @@ extern "C" {
* Software timer mode
*/
enum enSwTmrType {
LOS_SWTMR_MODE_ONCE, /**< One-off software timer */ //一次性的软件计时器
LOS_SWTMR_MODE_PERIOD, /**< Periodic software timer */ //周期性的软件计时器
LOS_SWTMR_MODE_NO_SELFDELETE, /**< One-off software timer, but not self-delete */ //一次性软件计时器,但不能自删除
LOS_SWTMR_MODE_OPP /**< After the one-off timer finishes timing, //一次性完成后启用周期性软件计时器,鸿蒙目前暂时不支持这种方式
LOS_SWTMR_MODE_ONCE, /**< One-off software timer | 一次性的软件计时器*/
LOS_SWTMR_MODE_PERIOD, /**< Periodic software timer | 周期性的软件计时器*/
LOS_SWTMR_MODE_NO_SELFDELETE, /**< One-off software timer, but not self-delete | 一次性软件计时器,但不能自删除*/
LOS_SWTMR_MODE_OPP /**< After the one-off timer finishes timing,
the periodic software timer is enabled.
This mode is not supported temporarily. */
This mode is not supported temporarily. | 一次性完成后启用周期性软件计时器,鸿蒙目前暂时不支持这种方式*/
};
/**
......@@ -261,23 +261,24 @@ typedef VOID (*SWTMR_PROC_FUNC)(UINTPTR arg); //函数指针, 赋值给 SWTMR_CT
/**
* @ingroup los_swtmr
* Software timer control structure
* Software timer control structure | 软件定时器控制块
* \n 变量前缀 uc:UINT8 us:UINT16 uw:UINT32 代表的意思
*/
typedef struct tagSwTmrCtrl {//软件定时器控制块
SortLinkList stSortList;//通过它挂到对应CPU核定时器链表上
UINT8 ucState; /**< Software timer state */ //软件定时器的状态
UINT8 ucMode; /**< Software timer mode */ //软件定时器的模式
UINT16 usTimerID; /**< Software timer ID */ //软件定时器ID,唯一标识,由软件计时器池分配
typedef struct tagSwTmrCtrl {
SortLinkList stSortList; ///< 通过它挂到对应CPU核定时器链表上
UINT8 ucState; /**< Software timer state | 软件定时器的状态*/
UINT8 ucMode; /**< Software timer mode | 软件定时器的模式*/
UINT16 usTimerID; /**< Software timer ID | 软件定时器ID,唯一标识,由软件计时器池分配*/
UINT32 uwOverrun; /**< Times that a software timer repeats timing */
UINT32 uwCount; /**< Times that a software timer works */ //软件定时器工作的时间
UINT32 uwInterval; /**< Timeout interval of a periodic software timer */ //周期性软件定时器的超时间隔
UINT32 uwExpiry; /**< Timeout interval of an one-off software timer */ //一次性软件定时器的超时间隔
UINTPTR uwArg; /**< Parameter passed in when the callback function //回调函数的参数
that handles software timer timeout is called */
SWTMR_PROC_FUNC pfnHandler; /**< Callback function that handles software timer timeout */ //处理软件计时器超时的回调函数
UINT32 uwOwnerPid; /** Owner of this software timer */ //软件定时器所属进程ID号
UINT32 uwCount; /**< Times that a software timer works | 软件定时器工作的时间*/
UINT32 uwInterval; /**< Timeout interval of a periodic software timer | 周期性软件定时器的超时间隔*/
UINT32 uwExpiry; /**< Timeout interval of an one-off software timer | 一次性软件定时器的超时间隔*/
UINTPTR uwArg; /**< Parameter passed in when the callback function
that handles software timer timeout is called | 回调函数的参数*/
SWTMR_PROC_FUNC pfnHandler; /**< Callback function that handles software timer timeout | 处理软件计时器超时的回调函数*/
UINT32 uwOwnerPid; /**< Owner of this software timer | 软件定时器所属进程ID号*/
UINT64 startTime; /**< Software timer start time */
} SWTMR_CTRL_S;//变量前缀 uc:UINT8 us:UINT16 uw:UINT32 代表的意思
} SWTMR_CTRL_S;
/**
* @ingroup los_swtmr
......
......@@ -43,7 +43,7 @@ LITE_USER_SEC_RODATA STATIC CHAR *g_initPath = "/dev/shm/init";
#else
LITE_USER_SEC_RODATA STATIC CHAR *g_initPath = "/bin/init";//由Init_lite在编译后,生成
#endif
//将 sys_call3 链接在 section(".user.text")段
///将 sys_call3 链接在 section(".user.text")段
LITE_USER_SEC_TEXT STATIC UINT32 sys_call3(UINT32 nbr, UINT32 parm1, UINT32 parm2, UINT32 parm3)
{
register UINT32 reg7 __asm__("r7") = (UINT32)(nbr); //系统调用号给了R7寄存器
......
......@@ -96,13 +96,19 @@ void OsSyscallHandleInit(void)
LOS_MODULE_INIT(OsSyscallHandleInit, LOS_INIT_LEVEL_KMOD_EXTENDED);//注册系统调用模块
/* The SYSCALL ID is in R7 on entry. Parameters follow in R0..R6 */
/******************************************************************
由汇编调用,见于 los_hw_exc.s / BLX OsArmA32SyscallHandle
SYSCALL是产生系统调用时触发的信号,R7寄存器存放具体的系统调用ID,也叫系统调用号
regs:参数就是所有寄存器
注意:本函数在用户态和内核态下都可能被调用到
//MOV R0, SP @获取SP值,R0将作为OsArmA32SyscallHandle的参数
******************************************************************/
/**
* @brief
@verbatim
由汇编调用,见于 los_hw_exc.s / BLX OsArmA32SyscallHandle
SYSCALL是产生系统调用时触发的信号,R7寄存器存放具体的系统调用ID,也叫系统调用号
regs:参数就是所有寄存器
注意:本函数在用户态和内核态下都可能被调用到
//MOV R0, SP @获取SP值,R0将作为OsArmA32SyscallHandle的参数
@endverbatim
* @param regs
* @return VOID
*/
VOID OsArmA32SyscallHandle(TaskContext *regs)
{
UINT32 ret;
......
git add -A
git commit -m ' 修改注解方式,支持doxygen
git commit -m ' 注解支持doxygen格式,基本修改完成
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
博客输出站点(国内):http://weharmonyos.com
博客输出站点(国外):https://weharmony.github.io
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册