75#ifdef LOSCFG_KERNEL_SHM
79#define SYSV_SHM_LOCK() (VOID)LOS_MuxLock(&g_sysvShmMux, LOS_WAIT_FOREVER)
80#define SYSV_SHM_UNLOCK() (VOID)LOS_MuxUnlock(&g_sysvShmMux)
82#define SHM_MAX_PAGES 4096
83#define SHM_MAX (SHM_MAX_PAGES * PAGE_SIZE)
87#define SHM_ALL (SHM_MAX_PAGES)
89#define SHM_SEG_FREE 0x2000
90#define SHM_SEG_USED 0x4000
91#define SHM_SEG_REMOVE 0x8000
101#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO)
104#define SHM_S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
105#define SHM_S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
106#define SHM_S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
107#define SHM_GROUPE_TO_USER 3
108#define SHM_OTHER_TO_USER 6
194 VM_ERR(
"ShmInit fail\n");
281 if (count != (size >> PAGE_SHIFT)) {
283 seg->
status = SHM_SEG_FREE;
289 seg->
status |= SHM_SEG_USED;
317 VM_ERR(
"free physical pages failed, count = %d, size = %d", count, seg->
ds.
shm_segsz >> PAGE_SHIFT);
321 seg->
status = SHM_SEG_FREE;
332 if ((seg->
status & SHM_SEG_USED) &&
349 if (((
UINT32)shmFlg & (IPC_CREAT | IPC_EXCL)) ==
350 (IPC_CREAT | IPC_EXCL)) {
382 LOS_DL_LIST_FOR_EACH_ENTRY(vmPage, pageList,
LosVmPage,
node) {
383 pa = VM_PAGE_TO_PHYS(vmPage);
387 VM_ERR(
"LOS_ArchMmuMap failed, ret = %d", ret);
401 VM_ERR(
"shm fork failed!");
437 return (region->
regionFlags & VM_MAP_REGION_FLAG_SHM) ? TRUE : FALSE;
448 if (seg->
status & SHM_SEG_USED) {
464 accMode = mode & S_IRWXU;
467 privMode <<= SHM_GROUPE_TO_USER;
468 accMode = (mode & S_IRWXG) << SHM_GROUPE_TO_USER;
470 privMode <<= SHM_OTHER_TO_USER;
471 accMode = (mode & S_IRWXO) << SHM_OTHER_TO_USER;
474 if (privMode & SHM_R) {
478 if (privMode & SHM_W) {
482 if (privMode & SHM_X) {
486 if ((mode == SHM_M) && (tmpMode & SHM_M)) {
488 }
else if (mode == SHM_M) {
492 if ((tmpMode & accMode) == accMode) {
522 if (key == IPC_PRIVATE) {
527 if (((
UINT32)shmflg & IPC_CREAT) == 0) {
535 if (((
UINT32)shmflg & IPC_CREAT) &&
536 ((
UINT32)shmflg & IPC_EXCL)) {
558 PRINT_DEBUG(
"%s %d, ret = %d\n", __FUNCTION__, __LINE__, ret);
564 if (((
UINT32)shmflg & SHM_REMAP) && (shmaddr == NULL)) {
568 if ((shmaddr != NULL) && !IS_PAGE_ALIGNED(shmaddr) &&
569 (((
UINT32)shmflg & SHM_RND) == 0)) {
581 UINT32 flags = MAP_ANONYMOUS | MAP_SHARED;
582 UINT32 mapFlags = flags | MAP_FIXED;
587 if (shmaddr != NULL) {
588 flags |= MAP_FIXED_NOREPLACE;
592 if (shmaddr == NULL) {
595 if ((
UINT32)shmflg & SHM_RND) {
610 if (region == NULL) {
638 mode_t acc_mode = SHM_S_IRUGO;
648 if ((
UINT32)shmflg & SHM_EXEC) {
650 acc_mode |= SHM_S_IXUGO;
651 }
else if (((
UINT32)shmflg & SHM_RDONLY) == 0) {
653 acc_mode |= SHM_S_IWUGO;
686 PRINT_DEBUG(
"%s %d, ret = %d\n", __FUNCTION__, __LINE__, ret);
707 struct shm_info shmInfo;
710 cmd = ((
UINT32)cmd & ~IPC_64);
714 if ((cmd != IPC_INFO) && (cmd != SHM_INFO)) {
722 if ((buf == NULL) && (cmd != IPC_RMID)) {
740 if (cmd == SHM_STAT) {
741 ret = (
unsigned int)((
unsigned int)seg->
ds.
shm_perm.seq << 16) | (
unsigned int)((
unsigned int)shmid & 0xffff);
759 (shm_perm.
mode & ACCESSPERMS);
762 (VOID)memcpy_s(seg->
ownerName, OS_PCB_NAME_LEN, OS_PCB_FROM_PID(shm_perm.
uid)->processName,
773 seg->
status |= SHM_SEG_REMOVE;
790 shmInfo.swap_attempts = 0;
791 shmInfo.swap_successes = 0;
801 VM_ERR(
"the cmd(%d) is not supported!", cmd);
812 PRINT_DEBUG(
"%s %d, ret = %d\n", __FUNCTION__, __LINE__, ret);
832 if (IS_PAGE_ALIGNED(shmaddr) == 0) {
839 if (region == NULL) {
841 goto ERROR_WITH_LOCK;
843 shmid = region->
shmid;
847 goto ERROR_WITH_LOCK;
868 (seg->
status & SHM_SEG_REMOVE)) {
883 PRINT_DEBUG(
"%s %d, ret = %d\n", __FUNCTION__, __LINE__, ret);
893 PRINTK(
"\r\n------- Shared Memory Segments -------\n");
894 PRINTK(
"key shmid perms bytes nattch status owner\n");
898 if (!(seg->
status & SHM_SEG_USED)) {
901 PRINTK(
"%08x %-8d %-10o %-10u %-10u %-10x %s\n", seg->
ds.
shm_perm.key,
913 PRINT_ERR(
"shmid is invalid: %d\n", shmid);
932 PRINTK(
"\tnone option, print shm usage info\n"
933 "\t-r [shmid], Recycle the specified shared memory about shmid\n"
934 "\t-h | --help, print shm command usage\n");
944 }
else if (argc == 1) {
945 if ((strcmp(argv[0],
"-h") != 0) && (strcmp(argv[0],
"--help") != 0)) {
946 PRINTK(
"Invalid option: %s\n", argv[0]);
949 }
else if (argc == 2) {
950 if (strcmp(argv[0],
"-r") != 0) {
951 PRINTK(
"Invalid option: %s\n", argv[0]);
954 shmid = strtoul((
CHAR *)argv[1], &endPtr, 0);
955 if ((endPtr == NULL) || (*endPtr != 0)) {
956 PRINTK(
"check shmid %s(us) invalid\n", argv[1]);
@ CMD_TYPE_SHOW
用户怎么输入就怎么显示出现,包括 \0 这些字符也都会存在
STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
Atomic addSelf.
STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
Atomic auto-decrement. | 对32bit原子数据做减1
LITE_OS_SEC_TEXT UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary)
Align the value (addr) by some bytes (boundary) you specify.
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
初始化互斥锁
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
销毁互斥锁
https://blog.csdn.net/qq_38410730/article/details/81036768
STATUS_T LOS_ArchMmuMap(LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T paddr, size_t count, UINT32 flags)
LOS_ArchMmuMap 映射进程空间虚拟地址区间与物理地址区间 所谓的map就是生成L1,L2页表项的过程
STATUS_T LOS_ArchMmuUnmap(LosArchMmu *archMmu, VADDR_T vaddr, size_t count)
LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系
LITE_OS_SEC_TEXT INT32 LOS_GetUserID(VOID)
LITE_OS_SEC_TEXT INT32 LOS_GetGroupID(VOID)
LITE_OS_SEC_TEXT UINT32 LOS_GetCurrProcessID(VOID)
获取当前进程的进程ID
LITE_OS_SEC_TEXT BOOL LOS_CheckInGroups(UINT32 gid)
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
VOID LOS_RbDelNode(LosRbTree *pstTree, LosRbNode *pstNode)
STATIC INLINE VOID OsCleanPageShared(LosVmPage *page)
给页面撕掉共享页标签
STATIC INLINE VOID OsSetPageShared(LosVmPage *page)
STATIC INLINE STATUS_T LOS_MuxAcquire(LosMux *m)
STATIC INLINE STATUS_T LOS_MuxRelease(LosMux *m)
STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
从外部权限标签转化为线性区权限标签
LosVmMapRegion * LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr)
查找线性区 根据起始地址在进程空间内查找是否存在
LosVmMapRegion * LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff)
LosVmMapRegion * LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
查找线性区 根据地址区间在进程空间内查找是否存在
size_t LOS_PhysPagesAlloc(size_t nPages, LOS_DL_LIST *list)
LOS_PhysPagesAlloc 分配nPages页个物理页框,并将页框挂入list 返回已分配的页面大小,不负责一定能分配到nPages的页框
size_t LOS_PhysPagesFree(LOS_DL_LIST *list)
释放双链表中的所有节点内存,本质是回归到伙伴orderlist中
VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags, int fd, unsigned long pgoff)
void free(void *ptr)
释放ptr所指向的内存空间
STATIC struct shmIDSource * g_shmSegs
VOID OsShmFork(LosVmSpace *space, LosVmMapRegion *oldRegion, LosVmMapRegion *newRegion)
fork 一个共享线性区
LosVmMapRegion * ShmatVmmAlloc(struct shmIDSource *seg, const VOID *shmaddr, INT32 shmflg, UINT32 prot)
分配一个共享线性区并映射好
BOOL OsIsShmRegion(LosVmMapRegion *region)
是否为共享线性区,是否有标签?
STATIC VOID OsShmDeleteCmd(INT32 shmid)
STATIC VOID OsShmInfoCmd(VOID)
STATIC INT32 ShmFindSegByKey(key_t key)
通过key查找 shmId
STATIC INLINE VOID ShmFreeSeg(struct shmIDSource *seg)
释放seg->node 所占物理页框,seg本身重置
LOS_MODULE_INIT(ShmInit, LOS_INIT_LEVEL_VM_COMPLETE)
STATIC LosMux g_sysvShmMux
INT32 ShmDt(const VOID *shmaddr)
当对共享存储的操作已经结束时,则调用shmdt与该存储段分离 如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值减1
STATIC UINT32 g_shmUsedPageCount
STATIC VOID ShmSetSharedFlag(struct shmIDSource *seg)
给共享段中所有物理页框贴上共享标签
INT32 ShmatParamCheck(const VOID *shmaddr, INT32 shmflg)
STATIC INT32 ShmAllocSeg(key_t key, size_t size, INT32 shmflg)
为共享段分配物理内存 例如:参数size = 4097, LOS_Align(size, PAGE_SIZE) = 8192 分配页数 size >> PAGE_SHIFT = 2页
INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
ShmCtl 此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
VOID OsShmRegionFree(LosVmSpace *space, LosVmMapRegion *region)
释放共享线性区
STATIC VOID OsShmCmdUsage(VOID)
UINT32 OsShellCmdShm(INT32 argc, const CHAR *argv[])
共享内存
STATIC VOID ShmClearSharedFlag(struct shmIDSource *seg)
给共享段中所有物理页框撕掉共享标签
STATIC struct shminfo g_shmInfo
STATIC struct shmIDSource * ShmFindSeg(int shmid)
通过ID找到共享内存资源
STATIC INT32 ShmSegValidCheck(INT32 segNum, size_t size, INT32 shmFlg)
共享内存段有效性检查
SHELLCMD_ENTRY(shm_shellcmd, CMD_TYPE_SHOW, "shm", 2,(CmdCallBackFunc) OsShellCmdShm)
STATIC VOID ShmPagesRefDec(struct shmIDSource *seg)
seg下所有共享页引用减少
VOID * ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg)
ShmAt 用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
STATIC VOID ShmVmmMapping(LosVmSpace *space, LOS_DL_LIST *pageList, VADDR_T vaddr, UINT32 regionFlags)
共享内存映射
STATIC INT32 ShmSegUsedCount(VOID)
获取共享内存池中已被使用的段数量
INT32 ShmGet(key_t key, size_t size, INT32 shmflg)
ShmGet 得到一个共享内存标识符或创建一个共享内存对象
STATIC INT32 ShmPermCheck(struct shmIDSource *seg, mode_t mode)
对共享内存段权限检查
CHAR processName[OS_PCB_NAME_LEN]
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间
CHAR ownerName[OS_PCB_NAME_LEN]
size_t shm_segsz
共享内存段的大小,单位为字节
time_t shm_dtime
最后一个进程离开共享内存的时间
pid_t shm_lpid
最后操作共享内存的进程ID
unsigned long shm_nattch
当前使用该共享内存段的进程数量
struct ipc_perm shm_perm
操作许可,里面包含共享内存的用户ID、组ID等信息
time_t shm_atime
最后一个进程访问共享内存的时间
pid_t shm_cpid
创建共享内存的进程ID
unsigned long __unused[4]
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 ARG_NUM_0 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_4 ARG_NUM_5 ARG_NUM_6 ARG_NUM_3 ARG_NUM_5 ARG_NUM_7 ARG_NUM_1 ARG_NUM_4 ARG_NUM_5 ARG_NUM_4 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_7 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_7 ARG_NUM_3 ARG_NUM_2 char ARG_NUM_2 ARG_NUM_1 ARG_NUM_0 ARG_NUM_0 ARG_NUM_3 void ARG_NUM_1 ARG_NUM_0 unsigned ARG_NUM_0 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_5 ARG_NUM_3 ARG_NUM_3 ARG_NUM_4 ARG_NUM_1 ARG_NUM_1 ARG_NUM_3 ARG_NUM_2 mode_t
u32_t(* CmdCallBackFunc)(u32_t argc, const char **argv)
size_t LOS_ArchCopyToUser(void *dst, const void *src, size_t len)
从内核空间拷贝到用户空间
size_t LOS_ArchCopyFromUser(void *dst, const void *src, size_t len)