Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
鸿蒙内核源码分析
注释鸿蒙内核源码
提交
2f73237a
注释鸿蒙内核源码
项目概览
鸿蒙内核源码分析
/
注释鸿蒙内核源码
通知
270
Star
29
Fork
11
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
106
Wiki
分析
仓库
DevOps
项目成员
Pages
注释鸿蒙内核源码
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
106
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
2f73237a
编写于
10月 21, 2020
作者:
鸿蒙内核源码分析
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
鸿蒙源码分析系列篇
https://blog.csdn.net/kuangyufei
https://my.oschina.net/u/3751245
上级
4e89c02a
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
102 addition
and
88 deletion
+102
-88
arch/arm/arm/src/user_copy.c
arch/arm/arm/src/user_copy.c
+1
-1
kernel/base/include/los_vm_filemap.h
kernel/base/include/los_vm_filemap.h
+4
-4
kernel/base/vm/los_vm_map.c
kernel/base/vm/los_vm_map.c
+1
-1
kernel/base/vm/shm.c
kernel/base/vm/shm.c
+96
-82
zzz/git/pull.sh
zzz/git/pull.sh
+0
-0
zzz/git/push.sh
zzz/git/push.sh
+0
-0
zzz/test/gcc.sh
zzz/test/gcc.sh
+0
-0
zzz/test/main.c
zzz/test/main.c
+0
-0
zzz/test/main.exe
zzz/test/main.exe
+0
-0
zzz/test/main.s
zzz/test/main.s
+0
-0
未找到文件。
arch/arm/arm/src/user_copy.c
浏览文件 @
2f73237a
...
...
@@ -61,7 +61,7 @@ size_t arch_copy_to_user(void *dst, const void *src, size_t len)
}
size_t
LOS_ArchCopyToUser
(
void
*
dst
,
const
void
*
src
,
size_t
len
)
{
{
//先判断地址是不是在用户空间
if
(
!
LOS_IsUserAddressRange
((
VADDR_T
)(
UINTPTR
)
dst
,
len
))
{
return
len
;
}
...
...
kernel/base/include/los_vm_filemap.h
浏览文件 @
2f73237a
...
...
@@ -168,14 +168,14 @@ STATIC INLINE BOOL OsIsPageMapped(LosFilePage *page)
/* The follow three functions is used to SHM module */
STATIC
INLINE
VOID
OsSetPageShared
(
LosVmPage
*
page
)
{
LOS_BitmapSet
(
&
page
->
flags
,
FILE_PAGE_SHARED
);
LOS_BitmapSet
(
&
page
->
flags
,
FILE_PAGE_SHARED
);
//设为共享页面,共享页位 置0
}
//取消共享页属性
STATIC
INLINE
VOID
OsCleanPageShared
(
LosVmPage
*
page
)
{
LOS_BitmapClr
(
&
page
->
flags
,
FILE_PAGE_SHARED
);
LOS_BitmapClr
(
&
page
->
flags
,
FILE_PAGE_SHARED
);
//共享页位 置0
}
//是否为共享页
STATIC
INLINE
BOOL
OsIsPageShared
(
LosVmPage
*
page
)
{
return
BIT_GET
(
page
->
flags
,
FILE_PAGE_SHARED
);
...
...
kernel/base/vm/los_vm_map.c
浏览文件 @
2f73237a
...
...
@@ -453,7 +453,7 @@ LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, un
region
->
regionFlags
=
regionFlags
;
//标识,可读可写可执行这些
region
->
regionType
=
VM_MAP_REGION_TYPE_NONE
;
//未映射
region
->
forkFlags
=
0
;
//
region
->
shmid
=
-
1
;
region
->
shmid
=
-
1
;
//默认线性区为不共享,无共享资源ID
return
region
;
}
//通过虚拟地址查询物理地址
...
...
kernel/base/vm/shm.c
浏览文件 @
2f73237a
...
...
@@ -73,31 +73,31 @@ STATIC LosMux g_sysvShmMux;
#define SHM_M 010000
#endif
#ifndef ACCESSPERMS
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO)
#endif
#ifndef ACCESSPERMS
//出工程区了,详见..\vendor_hisi_hi3861_hi3861\hi3861\platform\os\Huawei_LiteOS\components\lib\libc\musl\include\sys\stat.h
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO)
//文件权限值意思就是 用户,用户组,其他可读可写.
#endif
//代表含义U:user G:group O:other
#define SHM_GROUPE_TO_USER 3
#define SHM_OTHER_TO_USER 6
/* private structure */
struct
shmSegMap
{
vaddr_t
vaddr
;
INT32
shmID
;
vaddr_t
vaddr
;
//虚拟地址
INT32
shmID
;
//可看出共享内存使用了ID管理机制
};
//结构体定义可见于..\vendor_hisi_hi3861_hi3861\hi3861\platform\os\Huawei_LiteOS\components\lib\libc\musl\arch\generic\bits\shm.h
struct
shmIDSource
{
struct
shmid_ds
ds
;
UINT32
status
;
LOS_DL_LIST
node
;
struct
shmIDSource
{
//共享存储结构体
struct
shmid_ds
ds
;
//是内核为每一个共享内存段维护的数据结构,包含权限,各进程最后操作的时间,进程ID等信息
UINT32
status
;
//状态 SHM_SEG_FREE ...
LOS_DL_LIST
node
;
//节点,挂vmPage
};
/* private data */
STATIC
struct
shminfo
g_shmInfo
=
{
.
shmmax
=
SHM_MAX
,
//最大的内存segment的大小
.
shmmin
=
SHM_MIN
,
//最小的内存segment的大小
.
shmmni
=
SHM_MNI
,
//整个系统的内存segment的总个数
.
shmseg
=
SHM_SEG
,
//每个进程可以使用的内存segment的最大个数
.
shmmax
=
SHM_MAX
,
//最大的内存segment的大小
50M
.
shmmin
=
SHM_MIN
,
//最小的内存segment的大小
1M
.
shmmni
=
SHM_MNI
,
//整个系统的内存segment的总个数
:默认192 ShmAllocSeg
.
shmseg
=
SHM_SEG
,
//每个进程可以使用的内存segment的最大个数
128
.
shmall
=
SHM_ALL
,
};
...
...
@@ -113,38 +113,38 @@ INT32 ShmInit(VOID)
return
-
1
;
}
g_shmSegs
=
LOS_MemAlloc
((
VOID
*
)
OS_SYS_MEM_ADDR
,
sizeof
(
struct
shmIDSource
)
*
g_shmInfo
.
shmmni
);
g_shmSegs
=
LOS_MemAlloc
((
VOID
*
)
OS_SYS_MEM_ADDR
,
sizeof
(
struct
shmIDSource
)
*
g_shmInfo
.
shmmni
);
//分配shm段数组
if
(
g_shmSegs
==
NULL
)
{
(
VOID
)
LOS_MuxDestroy
(
&
g_sysvShmMux
);
return
-
1
;
}
(
VOID
)
memset_s
(
g_shmSegs
,
(
sizeof
(
struct
shmIDSource
)
*
g_shmInfo
.
shmmni
),
0
,
(
sizeof
(
struct
shmIDSource
)
*
g_shmInfo
.
shmmni
));
0
,
(
sizeof
(
struct
shmIDSource
)
*
g_shmInfo
.
shmmni
));
//数组清零
for
(
i
=
0
;
i
<
g_shmInfo
.
shmmni
;
i
++
)
{
g_shmSegs
[
i
].
status
=
SHM_SEG_FREE
;
g_shmSegs
[
i
].
ds
.
shm_perm
.
seq
=
i
+
1
;
LOS_ListInit
(
&
g_shmSegs
[
i
].
node
);
g_shmSegs
[
i
].
status
=
SHM_SEG_FREE
;
//节点初始状态为空闲
g_shmSegs
[
i
].
ds
.
shm_perm
.
seq
=
i
+
1
;
//struct ipc_perm shm_perm;系统为每一个IPC对象保存一个ipc_perm结构体,结构说明了IPC对象的权限和所有者
LOS_ListInit
(
&
g_shmSegs
[
i
].
node
);
//初始化节点
}
return
0
;
}
//共享内存释放初始化
INT32
ShmDeinit
(
VOID
)
{
UINT32
ret
;
(
VOID
)
LOS_MemFree
((
VOID
*
)
OS_SYS_MEM_ADDR
,
g_shmSegs
);
(
VOID
)
LOS_MemFree
((
VOID
*
)
OS_SYS_MEM_ADDR
,
g_shmSegs
);
//归还内存池
g_shmSegs
=
NULL
;
ret
=
LOS_MuxDestroy
(
&
g_sysvShmMux
);
ret
=
LOS_MuxDestroy
(
&
g_sysvShmMux
);
//销毁互斥量
if
(
ret
!=
LOS_OK
)
{
return
-
1
;
}
return
0
;
}
//设置共享flag
STATIC
inline
VOID
ShmSetSharedFlag
(
struct
shmIDSource
*
seg
)
{
LosVmPage
*
page
=
NULL
;
...
...
@@ -162,7 +162,7 @@ STATIC inline VOID ShmClearSharedFlag(struct shmIDSource *seg)
OsCleanPageShared
(
page
);
}
}
//seg下所有共享页引用减少
STATIC
VOID
ShmPagesRefDec
(
struct
shmIDSource
*
seg
)
{
LosVmPage
*
page
=
NULL
;
...
...
@@ -171,7 +171,7 @@ STATIC VOID ShmPagesRefDec(struct shmIDSource *seg)
LOS_AtomicDec
(
&
page
->
refCounts
);
}
}
//分配共享页
STATIC
INT32
ShmAllocSeg
(
key_t
key
,
size_t
size
,
int
shmflg
)
{
INT32
i
;
...
...
@@ -186,9 +186,9 @@ STATIC INT32 ShmAllocSeg(key_t key, size_t size, int shmflg)
size
=
LOS_Align
(
size
,
PAGE_SIZE
);
for
(
i
=
0
;
i
<
g_shmInfo
.
shmmni
;
i
++
)
{
if
(
g_shmSegs
[
i
].
status
&
SHM_SEG_FREE
)
{
g_shmSegs
[
i
].
status
&=
~
SHM_SEG_FREE
;
segNum
=
i
;
if
(
g_shmSegs
[
i
].
status
&
SHM_SEG_FREE
)
{
//找到空闲段
g_shmSegs
[
i
].
status
&=
~
SHM_SEG_FREE
;
//变成非空闲状态
segNum
=
i
;
//标号
break
;
}
}
...
...
@@ -198,15 +198,15 @@ STATIC INT32 ShmAllocSeg(key_t key, size_t size, int shmflg)
}
seg
=
&
g_shmSegs
[
segNum
];
count
=
LOS_PhysPagesAlloc
(
size
>>
PAGE_SHIFT
,
&
seg
->
node
);
if
(
count
!=
(
size
>>
PAGE_SHIFT
))
{
(
VOID
)
LOS_PhysPagesFree
(
&
seg
->
node
);
seg
->
status
=
SHM_SEG_FREE
;
count
=
LOS_PhysPagesAlloc
(
size
>>
PAGE_SHIFT
,
&
seg
->
node
);
//分配共享页面,函数内部把node都挂好了.
if
(
count
!=
(
size
>>
PAGE_SHIFT
))
{
//异常释放
(
VOID
)
LOS_PhysPagesFree
(
&
seg
->
node
);
//
seg
->
status
=
SHM_SEG_FREE
;
//回归seg池
return
-
ENOMEM
;
}
ShmSetSharedFlag
(
seg
);
ShmSetSharedFlag
(
seg
);
//node的每个页面设置为此乃共享页也
seg
->
status
|=
SHM_SEG_USED
;
seg
->
status
|=
SHM_SEG_USED
;
//段已使用
seg
->
ds
.
shm_perm
.
mode
=
(
unsigned
int
)
shmflg
&
ACCESSPERMS
;
seg
->
ds
.
shm_perm
.
key
=
key
;
seg
->
ds
.
shm_segsz
=
size
;
...
...
@@ -270,7 +270,7 @@ STATIC INT32 ShmSegValidCheck(INT32 segNum, size_t size, int shmFalg)
return
segNum
;
}
//通过ID找到资源
STATIC
struct
shmIDSource
*
ShmFindSeg
(
int
shmid
)
{
struct
shmIDSource
*
seg
=
NULL
;
...
...
@@ -281,7 +281,7 @@ STATIC struct shmIDSource *ShmFindSeg(int shmid)
}
seg
=
&
g_shmSegs
[
shmid
];
if
((
seg
->
status
&
SHM_SEG_FREE
)
||
(
seg
->
status
&
SHM_SEG_REMOVE
))
{
if
((
seg
->
status
&
SHM_SEG_FREE
)
||
(
seg
->
status
&
SHM_SEG_REMOVE
))
{
//空闲或删除时
set_errno
(
EIDRM
);
return
NULL
;
}
...
...
@@ -306,13 +306,13 @@ STATIC VOID ShmVmmMapping(LosVmSpace *space, LOS_DL_LIST *pageList, VADDR_T vadd
va
+=
PAGE_SIZE
;
}
}
//fork 一个共享线性区
VOID
OsShmFork
(
LosVmSpace
*
space
,
LosVmMapRegion
*
oldRegion
,
LosVmMapRegion
*
newRegion
)
{
struct
shmIDSource
*
seg
=
NULL
;
SYSV_SHM_LOCK
();
seg
=
ShmFindSeg
(
oldRegion
->
shmid
);
seg
=
ShmFindSeg
(
oldRegion
->
shmid
);
//通过老区ID获取对应的共享资源ID结构体
if
(
seg
==
NULL
)
{
SYSV_SHM_UNLOCK
();
VM_ERR
(
"shm fork failed!"
);
...
...
@@ -364,7 +364,7 @@ STATIC INT32 ShmSegUsedCount(VOID)
}
return
count
;
}
//共享内存权限检查
STATIC
INT32
ShmPermCheck
(
struct
shmIDSource
*
seg
,
mode_t
mode
)
{
INT32
uid
=
LOS_GetUserID
();
...
...
@@ -405,9 +405,15 @@ STATIC INT32 ShmPermCheck(struct shmIDSource *seg, mode_t mode)
}
/*
得到一个共享内存标识符或创建一个共享内存对象
key_t:建立新共享内存对象
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标志原理相同)
*/
INT32
ShmGet
(
key_t
key
,
size_t
size
,
INT32
shmflg
)
{
...
...
@@ -466,13 +472,13 @@ INT32 ShmatParamCheck(const void *shmaddr, int shmflg)
}
if
((
shmaddr
!=
NULL
)
&&
!
IS_PAGE_ALIGNED
(
shmaddr
)
&&
((
shmflg
&
SHM_RND
)
==
0
))
{
((
shmflg
&
SHM_RND
)
==
0
))
{
//取整 SHM_RND
return
EINVAL
;
}
return
0
;
}
//共享
LosVmMapRegion
*
ShmatVmmAlloc
(
struct
shmIDSource
*
seg
,
const
VOID
*
shmaddr
,
INT32
shmflg
,
UINT32
prot
)
{
...
...
@@ -482,11 +488,11 @@ LosVmMapRegion *ShmatVmmAlloc(struct shmIDSource *seg, const VOID *shmaddr,
UINT32
regionFlags
;
INT32
ret
;
regionFlags
=
OsCvtProtFlagsToRegionFlags
(
prot
,
MAP_ANONYMOUS
|
MAP_SHARED
);
regionFlags
=
OsCvtProtFlagsToRegionFlags
(
prot
,
MAP_ANONYMOUS
|
MAP_SHARED
);
//映射方式:共享或匿名
(
VOID
)
LOS_MuxAcquire
(
&
space
->
regionMux
);
if
(
shmaddr
==
NULL
)
{
region
=
LOS_RegionAlloc
(
space
,
0
,
seg
->
ds
.
shm_segsz
,
regionFlags
,
0
);
}
else
{
if
(
shmaddr
==
NULL
)
{
//shm_segsz:段的大小(以字节为单位)
region
=
LOS_RegionAlloc
(
space
,
0
,
seg
->
ds
.
shm_segsz
,
regionFlags
,
0
);
//分配一个区,注意这里的虚拟地址传的是0,
}
else
{
//如果地址虚拟地址传入是0,则由内核选择创建映射的虚拟地址, 这是创建新映射的最便捷的方法。
if
(
shmflg
&
SHM_RND
)
{
vaddr
=
ROUNDDOWN
((
VADDR_T
)(
UINTPTR
)
shmaddr
,
SHMLBA
);
}
else
{
...
...
@@ -513,7 +519,11 @@ ERROR:
(
VOID
)
LOS_MuxRelease
(
&
space
->
regionMux
);
return
NULL
;
}
/* 共享存储的连接使用
一旦创建/引用了一个共享存储段,那么进程就可调用shmat函数将其连接到它的地址空间中
如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值加1
shmid 就是个索引,就跟进程和线程的ID一样 g_shmSegs[shmid] shmid > 192个
*/
VOID
*
ShmAt
(
INT32
shmid
,
const
VOID
*
shmaddr
,
INT32
shmflg
)
{
INT32
ret
;
...
...
@@ -522,7 +532,7 @@ VOID *ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg)
LosVmMapRegion
*
r
=
NULL
;
mode_t
mode
;
ret
=
ShmatParamCheck
(
shmaddr
,
shmflg
);
ret
=
ShmatParamCheck
(
shmaddr
,
shmflg
);
//参数检查
if
(
ret
!=
0
)
{
set_errno
(
ret
);
return
(
VOID
*
)
-
1
;
...
...
@@ -535,19 +545,19 @@ VOID *ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg)
}
SYSV_SHM_LOCK
();
seg
=
ShmFindSeg
(
shmid
);
seg
=
ShmFindSeg
(
shmid
);
//找到段
if
(
seg
==
NULL
)
{
SYSV_SHM_UNLOCK
();
return
(
VOID
*
)
-
1
;
}
mode
=
((
unsigned
int
)
shmflg
&
SHM_RDONLY
)
?
SHM_R
:
(
SHM_R
|
SHM_W
);
mode
=
((
unsigned
int
)
shmflg
&
SHM_RDONLY
)
?
SHM_R
:
(
SHM_R
|
SHM_W
);
//读写模式判断
ret
=
ShmPermCheck
(
seg
,
mode
);
if
(
ret
!=
0
)
{
goto
ERROR
;
}
seg
->
ds
.
shm_nattch
++
;
seg
->
ds
.
shm_nattch
++
;
//ds上记录有一个进程绑定上来
r
=
ShmatVmmAlloc
(
seg
,
shmaddr
,
shmflg
,
prot
);
if
(
r
==
NULL
)
{
seg
->
ds
.
shm_nattch
--
;
...
...
@@ -555,10 +565,10 @@ VOID *ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg)
return
(
VOID
*
)
-
1
;
}
r
->
shmid
=
shmid
;
r
->
regionFlags
|=
VM_MAP_REGION_FLAG_SHM
;
seg
->
ds
.
shm_atime
=
time
(
NULL
);
seg
->
ds
.
shm_lpid
=
LOS_GetCurrProcessID
();
r
->
shmid
=
shmid
;
//把ID给线性区的shmid
r
->
regionFlags
|=
VM_MAP_REGION_FLAG_SHM
;
//这是一个共享线性区
seg
->
ds
.
shm_atime
=
time
(
NULL
);
//访问时间
seg
->
ds
.
shm_lpid
=
LOS_GetCurrProcessID
();
//进程ID
SYSV_SHM_UNLOCK
();
return
(
VOID
*
)(
UINTPTR
)
r
->
range
.
base
;
...
...
@@ -568,7 +578,7 @@ ERROR:
PRINT_DEBUG
(
"%s %d, ret = %d
\n
"
,
__FUNCTION__
,
__LINE__
,
ret
);
return
(
VOID
*
)
-
1
;
}
//此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
INT32
ShmCtl
(
INT32
shmid
,
INT32
cmd
,
struct
shmid_ds
*
buf
)
{
struct
shmIDSource
*
seg
=
NULL
;
...
...
@@ -595,13 +605,13 @@ INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
switch
(
cmd
)
{
case
IPC_STAT
:
case
SHM_STAT
:
case
SHM_STAT
:
//取段结构
ret
=
ShmPermCheck
(
seg
,
SHM_R
);
if
(
ret
!=
0
)
{
goto
ERROR
;
}
ret
=
LOS_ArchCopyToUser
(
buf
,
&
seg
->
ds
,
sizeof
(
struct
shmid_ds
));
ret
=
LOS_ArchCopyToUser
(
buf
,
&
seg
->
ds
,
sizeof
(
struct
shmid_ds
));
//把内核空间的共享页数据拷贝到用户空间
if
(
ret
!=
0
)
{
ret
=
EFAULT
;
goto
ERROR
;
...
...
@@ -610,13 +620,13 @@ INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
ret
=
(
unsigned
int
)((
unsigned
int
)
seg
->
ds
.
shm_perm
.
seq
<<
16
)
|
(
unsigned
int
)((
unsigned
int
)
shmid
&
0xffff
);
/* 16: use the seq as the upper 16 bits */
}
break
;
case
IPC_SET
:
case
IPC_SET
:
//重置共享段
ret
=
ShmPermCheck
(
seg
,
SHM_M
);
if
(
ret
!=
0
)
{
ret
=
EPERM
;
goto
ERROR
;
}
//从用户空间拷贝数据到内核空间
ret
=
LOS_ArchCopyFromUser
(
&
shm_perm
,
&
buf
->
shm_perm
,
sizeof
(
struct
ipc_perm
));
if
(
ret
!=
0
)
{
ret
=
EFAULT
;
...
...
@@ -625,10 +635,10 @@ INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
seg
->
ds
.
shm_perm
.
uid
=
shm_perm
.
uid
;
seg
->
ds
.
shm_perm
.
gid
=
shm_perm
.
gid
;
seg
->
ds
.
shm_perm
.
mode
=
(
seg
->
ds
.
shm_perm
.
mode
&
~
ACCESSPERMS
)
|
(
shm_perm
.
mode
&
ACCESSPERMS
);
(
shm_perm
.
mode
&
ACCESSPERMS
);
//可访问
seg
->
ds
.
shm_ctime
=
time
(
NULL
);
break
;
case
IPC_RMID
:
case
IPC_RMID
:
//删除共享段
ret
=
ShmPermCheck
(
seg
,
SHM_M
);
if
(
ret
!=
0
)
{
ret
=
EPERM
;
...
...
@@ -636,11 +646,11 @@ INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
}
seg
->
status
|=
SHM_SEG_REMOVE
;
if
(
seg
->
ds
.
shm_nattch
<=
0
)
{
ShmFreeSeg
(
seg
);
if
(
seg
->
ds
.
shm_nattch
<=
0
)
{
//没有任何进程在使用了
ShmFreeSeg
(
seg
);
//释放 归还内存
}
break
;
case
IPC_INFO
:
case
IPC_INFO
:
//把内核空间的共享页数据拷贝到用户空间
ret
=
LOS_ArchCopyToUser
(
buf
,
&
g_shmInfo
,
sizeof
(
struct
shminfo
));
if
(
ret
!=
0
)
{
ret
=
EFAULT
;
...
...
@@ -655,7 +665,7 @@ INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
shmInfo
.
swap_attempts
=
0
;
shmInfo
.
swap_successes
=
0
;
shmInfo
.
used_ids
=
ShmSegUsedCount
();
ret
=
LOS_ArchCopyToUser
(
buf
,
&
shmInfo
,
sizeof
(
struct
shm_info
));
ret
=
LOS_ArchCopyToUser
(
buf
,
&
shmInfo
,
sizeof
(
struct
shm_info
));
//把内核空间的共享页数据拷贝到用户空间
if
(
ret
!=
0
)
{
ret
=
EFAULT
;
goto
ERROR
;
...
...
@@ -677,56 +687,60 @@ ERROR:
PRINT_DEBUG
(
"%s %d, ret = %d
\n
"
,
__FUNCTION__
,
__LINE__
,
ret
);
return
-
1
;
}
/* 当对共享存储的操作已经结束时,则调用shmdt与该存储段分离
如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值减1
注意:这并不从系统中删除共享存储的标识符以及其相关的数据结构。共享存储的仍然存在,
直至某个进程带IPC_RMID命令的调用shmctl特地删除共享存储为止
*/
INT32
ShmDt
(
const
VOID
*
shmaddr
)
{
LosVmSpace
*
space
=
OsCurrProcessGet
()
->
vmSpace
;
LosVmSpace
*
space
=
OsCurrProcessGet
()
->
vmSpace
;
//获取进程空间
struct
shmIDSource
*
seg
=
NULL
;
LosVmMapRegion
*
region
=
NULL
;
INT32
shmid
;
INT32
ret
;
if
(
IS_PAGE_ALIGNED
(
shmaddr
)
==
0
)
{
if
(
IS_PAGE_ALIGNED
(
shmaddr
)
==
0
)
{
//地址是否对齐
ret
=
EINVAL
;
goto
ERROR
;
}
(
VOID
)
LOS_MuxAcquire
(
&
space
->
regionMux
);
region
=
LOS_RegionFind
(
space
,
(
VADDR_T
)(
UINTPTR
)
shmaddr
);
region
=
LOS_RegionFind
(
space
,
(
VADDR_T
)(
UINTPTR
)
shmaddr
);
//找到线性区
if
(
region
==
NULL
)
{
ret
=
EINVAL
;
goto
ERROR_WITH_LOCK
;
}
shmid
=
region
->
shmid
;
shmid
=
region
->
shmid
;
//线性区共享ID
if
(
region
->
range
.
base
!=
(
VADDR_T
)(
UINTPTR
)
shmaddr
)
{
ret
=
EINVAL
;
if
(
region
->
range
.
base
!=
(
VADDR_T
)(
UINTPTR
)
shmaddr
)
{
//这是用户空间和内核空间的一次解绑
ret
=
EINVAL
;
//shmaddr 必须要等于region->range.base
goto
ERROR_WITH_LOCK
;
}
/* remove it from aspace */
LOS_RbDelNode
(
&
space
->
regionRbTree
,
&
region
->
rbNode
);
LOS_ArchMmuUnmap
(
&
space
->
archMmu
,
region
->
range
.
base
,
region
->
range
.
size
>>
PAGE_SHIFT
);
LOS_RbDelNode
(
&
space
->
regionRbTree
,
&
region
->
rbNode
);
//从红黑树和链表中摘除节点
LOS_ArchMmuUnmap
(
&
space
->
archMmu
,
region
->
range
.
base
,
region
->
range
.
size
>>
PAGE_SHIFT
);
//解除线性区的映射
/* free it */
free
(
region
);
free
(
region
);
//规划线性区所占内存池中的内存
SYSV_SHM_LOCK
();
seg
=
ShmFindSeg
(
shmid
);
seg
=
ShmFindSeg
(
shmid
);
//找到seg,线性区和共享段的关系是 1:N 的关系,其他空间的线性区也会绑在共享段上
if
(
seg
==
NULL
)
{
ret
=
EINVAL
;
SYSV_SHM_UNLOCK
();
goto
ERROR_WITH_LOCK
;
}
ShmPagesRefDec
(
seg
);
seg
->
ds
.
shm_nattch
--
;
if
((
seg
->
ds
.
shm_nattch
<=
0
)
&&
(
seg
->
status
&
SHM_SEG_REMOVE
))
{
ShmFreeSeg
(
seg
);
ShmPagesRefDec
(
seg
);
//页面引用数 --
seg
->
ds
.
shm_nattch
--
;
//使用共享内存的进程数少了一个
if
((
seg
->
ds
.
shm_nattch
<=
0
)
&&
//无任何进程使用共享内存
(
seg
->
status
&
SHM_SEG_REMOVE
))
{
//状态为删除时需要释放 物理页内存了,否则其他进程还要继续使用共享内存
ShmFreeSeg
(
seg
);
//释放seg 页框链表中的页框内存,再重置seg状态
}
seg
->
ds
.
shm_dtime
=
time
(
NULL
);
seg
->
ds
.
shm_lpid
=
LOS_GetCurrProcessID
();
seg
->
ds
.
shm_lpid
=
LOS_GetCurrProcessID
();
//获取当前进程ID
SYSV_SHM_UNLOCK
();
(
VOID
)
LOS_MuxRelease
(
&
space
->
regionMux
);
return
0
;
...
...
www
/git/pull.sh
→
zzz
/git/pull.sh
浏览文件 @
2f73237a
文件已移动
www
/git/push.sh
→
zzz
/git/push.sh
浏览文件 @
2f73237a
文件已移动
www
/test/gcc.sh
→
zzz
/test/gcc.sh
浏览文件 @
2f73237a
文件已移动
www
/test/main.c
→
zzz
/test/main.c
浏览文件 @
2f73237a
文件已移动
www
/test/main.exe
→
zzz
/test/main.exe
浏览文件 @
2f73237a
文件已移动
www
/test/main.s
→
zzz
/test/main.s
浏览文件 @
2f73237a
文件已移动
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录