Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
kernel_liteos_a_note
提交
3231b208
kernel_liteos_a_note
项目概览
李少辉-开发者
/
kernel_liteos_a_note
与 Fork 源项目一致
Fork自
鸿蒙内核源码分析 / 注释鸿蒙内核源码
通知
6
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
kernel_liteos_a_note
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
3231b208
编写于
10月 23, 2020
作者:
鸿蒙内核源码分析
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
鸿蒙源码分析系列篇
https://blog.csdn.net/kuangyufei
https://my.oschina.net/u/3751245
上级
d393a8b2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
69 addition
and
114 deletion
+69
-114
README.md
README.md
+3
-3
kernel/base/core/los_process.c
kernel/base/core/los_process.c
+21
-21
kernel/base/core/los_task.c
kernel/base/core/los_task.c
+22
-22
kernel/base/sched/sched_sq/los_sched.c
kernel/base/sched/sched_sq/los_sched.c
+22
-22
kernel/include/los_task.h
kernel/include/los_task.h
+1
-1
zzz/test/mux.c
zzz/test/mux.c
+0
-45
未找到文件。
README.md
浏览文件 @
3231b208
...
...
@@ -11,15 +11,15 @@
*
###
**致敬鸿蒙内核开发者**
感谢开放原子开源基金会,鸿蒙内核开发者提供了如此优秀的源码,让笔者一了多年的夙愿,津津乐道
与此.越深入精读内核源码,越能感受到设计者的精巧用心,创新突破. 向开发者致敬ppp. 可以毫不夸张的说 kernel_liteos_a 可作为大学C语言,数据结构,操作系统,汇编语言 四门课程的教学项目.如此宝库,不深入研究真会觉得
太可惜了.
感谢开放原子开源基金会,鸿蒙内核开发者提供了如此优秀的源码,让笔者一了多年的夙愿,津津乐道
于此.越深入精读内核源码,越能感受到设计者的精巧用心,创新突破. 向开发者致敬ppp. 可以毫不夸张的说 kernel_liteos_a 可作为大学C语言,数据结构,操作系统,汇编语言 四门课程的教学项目.如此宝库,不深入研究实在是
太可惜了.
*
###
**系列篇和源码注释怎么更新**
好记性不如烂笔头,笔者把研究过程心得写成鸿蒙源码分析系列篇,如此源码注释结合系列篇文章理解鸿蒙内核实现会更彻底.
系列篇文章查看: 进入>> 鸿蒙源码分析系列篇 [CSDN站](https://blog.csdn.net/kuangyufei) | [
oschina站](https://my.oschina.net/u/3751245) 查看, 正在持续更新中..., 感谢CSDN, oschina
对博文的推荐.
系列篇文章查看: 进入>> 鸿蒙源码分析系列篇 [CSDN站](https://blog.csdn.net/kuangyufei) | [
OSCHINA站](https://my.oschina.net/u/3751245) 查看, 正在持续更新中..., 感谢CSDN, OSCHINA
对博文的推荐.
注释中文版查看: 进入>> 鸿蒙内核源码注释中文版 [CSDN仓库](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [Gitee仓库 ](https://gitee.com/weharmony/kernel_liteos_a_note) | [Github仓库](https://github.com/kuangyufei/kernel_liteos_a_note)
查看,三
大仓库同步更新. 正在持续加注中....
注释中文版查看: 进入>> 鸿蒙内核源码注释中文版 [CSDN仓库](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [Gitee仓库 ](https://gitee.com/weharmony/kernel_liteos_a_note) | [Github仓库](https://github.com/kuangyufei/kernel_liteos_a_note)
[coding仓库](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) 查看,四
大仓库同步更新. 正在持续加注中....
精读内核源码当然是件很困难的事,但正因为很难才值得去做! 内心不渴望的永远不可能靠近自己.别再去纠结而没有行动.笔者一直坚信兴趣是最好的老师,加注就是在做自己感兴趣的事, 希望感兴趣的各位能看到.如果能让更多人参与到内核的研究,减少学习的成本,哪怕就节省一天的时间,这么多人能节省多少时间, 这是件多好玩,多有意义的事情啊.
...
...
kernel/base/core/los_process.c
浏览文件 @
3231b208
...
...
@@ -498,66 +498,66 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
LOS_Panic
(
"pid : %u is the root process exit!
\n
"
,
processCB
->
processID
);
return
;
}
LITE_OS_SEC_TEXT_INIT
UINT32
OsProcessInit
(
VOID
)
//进程模块初始化
//进程模块初始化,被编译放在代码段 .init 中
LITE_OS_SEC_TEXT_INIT
UINT32
OsProcessInit
(
VOID
)
{
UINT32
index
;
UINT32
size
;
g_processMaxNum
=
LOSCFG_BASE_CORE_PROCESS_LIMIT
;
//
默认是64个
size
=
g_processMaxNum
*
sizeof
(
LosProcessCB
);
g_processMaxNum
=
LOSCFG_BASE_CORE_PROCESS_LIMIT
;
//
默认支持64个进程
size
=
g_processMaxNum
*
sizeof
(
LosProcessCB
);
//算出总大小
g_processCBArray
=
(
LosProcessCB
*
)
LOS_MemAlloc
(
m_aucSysMem1
,
size
);
// 进程池,占用内核堆
g_processCBArray
=
(
LosProcessCB
*
)
LOS_MemAlloc
(
m_aucSysMem1
,
size
);
// 进程池,占用内核堆
,内存池分配
if
(
g_processCBArray
==
NULL
)
{
return
LOS_NOK
;
}
(
VOID
)
memset_s
(
g_processCBArray
,
size
,
0
,
size
);
//安全方式重置
(
VOID
)
memset_s
(
g_processCBArray
,
size
,
0
,
size
);
//安全方式重置
清0
LOS_ListInit
(
&
g_freeProcess
);
//进程空闲链表初始化,创建一个进程时从g_freeProcess中申请一个进程描述符使用
LOS_ListInit
(
&
g_processRecyleList
);
//进程回收链表初始化,回收完成后进入g_freeProcess等待再次被申请使用
for
(
index
=
0
;
index
<
g_processMaxNum
;
index
++
)
{
for
(
index
=
0
;
index
<
g_processMaxNum
;
index
++
)
{
//进程池循环创建
g_processCBArray
[
index
].
processID
=
index
;
//进程ID[0-g_processMaxNum]赋值
g_processCBArray
[
index
].
processStatus
=
OS_PROCESS_FLAG_UNUSED
;
// 默认都是白纸一张,臣妾干净着呢
LOS_ListTailInsert
(
&
g_freeProcess
,
&
g_processCBArray
[
index
].
pendList
);
// 初始全是可分配进程描述符
}
g_userInitProcess
=
1
;
/* 1: The root process ID of the user-mode process is fixed at 1 */
// ????? 为啥用户模式的根进程 选1 ,内核模式的根进程选2
g_userInitProcess
=
1
;
/* 1: The root process ID of the user-mode process is fixed at 1 */
//用户模式的根进程
LOS_ListDelete
(
&
g_processCBArray
[
g_userInitProcess
].
pendList
);
// 清空g_userInitProcess pend链表
g_kernelInitProcess
=
2
;
/* 2: The root process ID of the kernel-mode process is fixed at 2 */
g_kernelInitProcess
=
2
;
/* 2: The root process ID of the kernel-mode process is fixed at 2 */
//内核模式的根进程
LOS_ListDelete
(
&
g_processCBArray
[
g_kernelInitProcess
].
pendList
);
// 清空g_kernelInitProcess pend链表
return
LOS_OK
;
}
//创建一个名叫"KIdle"的进程,给CPU空闲的时候使用
STATIC
UINT32
OsCreateIdleProcess
(
VOID
)
{
UINT32
ret
;
CHAR
*
idleName
=
"Idle"
;
LosProcessCB
*
idleProcess
=
NULL
;
Percpu
*
perCpu
=
OsPercpuGet
();
UINT32
*
idleTaskID
=
&
perCpu
->
idleTaskID
;
UINT32
*
idleTaskID
=
&
perCpu
->
idleTaskID
;
//得到CPU的idle task
ret
=
OsCreateResourceFreeTask
();
// 创建一个资源回收任务
ret
=
OsCreateResourceFreeTask
();
// 创建一个资源回收任务
,优先级为5 用于回收进程退出时的各种资源
if
(
ret
!=
LOS_OK
)
{
return
ret
;
}
//创建一个名叫"KIdle"的进程,并创建一个idle task,CPU空闲的时候就待在 idle task中等待被唤醒
ret
=
LOS_Fork
(
CLONE_FILES
,
"KIdle"
,
(
TSK_ENTRY_FUNC
)
OsIdleTask
,
LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE
);
if
(
ret
<
0
)
{
return
LOS_NOK
;
}
g_kernelIdleProcess
=
(
UINT32
)
ret
;
g_kernelIdleProcess
=
(
UINT32
)
ret
;
//返回进程ID
idleProcess
=
OS_PCB_FROM_PID
(
g_kernelIdleProcess
);
*
idleTaskID
=
idleProcess
->
threadGroupID
;
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskStatus
|=
OS_TASK_FLAG_SYSTEM_TASK
;
idleProcess
=
OS_PCB_FROM_PID
(
g_kernelIdleProcess
);
//通过ID拿到进程实体
*
idleTaskID
=
idleProcess
->
threadGroupID
;
//绑定CPU的IdleTask,或者说改变CPU现有的idle任务
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskStatus
|=
OS_TASK_FLAG_SYSTEM_TASK
;
//设定Idle task 为一个系统任务
#if (LOSCFG_KERNEL_SMP == YES)
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
cpuAffiMask
=
CPUID_TO_AFFI_MASK
(
ArchCurrCpuid
());
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
cpuAffiMask
=
CPUID_TO_AFFI_MASK
(
ArchCurrCpuid
());
//多核CPU的任务指定,防止乱串了,注意多核才会有并行处理
#endif
(
VOID
)
memset_s
(
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskName
,
OS_TCB_NAME_LEN
,
0
,
OS_TCB_NAME_LEN
);
(
VOID
)
memcpy_s
(
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskName
,
OS_TCB_NAME_LEN
,
idleName
,
strlen
(
idleName
));
(
VOID
)
memset_s
(
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskName
,
OS_TCB_NAME_LEN
,
0
,
OS_TCB_NAME_LEN
);
//task 名字先清0
(
VOID
)
memcpy_s
(
OS_TCB_FROM_TID
(
*
idleTaskID
)
->
taskName
,
OS_TCB_NAME_LEN
,
idleName
,
strlen
(
idleName
));
//task 名字叫 idle
return
LOS_OK
;
}
...
...
kernel/base/core/los_task.c
浏览文件 @
3231b208
...
...
@@ -124,10 +124,10 @@ VOID OsSetMainTask()
LOS_ListInit
(
&
g_mainTask
[
i
].
lockList
);
//初始化 每个CPU core 持有的锁链表
}
}
LITE_OS_SEC_TEXT
WEAK
VOID
OsIdleTask
(
VOID
)
//空任务
//空闲任务 注意 #define WEAK __attribute__((weak)) 是用于防止crash的
LITE_OS_SEC_TEXT
WEAK
VOID
OsIdleTask
(
VOID
)
{
while
(
1
)
{
while
(
1
)
{
//只有一个死循环
#ifdef LOSCFG_KERNEL_TICKLESS
if
(
OsTickIrqFlagGet
())
{
OsTickIrqFlagSet
(
0
);
...
...
@@ -243,7 +243,7 @@ LITE_OS_SEC_TEXT UINT32 OsTaskSetDeatchUnsafe(LosTaskCB *taskCB)
return
LOS_EINVAL
;
}
//任务扫描
LITE_OS_SEC_TEXT
VOID
OsTaskScan
(
VOID
)
{
SortLinkList
*
sortList
=
NULL
;
...
...
@@ -253,7 +253,7 @@ LITE_OS_SEC_TEXT VOID OsTaskScan(VOID)
LOS_DL_LIST
*
listObject
=
NULL
;
SortLinkAttribute
*
taskSortLink
=
NULL
;
taskSortLink
=
&
OsPercpuGet
()
->
taskSortLink
;
taskSortLink
=
&
OsPercpuGet
()
->
taskSortLink
;
//获取任务的排序链表
taskSortLink
->
cursor
=
(
taskSortLink
->
cursor
+
1
)
&
OS_TSK_SORTLINK_MASK
;
listObject
=
taskSortLink
->
sortLink
+
taskSortLink
->
cursor
;
...
...
@@ -841,7 +841,7 @@ LOS_ERREND_REWIND_TCB:
LOS_ERREND:
return
errRet
;
}
//创建Task
LITE_OS_SEC_TEXT_INIT
UINT32
LOS_TaskCreate
(
UINT32
*
taskID
,
TSK_INIT_PARAM_S
*
initParam
)
{
UINT32
ret
;
...
...
@@ -856,35 +856,35 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in
return
LOS_ERRNO_TSK_YIELD_IN_INT
;
}
if
(
initParam
->
uwResved
&
OS_TASK_FLAG_IDLEFLAG
)
{
initParam
->
processID
=
OsGetIdleProcessID
();
}
else
if
(
OsProcessIsUserMode
(
OsCurrProcessGet
()))
{
initParam
->
processID
=
OsGetKernelInitProcessID
();
if
(
initParam
->
uwResved
&
OS_TASK_FLAG_IDLEFLAG
)
{
//OS_TASK_FLAG_IDLEFLAG 是属于内核 idle进程专用的
initParam
->
processID
=
OsGetIdleProcessID
();
//获取空闲进程
}
else
if
(
OsProcessIsUserMode
(
OsCurrProcessGet
()))
{
//当前进程是否为用户模式
initParam
->
processID
=
OsGetKernelInitProcessID
();
//不是就取"Kernel"进程
}
else
{
initParam
->
processID
=
OsCurrProcessGet
()
->
processID
;
initParam
->
processID
=
OsCurrProcessGet
()
->
processID
;
//获取当前进程 ID赋值
}
initParam
->
uwResved
&=
~
OS_TASK_FLAG_IDLEFLAG
;
initParam
->
uwResved
&=
~
OS_TASK_FLAG_PTHREAD_JOIN
;
if
(
initParam
->
uwResved
&
LOS_TASK_STATUS_DETACHED
)
{
initParam
->
uwResved
=
OS_TASK_FLAG_DETACHED
;
initParam
->
uwResved
&=
~
OS_TASK_FLAG_IDLEFLAG
;
//不能是 OS_TASK_FLAG_IDLEFLAG
initParam
->
uwResved
&=
~
OS_TASK_FLAG_PTHREAD_JOIN
;
//不能是 OS_TASK_FLAG_PTHREAD_JOIN
if
(
initParam
->
uwResved
&
LOS_TASK_STATUS_DETACHED
)
{
//是否设置了自动删除
initParam
->
uwResved
=
OS_TASK_FLAG_DETACHED
;
//自动删除,注意这里是 = ,也就是说只有 OS_TASK_FLAG_DETACHED 一个标签了
}
ret
=
LOS_TaskCreateOnly
(
taskID
,
initParam
);
ret
=
LOS_TaskCreateOnly
(
taskID
,
initParam
);
//创建一个任务,这是任务创建的实体,前面都只是前期准备工作
if
(
ret
!=
LOS_OK
)
{
return
ret
;
}
taskCB
=
OS_TCB_FROM_TID
(
*
taskID
);
taskCB
=
OS_TCB_FROM_TID
(
*
taskID
);
//通过ID拿到task实体
SCHEDULER_LOCK
(
intSave
);
taskCB
->
taskStatus
&=
~
OS_TASK_STATUS_INIT
;
OS_TASK_SCHED_QUEUE_ENQUEUE
(
taskCB
,
0
);
taskCB
->
taskStatus
&=
~
OS_TASK_STATUS_INIT
;
//任务不再是初始化
OS_TASK_SCHED_QUEUE_ENQUEUE
(
taskCB
,
0
);
//进入调度就绪队列,新任务是直接进入就绪队列的
SCHEDULER_UNLOCK
(
intSave
);
/* in case created task not running on this core,
schedule or not depends on other schedulers status. */
LOS_MpSchedule
(
OS_MP_CPU_ALL
);
if
(
OS_SCHEDULER_ACTIVE
)
{
LOS_Schedule
();
LOS_MpSchedule
(
OS_MP_CPU_ALL
);
//如果创建的任务没有在这个核心上运行,是否调度取决于其他调度程序的状态。
if
(
OS_SCHEDULER_ACTIVE
)
{
//当前CPU核处于可调度状态
LOS_Schedule
();
//发起调度
}
return
LOS_OK
;
...
...
kernel/base/sched/sched_sq/los_sched.c
浏览文件 @
3231b208
...
...
@@ -82,7 +82,7 @@ STATIC VOID OsSchedSwitchProcess(LosProcessCB *runProcess, LosProcessCB *newProc
newProcess
->
timeSlice
=
OS_PROCESS_SCHED_RR_INTERVAL
;
//重新分配时间片,默认 20ms
}
}
//重新调度实现
VOID
OsSchedResched
(
VOID
)
{
LosTaskCB
*
runTask
=
NULL
;
...
...
@@ -90,50 +90,50 @@ VOID OsSchedResched(VOID)
LosProcessCB
*
runProcess
=
NULL
;
LosProcessCB
*
newProcess
=
NULL
;
LOS_ASSERT
(
LOS_SpinHeld
(
&
g_taskSpin
));
LOS_ASSERT
(
LOS_SpinHeld
(
&
g_taskSpin
));
//必须持有任务自旋锁,自旋锁是不是进程层面去抢锁,而是CPU各自核之间去争夺锁
if
(
!
OsPreemptableInSched
())
{
if
(
!
OsPreemptableInSched
())
{
//是否置了重新调度标识位
return
;
}
runTask
=
OsCurrTaskGet
();
newTask
=
OsGetTopTask
();
runTask
=
OsCurrTaskGet
();
//获取当前任务
newTask
=
OsGetTopTask
();
//获取优先级最最最高的任务
/* always be able to get one task */
LOS_ASSERT
(
newTask
!=
NULL
);
LOS_ASSERT
(
newTask
!=
NULL
);
//不能没有需调度的任务
if
(
runTask
==
newTask
)
{
if
(
runTask
==
newTask
)
{
//当前任务就是最高任务,那还调度个啥的,直接退出.
return
;
}
runTask
->
taskStatus
&=
~
OS_TASK_STATUS_RUNNING
;
newTask
->
taskStatus
|=
OS_TASK_STATUS_RUNNING
;
runTask
->
taskStatus
&=
~
OS_TASK_STATUS_RUNNING
;
//当前任务状态位置成不在运行状态
newTask
->
taskStatus
|=
OS_TASK_STATUS_RUNNING
;
//最高任务状态位置成在运行状态
runProcess
=
OS_PCB_FROM_PID
(
runTask
->
processID
);
newProcess
=
OS_PCB_FROM_PID
(
newTask
->
processID
);
runProcess
=
OS_PCB_FROM_PID
(
runTask
->
processID
);
//通过进程ID索引拿到进程实体
newProcess
=
OS_PCB_FROM_PID
(
newTask
->
processID
);
//同上
OsSchedSwitchProcess
(
runProcess
,
newProcess
);
OsSchedSwitchProcess
(
runProcess
,
newProcess
);
//切换进程,里面主要涉及进程空间的切换,也就是MMU的上下文切换.
#if (LOSCFG_KERNEL_SMP == YES)
#if (LOSCFG_KERNEL_SMP == YES)
//CPU多核的情况
/* mask new running task's owner processor */
runTask
->
currCpu
=
OS_TASK_INVALID_CPUID
;
newTask
->
currCpu
=
ArchCurrCpuid
();
runTask
->
currCpu
=
OS_TASK_INVALID_CPUID
;
//当前任务不占用CPU
newTask
->
currCpu
=
ArchCurrCpuid
();
//让新任务占用CPU
#endif
(
VOID
)
OsTaskSwitchCheck
(
runTask
,
newTask
);
(
VOID
)
OsTaskSwitchCheck
(
runTask
,
newTask
);
//切换task的检查
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
OsSchedStatistics
(
runTask
,
newTask
);
#endif
if
((
newTask
->
timeSlice
==
0
)
&&
(
newTask
->
policy
==
LOS_SCHED_RR
))
{
newTask
->
timeSlice
=
LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
;
if
((
newTask
->
timeSlice
==
0
)
&&
(
newTask
->
policy
==
LOS_SCHED_RR
))
{
//没有时间片且是抢占式调度的方式,注意 非抢占式都不需要时间片的.
newTask
->
timeSlice
=
LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
;
//给新任务时间片 默认 20ms
}
OsCurrTaskSet
((
VOID
*
)
newTask
);
OsCurrTaskSet
((
VOID
*
)
newTask
);
//设置新的task为CPU核的当前任务
if
(
OsProcessIsUserMode
(
newProcess
))
{
OsCurrUserTaskSet
(
newTask
->
userArea
);
if
(
OsProcessIsUserMode
(
newProcess
))
{
//用户模式下会怎么样?
OsCurrUserTaskSet
(
newTask
->
userArea
);
//设置task栈空间
}
PRINT_TRACE
(
"cpu%d run process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x ->
\n
"
...
...
@@ -145,7 +145,7 @@ VOID OsSchedResched(VOID)
newProcess
->
threadScheduleMap
,
newTask
->
taskName
,
newTask
->
taskID
,
newTask
->
taskStatus
);
/* do the task context switch */
OsTaskSchedule
(
newTask
,
runTask
);
OsTaskSchedule
(
newTask
,
runTask
);
//再执行调度,主要是切换CPU的上下文
}
VOID
OsSchedPreempt
(
VOID
)
...
...
kernel/include/los_task.h
浏览文件 @
3231b208
...
...
@@ -491,7 +491,7 @@ typedef struct {
*
* Information of specified parameters passed in during task creation.
*/
typedef
struct
tagTskInitParam
{
typedef
struct
tagTskInitParam
{
//Task的初始化参数
TSK_ENTRY_FUNC
pfnTaskEntry
;
/**< Task entrance function */
UINT16
usTaskPrio
;
/**< Task priority */
UINT16
policy
;
/**< Task policy */
...
...
zzz/test/mux.c
已删除
100644 → 0
浏览文件 @
d393a8b2
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// 打印机
void
printer
(
char
*
str
)
{
while
(
*
str
!=
'\0'
)
{
putchar
(
*
str
);
fflush
(
stdout
);
str
++
;
sleep
(
1
);
}
printf
(
"
\n
"
);
}
// 线程一
void
*
thread_fun_1
(
void
*
arg
)
{
char
*
str
=
"hello"
;
printer
(
str
);
//打印
}
// 线程二
void
*
thread_fun_2
(
void
*
arg
)
{
char
*
str
=
"world"
;
printer
(
str
);
//打印
}
int
main
(
void
)
{
pthread_t
tid1
,
tid2
;
// 创建 2 个线程
pthread_create
(
&
tid1
,
NULL
,
thread_fun_1
,
NULL
);
pthread_create
(
&
tid2
,
NULL
,
thread_fun_2
,
NULL
);
// 等待线程结束,回收其资源
pthread_join
(
tid1
,
NULL
);
pthread_join
(
tid2
,
NULL
);
return
0
;
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录