提交 3c36de58 编写于 作者: 鸿蒙内核源码分析'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
上级 52d0958c
......@@ -400,16 +400,23 @@ LITE_OS_SEC_TEXT_INIT VOID OsHwiInit(VOID)//硬件中断初始化
return;
}
/******************************************************************************
创建一个硬中断
中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,
handleIrq会调用该中断处理程序
******************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, //硬中断句柄编号 默认范围[0-127]
HWI_PRIOR_T hwiPrio, //硬中断优先级
HWI_MODE_T hwiMode, //硬中断模式 共享和非共享
HWI_PROC_FUNC hwiHandler,//硬中断处理函数
HwiIrqParam *irqParam) //硬中断处理函数参数
/**
* @brief 创建一个硬中断
\n 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,
\n handleIrq会调用该中断处理程序
* @param hwiNum 硬中断句柄编号 默认范围[0-127]
* @param hwiPrio 硬中断优先级
* @param hwiMode 硬中断模式 共享和非共享
* @param hwiHandler 硬中断处理函数
* @param irqParam 硬中断处理函数参数
* @return LITE_OS_SEC_TEXT_INIT
*/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum,
HWI_PRIOR_T hwiPrio,
HWI_MODE_T hwiMode,
HWI_PROC_FUNC hwiHandler,
HwiIrqParam *irqParam)
{
UINT32 ret;
......
......@@ -36,19 +36,22 @@
#include "los_mmu_descriptor_v6.h"
#undef ASSEMBLY
/******************************************************************************
CPU下异常向量表
指令名 功能描述
DMB 数据存储器隔离。DMB 指令保证: 仅当所有在它前面的存储器访问操作
都执行完毕后,才提交(commit)在它后面的存储器访问操作。
DSB 数据同步隔离。比 DMB 严格: 仅当所有在它前面的存储器访问操作
都执行完毕后,才执行在它后面的指令(亦即任何指令都要等待存储器访问操作)
ISB 指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执
行完毕之后,才执行它后面的指令。
******************************************************************************/
/*!
* @brief
* @verbatim
CPU下异常向量表
指令名 功能描述
DMB 数据存储器隔离。DMB 指令保证: 仅当所有在它前面的存储器访问操作
都执行完毕后,才提交(commit)在它后面的存储器访问操作。
DSB 数据同步隔离。比 DMB 严格: 仅当所有在它前面的存储器访问操作
都执行完毕后,才执行在它后面的指令(亦即任何指令都要等待存储器访问操作)
ISB 指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执
行完毕之后,才执行它后面的指令。
* @endverbatim
*/
.global __exc_stack_top @注意这个top并不是栈顶的意思,而是栈的地址高位,恰恰说的是栈底的位置
.global __svc_stack_top
.global __exc_stack
......
......@@ -31,26 +31,38 @@
#include "pthread.h"
/****************************************************************************
当 pthread_mutex_lock() 返回时,该互斥锁已被锁定。调用线程是该互斥锁的属主。
如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。
如果互斥锁类型为 PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。
如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。
如果互斥锁类型为 PTHREAD_MUTEX_ERRORCHECK,则会提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该线程锁定,
则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE,则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,
锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。 锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
如果互斥锁类型是 PTHREAD_MUTEX_DEFAULT,则尝试以递归方式锁定该互斥锁将产生不确定的行为。
对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,
则会产生不确定的行为。
参考链接: https://docs.oracle.com/cd/E19253-01/819-7051/sync-12/index.html
本文件是对鸿蒙轻内核互斥锁的封装
****************************************************************************/
int pthread_mutexattr_init(pthread_mutexattr_t *attr)//初始化互斥锁
/*!
* @file pthread_mutex.c
* @brief 对鸿蒙轻内核互斥锁的封装
* @verbatim
当 pthread_mutex_lock() 返回时,该互斥锁已被锁定。调用线程是该互斥锁的属主。
如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。
如果互斥锁类型为 PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。
如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。
如果互斥锁类型为 PTHREAD_MUTEX_ERRORCHECK,则会提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该线程锁定,
则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE,则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,
锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。
锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
如果互斥锁类型是 PTHREAD_MUTEX_DEFAULT,则尝试以递归方式锁定该互斥锁将产生不确定的行为。
对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,
则会产生不确定的行为。
参考链接: https://docs.oracle.com/cd/E19253-01/819-7051/sync-12/index.html
* @endverbatim
*/
/**
* @brief 初始化互斥锁属性
* @param attr
* @return int
*/
int pthread_mutexattr_init(pthread_mutexattr_t *attr)
{//如果互斥锁已初始化,则它会处于未锁定状态。互斥锁可以位于进程之间共享的内存中或者某个进程的专用内存中。
unsigned int ret = LOS_MuxAttrInit(attr);
if (ret != LOS_OK) {
......@@ -112,10 +124,15 @@ int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
{
return LOS_MuxAttrSetType(attr, type);
}
///初始化互斥锁
/* Initialize mutex. If mutexAttr is NULL, use default attributes. */
/**
* @brief 初始化互斥锁。 如果 mutexAttr 为 NULL,则使用默认属性。
* @param mutex
* @param mutexAttr
* @return int
*/
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
{//初始化互斥锁。 如果 mutexAttr 为 NULL,则使用默认属性。
{
unsigned int ret = LOS_MuxInit(mutex, mutexAttr);
if ((ret == LOS_OK) && (mutexAttr == NULL)) {
#if defined POSIX_MUTEX_DEFAULT_INHERIT
......
......@@ -37,10 +37,10 @@
#include "linux/spinlock.h"
#include "path_cache.h"
/*************************************************************************
https://www.howtogeek.com/193669/whats-the-difference-between-gpt-and-mbr-when-partitioning-a-drive/
https://www.html.cn/qa/other/20741.html
* GPT和MBR是做什么的?
/**
* @file disk.c
* @verbatim
GPT和MBR是做什么的?
在使用磁盘驱动器之前,必须对其进行分区。。MBR(主引导记录)和GPT(GUID分区表)是在驱动器上存储分区信息的两种不同方法。
这些信息包括分区在物理磁盘上的开始和结束位置,因此您的操作系统知道哪些扇区属于每个分区,哪些分区是可引导的。
这就是为什么在驱动器上创建分区之前必须选择MBR或GPT的原因。
......@@ -62,16 +62,21 @@ https://www.html.cn/qa/other/20741.html
或驱动器分区消失时才会看到问题。
GUID分区表自带备份。在磁盘的首尾部分分别保存了一份相同的分区表,因此当一份损坏可以通过另一份恢复。
而MBR磁盘分区表一旦被破坏就无法恢复,需要重新分区
*************************************************************************/
https://www.howtogeek.com/193669/whats-the-difference-between-gpt-and-mbr-when-partitioning-a-drive/
https://www.html.cn/qa/other/20741.html
* @endverbatim
* @brief
*/
//磁盘的最小单位就是扇区
los_disk g_sysDisk[SYS_MAX_DISK];//支持挂载的磁盘总数量 5个
los_part g_sysPart[SYS_MAX_PART];//支持磁盘的分区总数量 5*16,每个磁盘最大分16个区
los_disk g_sysDisk[SYS_MAX_DISK]; ///< 支持挂载的磁盘总数量 5个
los_part g_sysPart[SYS_MAX_PART]; ///< 支持磁盘的分区总数量 5*16,每个磁盘最大分16个区
UINT32 g_uwFatSectorsPerBlock = CONFIG_FS_FAT_SECTOR_PER_BLOCK;//每块支持扇区数 默认64个扇区
UINT32 g_uwFatBlockNums = CONFIG_FS_FAT_BLOCK_NUMS;//块数量 默认28
UINT32 g_uwFatSectorsPerBlock = CONFIG_FS_FAT_SECTOR_PER_BLOCK; ///< 每块支持扇区数 默认64个扇区
UINT32 g_uwFatBlockNums = CONFIG_FS_FAT_BLOCK_NUMS; ///< 块数量 默认28
spinlock_t g_diskSpinlock;//磁盘自锁锁
spinlock_t g_diskFatBlockSpinlock;//磁盘Fat块自旋锁
spinlock_t g_diskSpinlock; ///< 磁盘自锁锁
spinlock_t g_diskFatBlockSpinlock; ///< 磁盘Fat块自旋锁
UINT32 g_usbMode = 0;
......@@ -121,7 +126,7 @@ VOID SetFatSectorsPerBlock(UINT32 sectorsPerBlock)
}
}
#endif
//通过名称分配磁盘ID
///通过名称分配磁盘ID
INT32 los_alloc_diskid_byname(const CHAR *diskName)
{
INT32 diskID;
......
......@@ -32,49 +32,57 @@
#define __MTD_DEV_H__
#include "los_typedef.h"
/************************************************
MTD,Memory Technology Device即内存技术设备
Linux系统中采用MTD来管理不同类型的Flash芯片,包括NandFlash和NorFlash
NAND型和NOR型Flash在进行写入和擦除时都需要MTD(Memory Technology Drivers,MTD已集成在Flash芯片内部,
它是对Flash进行操作的接口),这是它们的共同特点;但在NOR型Flash上运行代码不需要任何的软件支持,
而在NAND型Flash上进行同样操作时,通常需要驱动程序,即内存技术驱动程序MTD。
NOR型Flash采用的SRAM接口,提供足够的地址引脚来寻址,可以很容易的存取其片内的每一个字节;
NAND型Flash使用复杂的I/O口来串行的存取数据,各个产品或厂商的方法可能各不相同,通常是采用8个I/O引脚
来传送控制、地址、数据信息。
/**
* @file mtd_dev.h
* @verbatim
MTD,Memory Technology Device即内存技术设备
Linux系统中采用MTD来管理不同类型的Flash芯片,包括NandFlash和NorFlash
NAND型和NOR型Flash在进行写入和擦除时都需要MTD(Memory Technology Drivers,MTD已集成在Flash芯片内部,
它是对Flash进行操作的接口),这是它们的共同特点;但在NOR型Flash上运行代码不需要任何的软件支持,
而在NAND型Flash上进行同样操作时,通常需要驱动程序,即内存技术驱动程序MTD。
NAND型Flash具有较高的单元密度,容量可以做得比较大,加之其生产过程更为简单,价格较低;NOR型Flash占据了容量
为1~16MB闪存市场的大部分,而NAND型Flash只是用在8~128MB的产品中,这也说明NOR主要用在代码存储介质中,
NAND适合数据存储。
************************************************/
NOR型Flash采用的SRAM接口,提供足够的地址引脚来寻址,可以很容易的存取其片内的每一个字节;
NAND型Flash使用复杂的I/O口来串行的存取数据,各个产品或厂商的方法可能各不相同,通常是采用8个I/O引脚
来传送控制、地址、数据信息。
#define MTD_NORFLASH 3 //存储空间一般比较小,但它可以不用初始化,可以在其内部运行程序,一般在其存储一些初始化内存的固件代码;
NAND型Flash具有较高的单元密度,容量可以做得比较大,加之其生产过程更为简单,价格较低;NOR型Flash占据了容量
为1~16MB闪存市场的大部分,而NAND型Flash只是用在8~128MB的产品中,这也说明NOR主要用在代码存储介质中,
NAND适合数据存储。
* @endverbatim
* @brief
*/
#define MTD_NORFLASH 3 ///< 存储空间一般比较小,但它可以不用初始化,可以在其内部运行程序,一般在其存储一些初始化内存的固件代码;
#define MTD_NANDFLASH 4
#define MTD_DATAFLASH 6
#define MTD_MLCNANDFLASH 8
/*********************************************
扇区是对硬盘而言,而块是对文件系统而言
文件系统不是一个扇区一个扇区的来读数据,一个扇区512个字节,太慢了,所以有了block(块)的概念,
文件系统是一个块一个块的读取的,block才是文件存取的最小单位。
*********************************************/
struct MtdNorDev {//一个block是4K,即:文件系统中1个块是由连续的8个扇区组成
unsigned long blockSize; //块大小,不用猜也知道,是4K,和内存的页等同,如此方便置换
unsigned long blockStart; //开始块索引
unsigned long blockEnd; //结束块索引
/**
* @brief
* @verbatim
扇区是对硬盘而言,而块是对文件系统而言
文件系统不是一个扇区一个扇区的来读数据,一个扇区512个字节,太慢了,所以有了block(块)的概念,
文件系统是一个块一个块的读取的,block才是文件存取的最小单位。
一个block是4K,即:文件系统中1个块是由连续的8个扇区组成
* @endverbatim
*/
struct MtdNorDev {
unsigned long blockSize; ///< 块大小,不用猜也知道,是4K,和内存的页等同,如此方便置换
unsigned long blockStart; ///< 开始块索引
unsigned long blockEnd; ///< 结束块索引
};
struct MtdDev {//flash MTD 层 描述符
/// flash MTD 层 描述符
struct MtdDev {
VOID *priv;
UINT32 type;
UINT64 size;
UINT32 eraseSize;//4K, 跟PAGE_CACHE_SIZE对应
//三个主要动作
int (*erase)(struct MtdDev *mtd, UINT64 start, UINT64 len, UINT64 *failAddr);//擦除flash操作
int (*read)(struct MtdDev *mtd, UINT64 start, UINT64 len, const char *buf);//读操作
int (*write)(struct MtdDev *mtd, UINT64 start, UINT64 len, const char *buf);//写操作
UINT32 eraseSize; ///< 4K, 跟PAGE_CACHE_SIZE对应
int (*erase)(struct MtdDev *mtd, UINT64 start, UINT64 len, UINT64 *failAddr);///< 擦除flash操作
int (*read)(struct MtdDev *mtd, UINT64 start, UINT64 len, const char *buf); ///< 读操作
int (*write)(struct MtdDev *mtd, UINT64 start, UINT64 len, const char *buf); ///< 写操作
};
......
......@@ -36,63 +36,68 @@
#include <sys/select.h>
#include <semaphore.h>
#include "linux/spinlock.h"
/****************************************************************************
fd:文件描述符(file descriptor)也叫文件句柄.
为了高效管理已被打开的文件所创建的索引,是一个非负整数,本质上一个凭证.凭证上岗.
fd只是个索引, 顺藤摸瓜, fd -> file -> vnode -> 块/字符驱动程序
当应用程序请求内核打开/新建一个文件时,内核会返回一个文件描述符用于对应这个打开/新建的文件,
读写文件也是需要使用这个文件描述符来指定待读写的文件的。
鸿蒙和LINUX一样,一切皆为文件,系统中,所有的文件操作,都是通过fd来定位资源和状态的
fd有两个好处, 1.安全,对用户透明,不需要知道具体怎么实现的,凭编号拿结果 2.方便扩展
-----------------------------------------------------------------------------
int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
见于..\third_party\musl\src\select\select.c
https://blog.csdn.net/starflame/article/details/7860091
理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。
则1字节长的fd_set最大可以对应8个fd。
typedef struct fd_set
{
unsigned char fd_bits [(FD_SETSIZE+7)/8];//用一位来表示一个FD
} fd_set;
fd_set:
select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄
(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,
由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。
process fd 和 system fd 的区别和联系
process fd(进程FD):每个进程都有一个属于自己的files_struct
system fd(系统FD):整个系统共用的fd表
二者的关系描述为:files_struct->ft_fds[进程FD].sysFd = 系统FD ;
****************************************************************************/
/**
* @file fb_table.h
* @verbatim
fd:文件描述符(file descriptor)也叫文件句柄.
为了高效管理已被打开的文件所创建的索引,是一个非负整数,本质上一个凭证.凭证上岗.
fd只是个索引, 顺藤摸瓜, fd -> file -> vnode -> 块/字符驱动程序
当应用程序请求内核打开/新建一个文件时,内核会返回一个文件描述符用于对应这个打开/新建的文件,
读写文件也是需要使用这个文件描述符来指定待读写的文件的。
鸿蒙和LINUX一样,一切皆为文件,系统中,所有的文件操作,都是通过fd来定位资源和状态的
fd有两个好处, 1.安全,对用户透明,不需要知道具体怎么实现的,凭编号拿结果 2.方便扩展
-----------------------------------------------------------------------------
int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
见于..\third_party\musl\src\select\select.c
https://blog.csdn.net/starflame/article/details/7860091
理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。
则1字节长的fd_set最大可以对应8个fd。
typedef struct fd_set
{
unsigned char fd_bits [(FD_SETSIZE+7)/8];//用一位来表示一个FD
} fd_set;
fd_set:
select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄
(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,
由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。
process fd 和 system fd 的区别和联系
process fd(进程FD):每个进程都有一个属于自己的files_struct
system fd(系统FD):整个系统共用的fd表
二者的关系描述为:files_struct->ft_fds[进程FD].sysFd = 系统FD ;
* @endverbatim
* @brief
*/
/* open file table for process fd */
struct file_table_s {//进程fd <--> 系统FD绑定
/// 进程fd <--> 系统FD绑定 sysFd的默认值是-1
struct file_table_s {
intptr_t sysFd; /* system fd associate with the tg_filelist index */
};//sysFd的默认值是-1
struct fd_table_s {//进程fd表结构体
unsigned int max_fds;//进程的文件描述符最多有256个
struct file_table_s *ft_fds; /* process fd array associate with system fd *///系统分配给进程的FD数组 ,fd 默认是 -1
fd_set *proc_fds; //进程fd管理位,用bitmap管理FD使用情况,默认打开了 0,1,2 (stdin,stdout,stderr)
};
/// 进程fd表结构体
struct fd_table_s {
unsigned int max_fds;///< 进程的文件描述符最多有256个
struct file_table_s *ft_fds; /* process fd array associate with system fd | 系统分配给进程的FD数组 ,fd 默认是 -1*/
fd_set *proc_fds; ///< 进程fd管理位,用bitmap管理FD使用情况,默认打开了 0,1,2 (stdin,stdout,stderr)
fd_set *cloexec_fds;
sem_t ft_sem; /* manage access to the file table */ //管理对文件表的访问的信号量
sem_t ft_sem; /* manage access to the file table | 管理对文件表的访问的信号量*/
};
//注:系统描述符的使用情况也是用bitmap管理见于 ..\third_party\third_party_NuttX\fs\inode\fs_files.c
//files_struct 为 进程 process->files 字段,包含一个进程的所有和VFS相关的内容
struct files_struct {//进程文件表结构体
int count; //持有的文件数量
struct fd_table_s *fdt; //持有的文件表
unsigned int file_lock; //文件互斥锁
unsigned int next_fd; //下一个fd
/// 注:系统描述符的使用情况也是用bitmap管理见于 ..\third_party\third_party_NuttX\fs\inode\fs_files.c
/// 进程文件表结构体 files_struct 为 进程 process->files 字段,包含一个进程的所有和VFS相关的内容
struct files_struct {
int count; ///< 持有的文件数量
struct fd_table_s *fdt; ///< 持有的文件表
unsigned int file_lock; ///< 文件互斥锁
unsigned int next_fd; ///< 下一个fd
#ifdef VFS_USING_WORKDIR
spinlock_t workdir_lock; //工作区目录自旋锁
char workdir[PATH_MAX]; //工作区路径,最大 256个字符
spinlock_t workdir_lock; ///< 工作区目录自旋锁
char workdir[PATH_MAX]; ///< 工作区路径,最大 256个字符
#endif
};
......@@ -102,17 +107,17 @@ typedef struct ProcessCB LosProcessCB;
void files_refer(int fd);
int files_close_internal(int fd, LosProcessCB *processCB);
//复制FD
///复制FD
struct files_struct *dup_fd(struct files_struct *oldf);
//为进程分配文件管理器,其中包含fd总数,(0,1,2)默认给了stdin,stdout,stderr
///为进程分配文件管理器,其中包含fd总数,(0,1,2)默认给了stdin,stdout,stderr
struct files_struct *alloc_files(void);
//删除参数进程的文件管理器
///删除参数进程的文件管理器
void delete_files(struct files_struct *files);
//创建文件管理器快照,所谓快照就是一份拷贝
///创建文件管理器快照,所谓快照就是一份拷贝
struct files_struct *create_files_snapshot(const struct files_struct *oldf);
//删除文件管理器快照
///删除文件管理器快照
void delete_files_snapshot(struct files_struct *files);
//分配一个系统fd,从全局tg_filelist中拿sysFd
///分配一个系统fd,从全局tg_filelist中拿sysFd
int alloc_fd(int minfd);
void alloc_std_fd(struct fd_table_s *fdt);
......
......@@ -48,33 +48,37 @@
#include "proc_fs.h"
#define WRITEPROC_ARGC 3
/*****************************************************************
鸿蒙内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。
proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为
访问系统内核数据的操作提供接口。
用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,
如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出
所需信息并提交的。
proc fs支持传入字符串参数,需要每个文件实现自己的写方法。
命令格式
writeproc <data> >> /proc/<filename>
/**
* @file fb_table.h
* @verbatim
鸿蒙内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。
proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为
访问系统内核数据的操作提供接口。
用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,
如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出
所需信息并提交的。
参数说明
参数 参数说明
data 要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。
filename data要传入的proc文件。
proc fs支持传入字符串参数,需要每个文件实现自己的写方法。
命令格式
writeproc <data> >> /proc/<filename>
proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。
注意:procfs暂不支持多线程访问
OHOS # writeproc test >> /proc/uptime
参数说明
参数 参数说明
data 要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。
filename data要传入的proc文件。
[INFO]write buf is: test
test >> /proc/uptime
说明: uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。
proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。
注意:procfs暂不支持多线程访问
OHOS # writeproc test >> /proc/uptime
*****************************************************************/
[INFO]write buf is: test
test >> /proc/uptime
说明: uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。
* @endverbatim
* @brief
*/
int OsShellCmdWriteProc(int argc, char **argv)
{
int i;
......
......@@ -82,13 +82,16 @@ struct file //文件系统最重要的两个结构体之一,另一个是inode
#endif
/**************************************************************************************************
初始化文件映射模块,
file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全局g_file_mapping链表上
page_mapping: 记录的是<文件,文件页>的关系,一个文件在操作过程中被映射成了多少个页,
file:是文件系统管理层面的概念
**************************************************************************************************/
/*!
* @brief
* @verbatim
初始化文件映射模块,
file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全局g_file_mapping链表上
page_mapping: 记录的是<文件,文件页>的关系,一个文件在操作过程中被映射成了多少个页,
file:是文件系统管理层面的概念
@endverbatim
* @return uint
*/
uint init_file_mapping()
{
uint ret;
......
......@@ -341,6 +341,14 @@ STATIC STATUS_T OsDoFileFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault, U
第一种:由编程错误引起的异常
第二种:属于进程的地址空间范围但还尚未分配物理页框引起的异常
***************************************************************/
/**
* @brief
* @param vaddr
* @param flags
* @param frame
* @return STATUS_T
*/
STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
{
LosVmSpace *space = LOS_SpaceGet(vaddr);//获取虚拟地址所属空间
......
......@@ -49,32 +49,32 @@ extern "C" {
* @ingroup los_config
* int stack start addr
*/
extern CHAR __int_stack_start; // 运行系统函数栈的开始地址
extern CHAR __rodata_start; // ROM开始地址 只读
extern CHAR __rodata_end; // ROM结束地址
extern CHAR __bss_start; // bss开始地址 __attribute__((section(".__bss_start")));
extern CHAR __bss_end; // bss结束地址 __attribute__((section(".__bss_end")));
extern CHAR __text_start; // 代码区开始地址
extern CHAR __text_end; // 代码区结束地址
extern CHAR __ram_data_start; // RAM开始地址 可读可写
extern CHAR __ram_data_end; // RAM结束地址
extern UINT32 __heap_start; // 堆区开始地址
extern UINT32 __heap_end; // 堆区结束地址
extern CHAR __int_stack_start; ///< 运行系统函数栈的开始地址
extern CHAR __rodata_start; ///< ROM开始地址 只读
extern CHAR __rodata_end; ///< ROM结束地址
extern CHAR __bss_start; ///< bss开始地址 __attribute__((section(".__bss_start")));
extern CHAR __bss_end; ///< bss结束地址 __attribute__((section(".__bss_end")));
extern CHAR __text_start; ///< 代码区开始地址
extern CHAR __text_end; ///< 代码区结束地址
extern CHAR __ram_data_start; ///< RAM开始地址 可读可写
extern CHAR __ram_data_end; ///< RAM结束地址
extern UINT32 __heap_start; ///< 堆区开始地址
extern UINT32 __heap_end; ///< 堆区结束地址
/****************************** System clock module configuration ****************************/
/**
* @ingroup los_config
* System clock (unit: HZ)
*/
#ifndef OS_SYS_CLOCK //HZ:是每秒中的周期性变动重复次数的计量
#define OS_SYS_CLOCK (get_bus_clk()) //系统主时钟频率 例如:50000000 即50微秒
#ifndef OS_SYS_CLOCK ///< HZ:是每秒中的周期性变动重复次数的计量
#define OS_SYS_CLOCK (get_bus_clk()) ///< 系统主时钟频率 例如:50000000 即50微秒
#endif
/**
* @ingroup los_config
* time timer clock (unit: HZ)
*/
#ifndef OS_TIME_TIMER_CLOCK
#define OS_TIME_TIMER_CLOCK OS_SYS_CLOCK //定时器频率
#define OS_TIME_TIMER_CLOCK OS_SYS_CLOCK ///< 定时器频率
#endif
/**
......@@ -131,7 +131,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* External configuration item for timer tailoring
*/
#if defined(LOSCFG_BASE_CORE_TICK_HW_TIME) && (LOSCFG_BASE_CORE_TICK_HW_TIME == 0)
#undef LOSCFG_BASE_CORE_TICK_HW_TIME //定时器裁剪的外部配置项
#undef LOSCFG_BASE_CORE_TICK_HW_TIME ///< 定时器裁剪的外部配置项
#endif
/****************************** Hardware interrupt module configuration ******************************/
......@@ -139,7 +139,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* @ingroup los_config
* Configuration item for hardware interrupt tailoring
*/
#ifndef LOSCFG_PLATFORM_HWI //硬件中断裁剪配置项
#ifndef LOSCFG_PLATFORM_HWI ///< 硬件中断裁剪配置项
#define LOSCFG_PLATFORM_HWI
#endif
......@@ -148,7 +148,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* Maximum number of used hardware interrupts, including Tick timer interrupts.
*/
#ifndef LOSCFG_PLATFORM_HWI_LIMIT
#define LOSCFG_PLATFORM_HWI_LIMIT 96 //硬件中断最大数量
#define LOSCFG_PLATFORM_HWI_LIMIT 96 ///< 硬件中断最大数量
#endif
/**
......@@ -183,7 +183,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* @ingroup los_config
* Default task priority
*/
#ifndef LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO //内核任务默认优先级
#ifndef LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO ///< 内核任务默认优先级
#define LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO 10
#endif
......@@ -191,7 +191,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* @ingroup los_config
* Maximum supported number of tasks except the idle task rather than the number of usable tasks
*/
#ifndef LOSCFG_BASE_CORE_TSK_LIMIT //支持的最大任务数(空闲任务除外,而不是可用任务数)
#ifndef LOSCFG_BASE_CORE_TSK_LIMIT ///< 支持的最大任务数(空闲任务除外,而不是可用任务数)
#define LOSCFG_BASE_CORE_TSK_LIMIT 128
#endif
......@@ -199,7 +199,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* @ingroup los_config
* Maximum supported number of process rather than the number of usable processes.
*/
#ifndef LOSCFG_BASE_CORE_PROCESS_LIMIT //支持的最大进程数,而不是可用进程数
#ifndef LOSCFG_BASE_CORE_PROCESS_LIMIT ///< 支持的最大进程数,而不是可用进程数
#define LOSCFG_BASE_CORE_PROCESS_LIMIT 64
#endif
......@@ -211,8 +211,8 @@ extern UINT32 __heap_end; // 堆区结束地址
* @ingroup los_config
* Size of the idle task stack
*/
#ifndef LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE //空闲任务栈大小
#define LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE SIZE(0x800)// 2K
#ifndef LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE ///< 空闲任务栈大小
#define LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE SIZE(0x800) ///< 2K
#endif
/**
......
......@@ -116,10 +116,13 @@ STATIC VOID InitLevelCall(const CHAR *name, const UINT32 level, struct ModuleIni
PRINTK("%s initialization at level %u consumes %lluns on cpu %u.\n", name, level, totalTime, ArchCurrCpuid());
#endif
}
/*********************************************************
初始化调用日志打印,这个函数的功能主要是为了记录某个步骤的耗时.在一个函数前后各调用一次就知道函数的执行情况.
/**
* @brief 初始化调用日志打印,这个函数的功能主要是为了记录某个步骤的耗时.在一个函数前后各调用一次就知道函数的执行情况.
这为开机调试提供了很重要的日志依据.
**********************************************************/
* @param level
* @return VOID
*/
VOID OsInitCall(const UINT32 level)
{
if (level >= LOS_INIT_LEVEL_FINISH) {
......
......@@ -31,43 +31,45 @@
#include "los_cppsupport.h"
#include "los_printf.h"
/**
* @brief @file los_cppsupport.c
* @verbatim
基本概念
C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上
开发的一种面向对象的编程语言。
/******************************************************************************
基本概念
C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上
开发的一种面向对象的编程语言。
运作机制
STL(Standard Template Library)标准模板库,是一些“容器”的集合,也是算法和其他
一些组件的集合。其目的是标准化组件,使用标准化组件后可以不用重新开发,直接使用现成的组件。
运作机制
STL(Standard Template Library)标准模板库,是一些“容器”的集合,也是算法和其他
一些组件的集合。其目的是标准化组件,使用标准化组件后可以不用重新开发,直接使用现成的组件。
开发流程
通过make menuconfig使能C++支持。
使用C++特性之前,需要调用函数LOS_CppSystemInit,初始化C++构造函数。
C函数与C++函数混合调用。在C++中调用C程序的函数,代码需加入C++包含的宏:
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus * /
#endif /* __cplusplus * /
/* code * /
...
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus * /
#endif /* __cplusplus * /
******************************************************************************/
开发流程
通过make menuconfig使能C++支持。
使用C++特性之前,需要调用函数LOS_CppSystemInit,初始化C++构造函数。
C函数与C++函数混合调用。在C++中调用C程序的函数,代码需加入C++包含的宏:
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus * /
#endif /* __cplusplus * /
/* code * /
...
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus * /
#endif /* __cplusplus * /
* @endverbatim
*/
typedef VOID (*InitFunc)(VOID);
/******************************************************************************
使用C++特性的前置条件 初始化C++构造函数
第一个参数:init_array段的起始地址。
第二个参数:init_array段的结束地址。
第三个参数:标记调用C++特性时的场景。
LOSCFG_KERNEL_CPPSUPPORT C++特性的裁剪开关
******************************************************************************/
/**
* @brief 使用C++特性的前置条件 初始化C++构造函数
* @param initArrayStart init_array段的起始地址
* @param initArrayEnd init_array段的结束地址
* @param flag 标记调用C++特性时的场景
* @return LITE_OS_SEC_TEXT_MINOR
*/
LITE_OS_SEC_TEXT_MINOR INT32 LOS_CppSystemInit(UINTPTR initArrayStart, UINTPTR initArrayEnd, INT32 flag)
{
UINTPTR *start = (UINTPTR *)initArrayStart;
......
......@@ -43,39 +43,57 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************
什么是句柄?
/**
* @brief 什么是句柄?
从形象意义的理解,跟门的把柄一样,握住门柄就控制了整个大门.
句柄是给用户程序使用的一个数字凭证,能以小博大,通过柄
能牵动内核模块工作.
****************************************************/
#define LITEIPC_DRIVER "/dev/lite_ipc" //设备位置
*/
#define LITEIPC_DRIVER "/dev/lite_ipc" ///< 设备位置
#define LITEIPC_DRIVER_MODE 0644
#define MAX_SERVICE_NUM LOSCFG_BASE_CORE_TSK_LIMIT //最大服务数等于任务数 默认128
#define MAX_SERVICE_NUM LOSCFG_BASE_CORE_TSK_LIMIT ///< 最大服务数等于任务数 默认128
#define USE_TIMESTAMP YES
typedef enum { //句柄状态
HANDLE_NOT_USED, //未使用
HANDLE_REGISTING, //注册中
HANDLE_REGISTED //已注册
/**
* @enum HandleStatus
* @brief 句柄状态
*/
typedef enum {
HANDLE_NOT_USED, ///< 未使用
HANDLE_REGISTING, ///< 注册中
HANDLE_REGISTED ///< 已注册
} HandleStatus;
typedef struct {//句柄信息
HandleStatus status; //状态
UINT32 taskID; //任务ID,以任务标识句柄
UINTPTR maxMsgSize;//最大消息大小
/**
* @struct HandleStatus
* @brief 句柄信息
*/
typedef struct {
HandleStatus status; ///< 状态
UINT32 taskID; ///< 任务ID,以任务标识句柄
UINTPTR maxMsgSize; ///< 最大消息大小
} HandleInfo;
typedef struct {// ipc池
VOID *uvaddr; //虚拟地址,指向进程的LiteIPC线性区基地址
VOID *kvaddr; //注意这里指的是物理地址
UINT32 poolSize;//ipc池大小
/**
* @struct IpcPool
* @brief ipc池
*/
typedef struct {
VOID *uvaddr; ///< 虚拟地址,指向进程的LiteIPC线性区基地址
VOID *kvaddr; ///< 注意这里指的是物理地址
UINT32 poolSize; ///< ipc池大小
} IpcPool;
//见于进程结构体: LosProcessCB.ipcInfo
typedef struct {//进程IPC信息
IpcPool pool; //ipc池
UINT32 ipcTaskID; //
UINT32 access[LOSCFG_BASE_CORE_TSK_LIMIT]; //访问的任务数组
/**
* @struct ProcIpcInfo
* @brief 进程IPC信息,见于进程结构体: LosProcessCB.ipcInfo
*/
typedef struct {
IpcPool pool; ///< ipc池
UINT32 ipcTaskID; //ipc任务ID
UINT32 access[LOSCFG_BASE_CORE_TSK_LIMIT]; ///< 访问的任务数组
} ProcIpcInfo;
typedef enum {
......@@ -106,15 +124,18 @@ typedef struct {
ObjContent content;
} SpecialObj;
typedef enum { //消息的类型
MT_REQUEST, //请求
MT_REPLY, //回复
MT_FAILED_REPLY,//回复失败
MT_DEATH_NOTIFY,//通知死亡
/**
* @brief 消息的类型
*/
typedef enum {
MT_REQUEST, ///< 请求
MT_REPLY, ///< 回复
MT_FAILED_REPLY,///< 回复失败
MT_DEATH_NOTIFY,///< 通知死亡
MT_NUM
} MsgType;
/* lite ipc ioctl */// 控制命令
/* lite ipc ioctl | 控制命令*/
#define IPC_IOC_MAGIC 'i'
#define IPC_SET_CMS _IO(IPC_IOC_MAGIC, 1)
#define IPC_CMS_CMD _IOWR(IPC_IOC_MAGIC, 2, CmsCmdContent)
......@@ -139,22 +160,22 @@ typedef enum {
} IpcFlag;
typedef struct {
MsgType type; /**< cmd type, decide the data structure below*/ //命令类型,决定下面的数据结构
SvcIdentity target; /**< serviceHandle or targetTaskId, depending on type */ //因命令类型不同而异
UINT32 code; /**< service function code */ //服务功能代码
MsgType type; /**< cmd type, decide the data structure below | 命令类型,决定下面的数据结构*/
SvcIdentity target; /**< serviceHandle or targetTaskId, depending on type | 因命令类型不同而异*/
UINT32 code; /**< service function code | 服务功能代码*/
UINT32 flag; //标签
#if (USE_TIMESTAMP == YES)
UINT64 timestamp; //时间戳
#endif
UINT32 dataSz; /**< size of data */ //消息内容大小
VOID *data; //消息的内容,真正要传递的消息
UINT32 dataSz; /**< size of data | 消息内容大小*/
VOID *data; ///< 消息的内容,真正要传递的消息
UINT32 spObjNum; // ..
VOID *offsets; // ..
UINT32 processID; /**< filled by kernel, processId of sender/reciever */ //由内核填充,发送/接收消息的进程ID
UINT32 taskID; /**< filled by kernel, taskId of sender/reciever */ //由内核填充,发送/接收消息的任务ID
UINT32 processID; /**< filled by kernel, processId of sender/reciever | 由内核填充,发送/接收消息的进程ID*/
UINT32 taskID; /**< filled by kernel, taskId of sender/reciever | 由内核填充,发送/接收消息的任务ID*/
#ifdef LOSCFG_SECURITY_CAPABILITY
UINT32 userID; //用户ID
UINT32 gid; //组ID
UINT32 userID; ///< 用户ID
UINT32 gid; ///< 组ID
#endif
} IpcMsg;
......@@ -163,14 +184,17 @@ typedef struct { //IPC 内容节点
LOS_DL_LIST listNode;//通过它挂到LosTaskCB.msgListHead链表上
} IpcListNode;
#define SEND (1 << 0) //发送
#define RECV (1 << 1) //接收
#define BUFF_FREE (1 << 2) //空闲状态
#define SEND (1 << 0) ///< 发送
#define RECV (1 << 1) ///< 接收
#define BUFF_FREE (1 << 2) ///< 空闲状态
typedef struct { //IPC消息内容回路,记录消息周期
UINT32 flag; /**< size of writeData */ //IPC标签 (SEND,RECV,BUFF_FREE)
IpcMsg *outMsg; /**< data to send to target */ //发给给目标任务的消息内容
IpcMsg *inMsg; /**< data reply by target */ //目标任务回复的消息内容
/**
* @brief IPC消息内容回路,记录消息周期
*/
typedef struct {
UINT32 flag; /**< size of writeData | IPC标签 (SEND,RECV,BUFF_FREE)*/
IpcMsg *outMsg; /**< data to send to target | 发给给目标任务的消息内容*/
IpcMsg *inMsg; /**< data reply by target | 目标任务回复的消息内容*/
VOID *buffToFree;
} IpcContent;
......
......@@ -37,43 +37,46 @@
#include "los_spinlock.h"
#include "los_mp.h"
/*******************************************************************
// @note_link http://weharmonyos.com/openharmony/zh-cn/readme/%E7%94%B5%E6%BA%90%E7%AE%A1%E7%90%86%E5%AD%90%E7%B3%BB%E7%BB%9F.html
电源管理子系统提供如下功能:
重启系统。
管理休眠运行锁。
系统电源状态查询。
充电和电池状态查询和上报。
亮灭屏管理和亮度调节。
/base/powermgr
├── battery_manager # 电池服务组件
│ ├── hdi # HDI层
│ ├── interfaces # 接口层
│ ├── sa_profile # SA配置文件
│ ├── services # 服务层
│ └── utils # 工具和通用层
├── display_manager # 显示控制组件
│ ├── interfaces # 接口层
│ └── sa_profile # SA配置文件
│ └── services # 服务层
│ └── utils # 工具和通用层
├── powermgr_lite # 轻量级电源管理组件
│ ├── interfaces # 接口层
│ └── services # 服务层
└── power_manager # 电源管理服务组件
├── interfaces # 接口层
├── sa_profile # SA配置文件
└── services # 服务层
└── utils # 工具和通用层
开发者通过电源管理子系统提供的接口可以进行申请和释放休眠运行锁RunningLock、获取电池信息、亮度调节、重启设备、关机等操作。
电源管理子系统相关仓库
powermgr_battery_manager
powermgr_power_manager
powermgr_display_manager
*******************************************************************/
/**
* @brief 删除链:删除由装入点管理的文件
* @verbatim
@note_link http://weharmonyos.com/openharmony/zh-cn/readme/%E7%94%B5%E6%BA%90%E7%AE%A1%E7%90%86%E5%AD%90%E7%B3%BB%E7%BB%9F.html
电源管理子系统提供如下功能:
重启系统。
管理休眠运行锁。
系统电源状态查询。
充电和电池状态查询和上报。
亮灭屏管理和亮度调节。
/base/powermgr
├── battery_manager # 电池服务组件
│ ├── hdi # HDI层
│ ├── interfaces # 接口层
│ ├── sa_profile # SA配置文件
│ ├── services # 服务层
│ └── utils # 工具和通用层
├── display_manager # 显示控制组件
│ ├── interfaces # 接口层
│ └── sa_profile # SA配置文件
│ └── services # 服务层
│ └── utils # 工具和通用层
├── powermgr_lite # 轻量级电源管理组件
│ ├── interfaces # 接口层
│ └── services # 服务层
└── power_manager # 电源管理服务组件
├── interfaces # 接口层
├── sa_profile # SA配置文件
└── services # 服务层
└── utils # 工具和通用层
开发者通过电源管理子系统提供的接口可以进行申请和释放休眠运行锁RunningLock、获取电池信息、亮度调节、重启设备、关机等操作。
电源管理子系统相关仓库
powermgr_battery_manager
powermgr_power_manager
powermgr_display_manager
* @endverbatim
*/
#ifdef LOSCFG_KERNEL_PM
#define PM_INFO_SHOW(seqBuf, arg...) do { \
if (seqBuf != NULL) { \
......@@ -87,22 +90,22 @@ powermgr_display_manager
#define OS_PM_LOCK_NAME_MAX 28
typedef UINT32 (*Suspend)(VOID);
//电源锁控制块
///< 电源锁控制块
typedef struct {
CHAR name[OS_PM_LOCK_NAME_MAX];//电源锁名称
UINT32 count; //数量
LOS_DL_LIST list; //电源锁链表,上面挂的是 OsPmLockCB
CHAR name[OS_PM_LOCK_NAME_MAX]; ///< 电源锁名称
UINT32 count; ///< 数量
LOS_DL_LIST list; ///< 电源锁链表,上面挂的是 OsPmLockCB
} OsPmLockCB;
//电源管理控制块
///< 电源管理控制块
typedef struct {
LOS_SysSleepEnum mode; //模式类型
UINT16 lock; //锁数量
LOS_DL_LIST lockList; //电源锁链表头,上面挂的是 OsPmLockCB
LOS_SysSleepEnum mode; ///< 模式类型
UINT16 lock; ///< 锁数量
LOS_DL_LIST lockList; ///< 电源锁链表头,上面挂的是 OsPmLockCB
} LosPmCB;
STATIC LosPmCB g_pmCB;//电源控制块全局遍历
STATIC SPIN_LOCK_INIT(g_pmSpin);//电源模块自旋锁
//获取电源模式
STATIC LosPmCB g_pmCB; ///< 电源控制块全局遍历
STATIC SPIN_LOCK_INIT(g_pmSpin); ///< 电源模块自旋锁
/// 获取电源模式
LOS_SysSleepEnum LOS_PmModeGet(VOID)
{
LOS_SysSleepEnum mode;
......
......@@ -45,32 +45,36 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/******************************************************************************
调用API接口时可能会出现错误,此时接口会返回对应的错误码,以便快速定位错误原因。
错误码是一个32位的无符号整型数,31~24位表示错误等级,23~16位表示错误码标志(当前该标志值为0),
15~8位代表错误码所属模块,7~0位表示错误码序号。
错误码中的错误等级
错误等级 数值 含义
NORMAL 0 提示
WARN 1 告警
ERR 2 严重
FATAL 3 致命
例如
#define LOS_ERRNO_TSK_NO_MEMORY LOS_ERRNO_OS_FATAL(LOS_MOD_TSK, 0x00)
#define LOS_ERRNO_OS_FATAL(MID, ERRNO) \
(LOS_ERRTYPE_FATAL | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO)))
说明
LOS_ERRTYPE_FATAL:错误等级为FATAL,值为0x03000000 LOS_ERRNO_OS_ID:错误码标志,
值为0x000000 MID:所属模块,LOS_MOD_TSK的值为0x2 ERRNO:错误码序号
所以LOS_ERRNO_TSK_NO_MEMORY的值为0x03000200
错误码接管
有时只靠错误码不能快速准确的定位问题,为方便用户分析错误,错误处理模块支持
注册错误处理的钩子函数,发生错误时,用户可以调用LOS_ErrHandle接口以执行错误处理函数。
******************************************************************************/
/**
* @brief
* @verbatim
调用API接口时可能会出现错误,此时接口会返回对应的错误码,以便快速定位错误原因。
错误码是一个32位的无符号整型数,31~24位表示错误等级,23~16位表示错误码标志(当前该标志值为0),
15~8位代表错误码所属模块,7~0位表示错误码序号。
错误码中的错误等级
错误等级 数值 含义
NORMAL 0 提示
WARN 1 告警
ERR 2 严重
FATAL 3 致命
例如
#define LOS_ERRNO_TSK_NO_MEMORY LOS_ERRNO_OS_FATAL(LOS_MOD_TSK, 0x00)
#define LOS_ERRNO_OS_FATAL(MID, ERRNO) \
(LOS_ERRTYPE_FATAL | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO)))
说明
LOS_ERRTYPE_FATAL:错误等级为FATAL,值为0x03000000 LOS_ERRNO_OS_ID:错误码标志,
值为0x000000 MID:所属模块,LOS_MOD_TSK的值为0x2 ERRNO:错误码序号
所以LOS_ERRNO_TSK_NO_MEMORY的值为0x03000200
错误码接管
有时只靠错误码不能快速准确的定位问题,为方便用户分析错误,错误处理模块支持
注册错误处理的钩子函数,发生错误时,用户可以调用LOS_ErrHandle接口以执行错误处理函数。
* @endverbatim
*/
/**
* @ingroup los_errno
......
......@@ -44,46 +44,46 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @brief 删除链:删除由装入点管理的文件
* @verbatim
基本概念
双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,
还增加一个指向前一个节点的指针。其头指针head是唯一确定的。
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种
数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表
具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。
双向链表的典型开发流程:
调用LOS_ListInit/LOS_DL_LIST_HEAD初始双向链表。
调用LOS_ListAdd/LOS_ListHeadInsert向链表头部插入节点。
调用LOS_ListTailInsert向链表尾部插入节点。
调用LOS_ListDelete删除指定节点。
调用LOS_ListEmpty判断链表是否为空。
调用LOS_ListDelInit删除指定节点并以此节点初始化链表。
注意事项
需要注意节点指针前后方向的操作。
链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。
如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。
* @endverbatim
*/
/******************************************************************************
基本概念
双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,
还增加一个指向前一个节点的指针。其头指针head是唯一确定的。
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种
数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表
具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。
双向链表的典型开发流程:
调用LOS_ListInit/LOS_DL_LIST_HEAD初始双向链表。
调用LOS_ListAdd/LOS_ListHeadInsert向链表头部插入节点。
调用LOS_ListTailInsert向链表尾部插入节点。
调用LOS_ListDelete删除指定节点。
调用LOS_ListEmpty判断链表是否为空。
调用LOS_ListDelInit删除指定节点并以此节点初始化链表。
注意事项
需要注意节点指针前后方向的操作。
链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。
如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。
参考
https://gitee.com/LiteOS/LiteOS/blob/master/doc/Huawei_LiteOS_Kernel_Developer_Guide_zh.md#setup
******************************************************************************/
/**
* @ingroup los_list
* Structure of a node in a doubly linked list.
* Structure of a node in a doubly linked list. | 双向链表,内核最重要结构体
*/
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 *///后继节点(右手)
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;
/**
* @ingroup los_list
*
* @par Description:
* This API is used to initialize a doubly linked list.
* This API is used to initialize a doubly linked list. | 将指定节点初始化为双向链表节点
* @attention
* <ul>
* <li>The parameter passed in should be ensured to be a legal pointer.</li>
......@@ -95,7 +95,7 @@ typedef struct LOS_DL_LIST {//双向链表,内核最重要结构体
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //将指定节点初始化为双向链表节点
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
{
list->pstNext = list;
......@@ -108,7 +108,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
*
* @par Description:
* <ul>
* <li>This API is used to point to the next node pointed to by the current node.</li>
* <li>This API is used to point to the next node pointed to by the current node. | 获取指定节点的后继结点</li>
* </ul>
* @attention
* <ul>
......@@ -121,7 +121,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //获取指定节点的后继结点
*/
#define LOS_DL_LIST_FIRST(object) ((object)->pstNext)
/**
......@@ -174,7 +174,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
*
* @par Description:
* <ul>
* <li>This API is used to point to the previous node pointed to by the current node.</li>
* <li>This API is used to point to the previous node pointed to by the current node. | 获取指定节点的前驱结点</li>
* </ul>
* @attention
* <ul>
......@@ -187,7 +187,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //获取指定节点的前驱结点
*/
#define LOS_DL_LIST_LAST(object) ((object)->pstPrev)
/**
......@@ -195,7 +195,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @brief Insert a new node to a doubly linked list.
*
* @par Description:
* This API is used to insert a new node to a doubly linked list.
* This API is used to insert a new node to a doubly linked list. | 将指定节点插入到双向链表头端
* @attention
* <ul>
* <li>The parameters passed in should be ensured to be legal pointers.</li>
......@@ -208,7 +208,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see LOS_ListDelete
*/ //将指定节点插入到双向链表头端
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
{
node->pstNext = list->pstNext;
......@@ -222,7 +222,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_
* @brief Insert a node to the tail of a doubly linked list.
*
* @par Description:
* This API is used to insert a new node to the tail of a doubly linked list.
* This API is used to insert a new node to the tail of a doubly linked list. | 将指定节点插入到双向链表尾端
* @attention
* <ul>
* <li>The parameters passed in should be ensured to be legal pointers.</li>
......@@ -235,7 +235,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see LOS_ListAdd | LOS_ListHeadInsert
*/ //将指定节点插入到双向链表尾端
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
{
LOS_ListAdd(list->pstPrev, node);
......@@ -246,7 +246,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list,
* @brief Insert a node to the head of a doubly linked list.
*
* @par Description:
* This API is used to insert a new node to the head of a doubly linked list.
* This API is used to insert a new node to the head of a doubly linked list. | 将指定节点插入到双向链表头端
* @attention
* <ul>
* <li>The parameters passed in should be ensured to be legal pointers.</li>
......@@ -259,7 +259,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list,
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see LOS_ListAdd | LOS_ListTailInsert
*/ //将指定节点插入到双向链表头端
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
{
LOS_ListAdd(list, node);
......@@ -270,7 +270,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsert(LOS_DL_LIST *list,
*
* @par Description:
* <ul>
* <li>This API is used to delete a specified node from a doubly linked list.</li>
* <li>This API is used to delete a specified node from a doubly linked list. | 将指定节点从链表中删除</li>
* </ul>
* @attention
* <ul>
......@@ -283,7 +283,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsert(LOS_DL_LIST *list,
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see LOS_ListAdd
*/ //将指定节点从链表中删除
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
{
node->pstNext->pstPrev = node->pstPrev;
......@@ -294,7 +294,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
/**
* @ingroup los_list
* @brief Identify whether a specified doubly linked list is empty.
* @brief Identify whether a specified doubly linked list is empty. | 判断链表是否为空
*
* @par Description:
* <ul>
......@@ -312,7 +312,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //判断链表是否为空
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
{
return (BOOL)(list->pstNext == list);
......@@ -400,7 +400,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
/**
* @ingroup los_list
* @brief Obtain the offset of a field to a structure address.
* @brief Obtain the offset of a field to a structure address. | 获取指定结构体内的成员相对于结构体起始地址的偏移量
*
* @par Description:
* This API is used to obtain the offset of a field to a structure address.
......@@ -416,12 +416,12 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //获取指定结构体内的成员相对于结构体起始地址的偏移量
*/
#define LOS_OFF_SET_OF(type, member) ((UINTPTR)&((type *)0)->member)
/**
* @ingroup los_list
* @brief Obtain the pointer to a structure that contains a doubly linked list.
* @brief Obtain the pointer to a structure that contains a doubly linked list. | 获取包含链表的结构体地址,接口的第一个入参表示的是链表中的下一个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称
*
* @par Description:
* This API is used to obtain the pointer to a structure that contains a doubly linked list.
......@@ -441,13 +441,13 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //获取包含链表的结构体地址,接口的第一个入参表示的是链表中的下一个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称
*/
#define LOS_DL_LIST_ENTRY(item, type, member) \
((type *)(VOID *)((CHAR *)(item) - LOS_OFF_SET_OF(type, member)))
/**
* @ingroup los_list
* @brief Iterate over a doubly linked list of given type.
* @brief Iterate over a doubly linked list of given type. | 遍历指定双向链表,获取包含该链表节点的结构体地址
*
* @par Description:
* This API is used to iterate over a doubly linked list of given type.
......@@ -465,7 +465,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //遍历指定双向链表,获取包含该链表节点的结构体地址
*/
#define LOS_DL_LIST_FOR_EACH_ENTRY(item, list, type, member) \
for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member); \
&(item)->member != (list); \
......@@ -473,7 +473,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
/**
* @ingroup los_list
* @brief iterate over a doubly linked list safe against removal of list entry.
* @brief iterate over a doubly linked list safe against removal of list entry. | 遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址
*
* @par Description:
* This API is used to iterate over a doubly linked list safe against removal of list entry.
......@@ -492,7 +492,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址
*/
#define LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, next, list, type, member) \
for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member), \
next = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member); \
......@@ -501,7 +501,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
/**
* @ingroup los_list
* @brief Delete initialize a doubly linked list.
* @brief Delete initialize a doubly linked list. | 将指定节点从链表中删除,并使用该节点初始化链表
*
* @par Description:
* This API is used to delete initialize a doubly linked list.
......@@ -516,7 +516,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsertList(LOS_DL_LIST *ol
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //将指定节点从链表中删除,并使用该节点初始化链表
*/
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
{
list->pstNext->pstPrev = list->pstPrev;
......@@ -526,7 +526,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
/**
* @ingroup los_list
* @brief iterate over a doubly linked list.
* @brief iterate over a doubly linked list. | 遍历双向链表
*
* @par Description:
* This API is used to iterate over a doubly linked list.
......@@ -542,7 +542,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //遍历双向链表
*/
#define LOS_DL_LIST_FOR_EACH(item, list) \
for (item = (list)->pstNext; \
(item) != (list); \
......@@ -550,7 +550,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
/**
* @ingroup los_list
* @brief Iterate over a doubly linked list safe against removal of list entry.
* @brief Iterate over a doubly linked list safe against removal of list entry. | 遍历双向链表,并存储当前节点的后继节点用于安全校验
*
* @par Description:
* This API is used to iterate over a doubly linked list safe against removal of list entry.
......@@ -567,7 +567,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //遍历双向链表,并存储当前节点的后继节点用于安全校验
*/
#define LOS_DL_LIST_FOR_EACH_SAFE(item, next, list) \
for (item = (list)->pstNext, next = (item)->pstNext; \
(item) != (list); \
......@@ -575,7 +575,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
/**
* @ingroup los_list
* @brief Initialize a double linked list.
* @brief Initialize a double linked list. | 定义一个节点并初始化为双向链表节点
*
* @par Description:
* This API is used to initialize a double linked list.
......@@ -590,7 +590,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
* @par Dependency:
* <ul><li>los_list.h: the header file that contains the API declaration.</li></ul>
* @see
*/ //定义一个节点并初始化为双向链表节点
*/
#define LOS_DL_LIST_HEAD(list) LOS_DL_LIST list = { &(list), &(list) }
#define LOS_ListPeekHeadType(list, type, element) ({ \
......
......@@ -46,8 +46,10 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/******************************************************************************
/**
* @file los_sys.h
* @brief
@verbatim
基本概念
时间管理以系统时钟为基础,给应用程序提供所有和时间有关的服务。
......@@ -77,9 +79,10 @@ extern "C" {
时间管理不是单独的功能模块,依赖于OS_SYS_CLOCK和LOSCFG_BASE_CORE_TICK_PER_SECOND两个配置选项。
系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间使用。
参考
https://gitee.com/LiteOS/LiteOS/blob/master/doc/Huawei_LiteOS_Kernel_Developer_Guide_zh.md#setup
******************************************************************************/
@endverbatim
*/
/**
* @ingroup los_sys
* System time basic function error code: Null pointer.
......
......@@ -39,11 +39,14 @@
#include <los_sem.h>
#include <los_mux.h>
#include <los_spinlock.h>
/**
* @brief
* @verbatim
移值lwip所需的内核架构层支持.
创建线程,互斥锁,信号量,队列的接口实现
* @endverbatim
*/
/***************************************************************
移值lwip所需的内核架构层支持.
创建线程,互斥锁,信号量,队列的接口实现
***************************************************************/
#ifdef LOSCFG_KERNEL_SMP
SPIN_LOCK_INIT(arch_protect_spin);
static u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
......
......@@ -707,7 +707,8 @@ INT32 LOS_DmesgToFile(CHAR *filename)
}
#endif
/*************************************************************
/**
* @brief
dmesg全称是display message (or display driver),即显示信息。
dmesg命令用于控制内核dmesg缓存区
......@@ -724,8 +725,10 @@ dmesg参数缺省时,默认打印缓存区内容。
关闭串口打印会影响shell使用,建议先连接telnet再尝试关闭串口。
dmesg > /usr/dmesg.log。
**************************************************************/
* @param argc
* @param argv
* @return INT32
*/
INT32 OsShellCmdDmesg(INT32 argc, const CHAR **argv)
{
if (argc == 1) {
......
......@@ -347,19 +347,24 @@ ERROUT:
}
return ret;
}
/************************************************
创建文件,从实现看 SysCreat 和 SysOpen 并没有太大的区别,只有打开方式的区别
SysCreat函数完全可以被SysOpen函数替代,常用标签如下:
O_CREAT:若文件存在,此标志无用;若不存在,建新文件
O_TRUNC:若文件存在,则长度被截为0,属性不变
O_WRONLY:写文件
O_RDONLY:读文件
O_BINARY:此标志可显示地给出以二进制方式打开文件
O_TEXT :此标志可用于显示地给出以文本方式打开文件
O_RDWR :即读也写
O_APPEND:即读也写,但每次写总是在文件尾添加
************************************************/
/*!
* @brief 创建文件,从实现看 SysCreat 和 SysOpen 并没有太大的区别,只有打开方式的区别
* \n SysCreat函数完全可以被SysOpen函数替代
* @param pathname
* @param mode
* @verbatim 常用标签如下:
O_CREAT:若文件存在,此标志无用;若不存在,建新文件
O_TRUNC:若文件存在,则长度被截为0,属性不变
O_WRONLY:写文件
O_RDONLY:读文件
O_BINARY:此标志可显示地给出以二进制方式打开文件
O_TEXT :此标志可用于显示地给出以文本方式打开文件
O_RDWR :即读也写
O_APPEND:即读也写,但每次写总是在文件尾添加
* @endverbatim
* @return int
*/
int SysCreat(const char *pathname, mode_t mode)
{
int ret = 0;
......@@ -497,14 +502,16 @@ OUT:
}
return ret;
}
/**************************************************
删除链:删除由装入点管理的文件
执行unlink()函数并不一定会真正的删除文件,它先会检查文件系统中此文件的连接数是否为1,
如果不是1说明此文件还有其他链接对象,因此只对此文件的连接数进行减1操作。若连接数为1,
并且在此时没有任何进程打开该文件,此内容才会真正地被删除掉。在有进程打开此文件的情况下,
则暂时不会删除,直到所有打开该文件的进程都结束时文件就会被删除。
**************************************************/
/**
* @brief 删除链:删除由装入点管理的文件
* @verbatim
执行unlink()函数并不一定会真正的删除文件,它先会检查文件系统中此文件的连接数是否为1,
如果不是1说明此文件还有其他链接对象,因此只对此文件的连接数进行减1操作。若连接数为1,
并且在此时没有任何进程打开该文件,此内容才会真正地被删除掉。在有进程打开此文件的情况下,
则暂时不会删除,直到所有打开该文件的进程都结束时文件就会被删除。
* @endverbatim
*/
int SysUnlink(const char *pathname)
{
int ret;
......@@ -903,7 +910,10 @@ int SysIoctl(int fd, int req, void *arg)
}
return ret;
}
/********************************************************
/**
* @brief
* @verbatim
用来修改已经打开文件的属性的函数包含5个功能:
1.复制一个已有文件描述符,功能和dup和dup2相同,对应的cmd:F_DUPFD、F_DUPFD_CLOEXEC。
当使用这两个cmd时,需要传入第三个参数,fcntl返回复制后的文件描述符,此返回值是之前未被占用的描述符,
......@@ -921,7 +931,12 @@ int SysIoctl(int fd, int req, void *arg)
5.获取、设置异步I/O所有权,对应的cmd:F_GETOWN、F_SETOWN。
获取和设置用来接收SIGIO/SIGURG信号的进程id或者进程组id。返回对应的进程id或者进程组id取负值。
********************************************************/
* @endverbatim
* @param fd
* @param cmd
* @param arg
* @return int
*/
int SysFcntl(int fd, int cmd, void *arg)
{
/* Process fd convert to system global fd */
......@@ -937,23 +952,29 @@ int SysFcntl(int fd, int cmd, void *arg)
}
return ret;
}
/********************************************************
管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。
调用pipe系统函数即可创建一个管道。有如下特质:
1. 其本质是一个伪文件(实为内核缓冲区)
2. 由两个文件描述符引用,一个表示读端,一个表示写端。
3. 规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
管道的局限性:
① 数据自己读不能自己写。
② 数据一旦被读走,便不在管道中存在,不可反复读取。
③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
④ 只能在有公共祖先的进程间使用管道。
常见的通信方式有,单工通信、半双工通信、全双工通信。
********************************************************/
#ifdef LOSCFG_KERNEL_PIPE
/**
* @brief
* @verbatim
管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。
调用pipe系统函数即可创建一个管道。有如下特质:
1. 其本质是一个伪文件(实为内核缓冲区)
2. 由两个文件描述符引用,一个表示读端,一个表示写端。
3. 规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
管道的局限性:
① 数据自己读不能自己写。
② 数据一旦被读走,便不在管道中存在,不可反复读取。
③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
④ 只能在有公共祖先的进程间使用管道。
常见的通信方式有,单工通信、半双工通信、全双工通信。
* @endverbatim
* @param pipefd
* @return int
*/
int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */
{
int ret;
......@@ -995,9 +1016,8 @@ int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */
return ret;
}
#endif
/********************************************************
/复制文件描述符
********************************************************/
/// 复制文件描述符
int SysDup2(int fd1, int fd2)
{
int ret;
......
......@@ -56,27 +56,32 @@
} \
} while (0)
/********************************************************
本文说明:包含消息队列和信号两部分内容,是实现IPC的其中两种方式
IPC(Inter-Process Communication,进程间通信)
每个进程各自有不同的用户地址空间,进程之间地址保护,相互隔离,任何一个进程的信息在另一个进程中都看不到,
所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,
进程B再从内核缓冲区把数据读走,
/**
* @brief 打开一个消息队列,由posix接口封装
* @verbatim
IPC(Inter-Process Communication,进程间通信)
每个进程各自有不同的用户地址空间,进程之间地址保护,相互隔离,任何一个进程的信息在另一个进程中都看不到,
所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,
进程B再从内核缓冲区把数据读走,
IPC实现方式之消息队列:
消息队列特点总结:
(1)消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识.
(2)消息队列允许一个或多个进程向它写入与读取消息.
(3)管道和消息队列的通信数据都是先进先出的原则。
(4)消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更有优势。
(5)消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
(6)目前主要有两种类型的消息队列:POSIX消息队列以及System V消息队列,System V消息队列是随内核持续的,
只有在内核重起或者人工删除时,该消息队列才会被删除。
鸿蒙liteos 支持POSIX消息队列并加入了一种自研的消息队列 liteipc,此处重点讲 posix消息队列
********************************************************/
//打开一个消息队列,由posix接口封装
IPC实现方式之消息队列:
消息队列特点总结:
(1)消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识.
(2)消息队列允许一个或多个进程向它写入与读取消息.
(3)管道和消息队列的通信数据都是先进先出的原则。
(4)消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更有优势。
(5)消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
(6)目前主要有两种类型的消息队列:POSIX消息队列以及System V消息队列,System V消息队列是随内核持续的,
只有在内核重起或者人工删除时,该消息队列才会被删除。
鸿蒙liteos 支持POSIX消息队列并加入了一种自研的消息队列 liteipc,此处重点讲 posix消息队列
* @endverbatim
* @param mqName
* @param openFlag
* @param mode
* @param attr
* @return mqd_t
*/
mqd_t SysMqOpen(const char *mqName, int openFlag, mode_t mode, struct mq_attr *attr)
{
mqd_t ret;
......@@ -120,12 +125,14 @@ int SysMqNotify(mqd_t personal, const struct sigevent *sigev)
}
return ret;
}
/******************************************************
封装posix的标准接口,获取和设置消息队列的属性
new:来判断是否是获取还是设置功能
new==null 获取
否则为设置
******************************************************/
/**
* @brief 封装posix的标准接口,获取和设置消息队列的属性
* @param mqd
* @param new 判断是否是获取还是设置功能,new==null 获取 否则为设置
* @param old
* @return int
*/
int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
{
int ret;
......@@ -150,14 +157,20 @@ int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
}
return ret;
}
/******************************************************
从内核中删除名为mqName的消息队列
如果该函数被调用了,但是仍然有进程已经打开了这个消息队列,那么这个消息队列
的销毁会被推迟到所有的引用都被关闭时执行.并且函数 mq_unlink() 不需要阻塞
到所有的引用都被关闭为止,它会立即返回.函数 mq_unlink()调用成功后, 如果在
随后调用 mq_open() 时重用这个消息队列名字,效果就像这个名字的消息队列不存在,
如果没有设置O_CREAT标志,函数mq_open() 会返回失败,否则会创建一个新的消息队列.
******************************************************/
/**
* @brief
* @verbatim
从内核中删除名为mqName的消息队列
如果该函数被调用了,但是仍然有进程已经打开了这个消息队列,那么这个消息队列
的销毁会被推迟到所有的引用都被关闭时执行.并且函数 mq_unlink() 不需要阻塞
到所有的引用都被关闭为止,它会立即返回.函数 mq_unlink()调用成功后, 如果在
随后调用 mq_open() 时重用这个消息队列名字,效果就像这个名字的消息队列不存在,
如果没有设置O_CREAT标志,函数mq_open() 会返回失败,否则会创建一个新的消息队列.
* @endverbatim
* @param mqName
* @return int
*/
int SysMqUnlink(const char *mqName)
{
int ret;
......@@ -175,9 +188,8 @@ int SysMqUnlink(const char *mqName)
}
return ret;
}
/******************************************************
定时时间发送消息,任务将被阻塞,等待被唤醒写入消息
******************************************************/
/// 定时时间发送消息,任务将被阻塞,等待被唤醒写入消息
int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio,
const struct timespec *absTimeout)
{
......@@ -211,9 +223,8 @@ int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int
}
return ret;
}
/******************************************************
定时接收消息,任务将被阻塞,等待被唤醒读取
******************************************************/
///定时接收消息,任务将被阻塞,等待被唤醒读取
ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio,
const struct timespec *absTimeout)
{
......@@ -263,15 +274,17 @@ int SysSigAction(int sig, const sigaction_t *restrict sa, sigaction_t *restrict
return OsSigAction(sig, sa, old);
}
/*****************************************************
系统调用之进程信号屏蔽,
什么意思?简单说就是 一个信号来了进程要不要处理,屏蔽就是不处理,注意不能屏蔽SIGKILL和SIGSTOP信号,必须要处理.
how
SIG_BLOCK 加入信号到进程屏蔽。set包含了希望阻塞的附加信号
SIG_UNBLOCK 从进程屏蔽里将信号删除。set包含了希望解除阻塞的信号
SIG_SETMASK 将set的值设定为新的进程屏蔽
*****************************************************/
/**
* @brief 系统调用之进程信号屏蔽,
什么意思?简单说就是 一个信号来了进程要不要处理,屏蔽就是不处理,注意不能屏蔽SIGKILL和SIGSTOP信号,必须要处理.
* @param how SIG_BLOCK 加入信号到进程屏蔽。set包含了希望阻塞的附加信号
\n SIG_UNBLOCK 从进程屏蔽里将信号删除。set包含了希望解除阻塞的信号
\n SIG_SETMASK 将set的值设定为新的进程屏蔽
* @param setl
* @param oldl
* @param sigsetsize
* @return int
*/
int SysSigprocMask(int how, const sigset_t_l *restrict setl, sigset_t_l *restrict oldl, size_t sigsetsize)
{
/* Let nxsig_procmask do all of the work */
......@@ -350,7 +363,7 @@ int SysSigPending(sigset_t_l *setl)
}
return ret;
}
///
int SysSigSuspend(sigset_t_l *setl)
{
sigset_t set;
......
......@@ -66,9 +66,10 @@
#ifdef LOSCFG_FS_VFS
#include "vnode.h"
#endif
/*********************************************************
https://blog.csdn.net/piyongduo3393/article/details/89378243
/**
* @file los_syscall.h
* @brief
@verbatim
什么情况下会发生从用户态向内核态切换。这里细分为3种情况:
1、发生系统调用时
......@@ -90,7 +91,11 @@ https://blog.csdn.net/piyongduo3393/article/details/89378243
比如硬盘读写操作的完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
可以看到上述三种由用户态切换到内核态的情况中,只有系统调用是进程主动请求发生切换的,
中断和异常都是被动的。
*********************************************************/
https://blog.csdn.net/piyongduo3393/article/details/89378243
@endverbatim
*/
/* process */
extern unsigned int SysGetGroupId(void);
extern unsigned int SysGetTid(void);
......
......@@ -36,27 +36,25 @@
#include "los_vm_syscall.h"
#include "fs/file.h"
//鸿蒙与Linux标准库的差异 https://weharmony.gitee.io/zh-cn/device-dev/kernel/%E4%B8%8ELinux%E6%A0%87%E5%87%86%E5%BA%93%E7%9A%84%E5%B7%AE%E5%BC%82/
/**************************************************
系统调用|申请虚拟内存(分配线性地址区间)
参数 描述
addr 用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),
/**
* @brief 系统调用|申请虚拟内存(分配线性地址区间)
* \n 鸿蒙与Linux标准库的差异 http://weharmonyos.com/zh-cn/device-dev/kernel/%E4%B8%8ELinux%E6%A0%87%E5%87%86%E5%BA%93%E7%9A%84%E5%B7%AE%E5%BC%82/
* @param addr 用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),
否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。
length 内存段的大小。
prot 用于设置内存段的访问权限,有如下权限:
PROT_READ:允许读该内存段。
PROT_WRITE:允许写该内存段。
PROT_EXEC:允许执行该内存段。
PROT_NONE:不能访问。
flags 控制程序对内存段的改变所造成的影响,有如下属性:
MAP_PRIVATE:标志指定线性区中的页可以被进程独享
MAP_SHARED:标志指定线性区中的页可以被几个进程共享
fd 打开的文件描述符,如果新的线性区将把一个文件映射到内存的情况
offset 用以改变经共享内存段访问的文件中数据的起始偏移值。
成功返回:虚拟内存地址,这地址是页对齐。
失败返回:(void *)-1。
**************************************************/
* @param size 内存段的大小。
* @param prot 用于设置内存段的访问权限,有如下权限:
\n PROT_READ:允许读该内存段。
\n PROT_WRITE:允许写该内存段。
\n PROT_EXEC:允许执行该内存段。
\n PROT_NONE:不能访问。
* @param flags 控制程序对内存段的改变所造成的影响,有如下属性:
\n MAP_PRIVATE:标志指定线性区中的页可以被进程独享
\n MAP_SHARED:标志指定线性区中的页可以被几个进程共享
* @param fd 打开的文件描述符,如果新的线性区将把一个文件映射到内存的情况
* @param offset 用以改变经共享内存段访问的文件中数据的起始偏移值。
* @return void* 成功返回:虚拟内存地址,这地址是页对齐。
\n 失败返回:(void *)-1。
*/
void *SysMmap(void *addr, size_t size, int prot, int flags, int fd, size_t offset)
{
/* Process fd convert to system global fd */
......@@ -64,61 +62,65 @@ void *SysMmap(void *addr, size_t size, int prot, int flags, int fd, size_t offse
return (void *)LOS_MMap((uintptr_t)addr, size, prot, flags, fd, offset);//分配线性地址区间
}
/**************************************************
释放虚拟内存
addr 虚拟内存起始位置
length 内存段的大小
成功返回0 失败返回-1。
**************************************************/
/**
* @brief 释放虚拟内存
* @param addr 虚拟内存起始位置
* @param size 内存段的大小
* @return int 成功返回0 失败返回-1。
*/
int SysMunmap(void *addr, size_t size)
{
return LOS_UnMMap((uintptr_t)addr, size);
}
/**************************************************
重新映射虚拟内存地址
参数 描述
old_address 需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。
old_size 内存段的原始大小。
new_size 新内存段的大小。
flags 如果没有足够的空间在当前位置展开映射,则返回失败
MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;
在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,
还必须指定MREMAP_MAYMOVE。
成功返回:重新映射后的虚拟内存地址
失败返回:((void *)-1)。
**************************************************/
/**
* @brief
* @param oldAddr 需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。
* @param oldLen 内存段的原始大小。
* @param newLen 新内存段的大小。
* @param flags 如果没有足够的空间在当前位置展开映射,则返回失败
\n MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
\n MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;
* @param newAddr 在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,
\n 还必须指定MREMAP_MAYMOVE。
* @return void* 成功返回:重新映射后的虚拟内存地址
\n 失败返回:((void *)-1)。
*/
void *SysMremap(void *oldAddr, size_t oldLen, size_t newLen, int flags, void *newAddr)
{
return (void *)LOS_DoMremap((vaddr_t)oldAddr, oldLen, newLen, flags, (vaddr_t)newAddr);
}
/**************************************************
**************************************************/
int SysMprotect(void *vaddr, size_t len, int prot)
{
return LOS_DoMprotect((uintptr_t)vaddr, len, (unsigned long)prot);
}
/**************************************************
brk也是申请堆内存的一种方式,一般小于 128K 会使用它
**************************************************/
/**
* @brief brk也是申请堆内存的一种方式,一般小于 128K 会使用它
* @param addr
* @return void*
*/
void *SysBrk(void *addr)
{
return LOS_DoBrk(addr);
}
/**************************************************
得到一个共享内存标识符或创建一个共享内存对象
key_t: 建立新共享内存对象 标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案。
为此,每个IPC对象都与一个键(key)相关联,这个键作为该对象的外部名,无论何时创建IPC结构(通过msgget、semget、shmget创建),
都应给IPC指定一个键, key_t由ftok创建,ftok当然在本工程里找不到,所以要写这么多.
size: 新建的共享内存大小,以字节为单位
shmflg: IPC_CREAT IPC_EXCL
IPC_CREAT: 在创建新的IPC时,如果key参数是IPC_PRIVATE或者和当前某种类型的IPC结构无关,则需要指明flag参数的IPC_CREAT标志位,
则用来创建一个新的IPC结构。(如果IPC结构已存在,并且指定了IPC_CREAT,则IPC_CREAT什么都不做,函数也不出错)
IPC_EXCL: 此参数一般与IPC_CREAT配合使用来创建一个新的IPC结构。如果创建的IPC结构已存在函数就出错返回,
返回EEXIST(这与open函数指定O_CREAT和O_EXCL标志原理相同)
**************************************************/
#ifdef LOSCFG_KERNEL_SHM
/**
* @brief 得到一个共享内存标识符或创建一个共享内存对象
* @param key 建立新共享内存对象 标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案。
\n 为此,每个IPC对象都与一个键(key)相关联,这个键作为该对象的外部名,无论何时创建IPC结构(通过msgget、semget、shmget创建),
\n 都应给IPC指定一个键, key_t由ftok创建,ftok当然在本工程里找不到,所以要写这么多.
* @param size 新建的共享内存大小,以字节为单位
* @param shmflg IPC_CREAT IPC_EXCL
\n IPC_CREAT: 在创建新的IPC时,如果key参数是IPC_PRIVATE或者和当前某种类型的IPC结构无关,则需要指明flag参数的IPC_CREAT标志位,
\n 则用来创建一个新的IPC结构。(如果IPC结构已存在,并且指定了IPC_CREAT,则IPC_CREAT什么都不做,函数也不出错)
\n IPC_EXCL: 此参数一般与IPC_CREAT配合使用来创建一个新的IPC结构。如果创建的IPC结构已存在函数就出错返回,
\n 返回EEXIST(这与open函数指定O_CREAT和O_EXCL标志原理相同)
* @return int
*/
int SysShmGet(key_t key, size_t size, int shmflg)
{
int ret;
......@@ -130,12 +132,18 @@ int SysShmGet(key_t key, size_t size, int shmflg)
return ret;
}
/**************************************************
连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
一旦创建/引用了一个共享存储段,那么进程就可调用shmat函数将其连接到它的地址空间中
如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值加1
shmid 就是个索引,就跟进程和线程的ID一样 g_shmSegs[shmid] shmid > 192个
**************************************************/
/**
* @brief @verbatim
连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
一旦创建/引用了一个共享存储段,那么进程就可调用shmat函数将其连接到它的地址空间中
如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值加1
@endverbatim
* @param shmid
* @param shmaddr
* @param shmflg
* @return void*
*/
void *SysShmAt(int shmid, const void *shmaddr, int shmflg)
{
void *ret = NULL;
......@@ -147,16 +155,17 @@ void *SysShmAt(int shmid, const void *shmaddr, int shmflg)
return ret;
}
/**************************************************
完成对共享内存的控制
此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
msqid 共享内存标识符
cmd IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
buf 共享内存管理结构体。
**************************************************/
/**
* @brief 完成对共享内存的控制
此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
* @param shmid 共享内存标识符
* @param cmd IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
\n IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
\n IPC_RMID:删除这片共享内存
* @param buf 共享内存管理结构体。
* @return int
*/
int SysShmCtl(int shmid, int cmd, struct shmid_ds *buf)
{
int ret;
......@@ -168,12 +177,13 @@ int SysShmCtl(int shmid, int cmd, struct shmid_ds *buf)
return ret;
}
/**************************************************
与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存
shmaddr:连接的共享内存的起始地址
本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
返回值 成功:0 出错:-1,错误原因存于error中r
**************************************************/
/**
* @brief 与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存
* @param shmaddr 连接的共享内存的起始地址
* \n 本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
* @return int 返回值 成功:0 出错:-1,错误原因存于error中
*/
int SysShmDt(const void *shmaddr)
{
int ret;
......
git add -A
git commit -m ' http://weharmonyos.com/doxygen/index.html ,支持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.
先完成此消息的编辑!
想要评论请 注册