v45.01 (fork篇) | fork是如何做到调用一次,返回两次的 ?

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    https://my.oschina.net/weharmony
上级 5d366c68
此差异已折叠。
......@@ -125,7 +125,7 @@ LITE_OS_SEC_TEXT VOID OsUserCloneParentStack(LosTaskCB *childTaskCB, LosTaskCB *
LOS_ASSERT(parentTaskCB->taskStatus & OS_TASK_STATUS_RUNNING);//当前任务一定是正在运行的task
(VOID)memcpy_s(childTaskCB->stackPointer, sizeof(TaskContext), cloneStack, sizeof(TaskContext));//直接把任务上下文拷贝了一份
context->R[0] = 0;//R0寄存器为0
context->R[0] = 0;//R0寄存器为0,这个很重要, pid = fork() pid == 0 是子进程返回.
}
//用户态运行栈初始化
LITE_OS_SEC_TEXT_INIT VOID OsUserTaskStackInit(TaskContext *context, TSK_ENTRY_FUNC taskEntry, UINTPTR stack)
......
......@@ -300,10 +300,10 @@ STATIC BOOL OsWaitWakeSpecifiedProcess(LOS_DL_LIST *head, const LosProcessCB *pr
return find;
}
//检查父进程的等待任务并唤醒任务
//检查父进程的等待任务并唤醒父进程
STATIC VOID OsWaitCheckAndWakeParentProcess(LosProcessCB *parentCB, const LosProcessCB *processCB)
{
LOS_DL_LIST *head = &parentCB->waitList;
LOS_DL_LIST *head = &parentCB->waitList;//
LOS_DL_LIST *list = NULL;
LosTaskCB *taskCB = NULL;
BOOL findSpecified = FALSE;
......@@ -483,13 +483,13 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
/* is a child process */
if (processCB->parentProcessID != OS_INVALID_VALUE) {//判断是否有父进程
parentCB = OS_PCB_FROM_PID(processCB->parentProcessID);//获取父进程实体
LOS_ListDelete(&processCB->siblingList);//将自己从兄弟链表中摘除,家人们,永别了!
LOS_ListDelete(&processCB->siblingList);//将自己从兄弟链表中摘除,家人们,永别了!
if (!OsProcessExitCodeSignalIsSet(processCB)) {//是否设置了退出码?
OsProcessExitCodeSet(processCB, status);//将进程状态设为退出码
}
LOS_ListTailInsert(&parentCB->exitChildList, &processCB->siblingList);//挂到父进程的孩子消亡链表,家人中,永别的可不止我一个.
LOS_ListDelete(&processCB->subordinateGroupList);//和志同道合的朋友们永别了,注意家里可不一定是朋友的,所有各有链表.
LOS_ListTailInsert(&processCB->group->exitProcessList, &processCB->subordinateGroupList);//挂到进程组消亡链表,朋友中,永的可不止我一个.
LOS_ListTailInsert(&processCB->group->exitProcessList, &processCB->subordinateGroupList);//挂到进程组消亡链表,朋友中,永的可不止我一个.
OsWaitCheckAndWakeParentProcess(parentCB, processCB);//检查父进程的等待任务并唤醒任务,此处将会切换到其他任务运行.
......@@ -1139,7 +1139,7 @@ LITE_OS_SEC_TEXT VOID OsWaitSignalToWakeProcess(LosProcessCB *processCB)
return;
}
//将任务插入waitList链表
STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *processCB)
{
LOS_DL_LIST *head = &processCB->waitList;
......@@ -1184,7 +1184,7 @@ STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcess
LosTaskCB *runTask = OsCurrTaskGet();
UINT32 ret;
if (pid > 0) {//等待进程号为pid的子进程
if (pid > 0) {//等待进程号为pid的子进程,回收指定pid的子进程
/* Wait for the child process whose process number is pid. */
childCB = OsFindExitChildProcess(processCB, pid);
if (childCB != NULL) {
......@@ -1205,7 +1205,7 @@ STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcess
}
runTask->waitID = processCB->group->groupID;
runTask->waitFlag = OS_PROCESS_WAIT_GID;
} else if (pid == -1) {
} else if (pid == -1) {//回收任意子进程(相当于wait)
/* Wait for any child process */
childCB = OsFindExitChildProcess(processCB, OS_INVALID_VALUE);
if (childCB != NULL) {
......@@ -1213,7 +1213,7 @@ STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcess
}
runTask->waitID = pid;
runTask->waitFlag = OS_PROCESS_WAIT_ANY;
} else { /* pid < -1 */
} else { /* pid < -1 */ //回收指定进程组内为|pid|的所有子进程
/* Wait for any child process whose group number is the pid absolute value. */
group = OsFindProcessGroup(-pid);
if (group == NULL) {
......@@ -1255,7 +1255,7 @@ STATIC INT32 OsWaitRecycleChildPorcess(const LosProcessCB *childCB, UINT32 intSa
(VOID)LOS_MemFree(m_aucSysMem1, group);
return pid;
}
//检查要等待的孩子进程
STATIC INT32 OsWaitChildProcessCheck(LosProcessCB *processCB, INT32 pid, LosProcessCB **childCB)
{
if (LOS_ListEmpty(&(processCB->childrenList)) && LOS_ListEmpty(&(processCB->exitChildList))) {
......@@ -1271,20 +1271,20 @@ STATIC UINT32 OsWaitOptionsCheck(UINT32 options)
flag = ~flag & options;
if (flag != 0) {
return LOS_EINVAL;
return LOS_EINVAL;//无效参数
}
if ((options & (LOS_WAIT_WCONTINUED | LOS_WAIT_WUNTRACED)) != 0) {
return LOS_EOPNOTSUPP;
return LOS_EOPNOTSUPP;//不支持
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
if (OS_INT_ACTIVE) {//中断发生期间
return LOS_EINTR;//中断提示
}
return LOS_OK;
}
//阻塞参数进程
//返回已经终止的子进程的进程ID号,并清除僵死进程。
LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage)
{
(VOID)rusage;
......@@ -1294,14 +1294,14 @@ LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, V
LosProcessCB *processCB = NULL;
LosTaskCB *runTask = NULL;
ret = OsWaitOptionsCheck(options);
ret = OsWaitOptionsCheck(options);//参数检查 只支持 LOS_WAIT_WNOHANG | LOS_WAIT_WUNTRACED
if (ret != LOS_OK) {
return -ret;
}
SCHEDULER_LOCK(intSave);
processCB = OsCurrProcessGet();
runTask = OsCurrTaskGet();
processCB = OsCurrProcessGet(); //获取当前进程
runTask = OsCurrTaskGet(); //获取当前任务
ret = OsWaitChildProcessCheck(processCB, pid, &childCB);
if (ret != LOS_OK) {
......@@ -1691,20 +1691,20 @@ STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name,
SCHEDULER_LOCK(intSave);
mainThread = OsCurrTaskGet();//获取当前task,注意变量名从这里也可以看出 thread 和 task 是一个概念,只是内核常说task,上层应用说thread ,概念的映射.
if (OsProcessIsUserMode(childProcessCB)) {//用户模式进程
childPara->pfnTaskEntry = mainThread->taskEntry;
childPara->uwStackSize = mainThread->stackSize;
childPara->userParam.userArea = mainThread->userArea;
childPara->userParam.userMapBase = mainThread->userMapBase;
childPara->userParam.userMapSize = mainThread->userMapSize;
if (OsProcessIsUserMode(childProcessCB)) {//用户进程
childPara->pfnTaskEntry = mainThread->taskEntry;//拷贝当前任务入口地址
childPara->uwStackSize = mainThread->stackSize; //栈空间大小
childPara->userParam.userArea = mainThread->userArea; //用户态栈区栈顶位置
childPara->userParam.userMapBase = mainThread->userMapBase; //用户态栈底
childPara->userParam.userMapSize = mainThread->userMapSize; //用户态栈大小
} else {
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
childPara->uwStackSize = size;
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;//参数(sp)为内核态入口地址
childPara->uwStackSize = size;//参数(size)为内核态栈大小
}
childPara->pcName = (CHAR *)name;
childPara->policy = mainThread->policy;
childPara->usTaskPrio = mainThread->priority;
childPara->processID = childProcessCB->processID;
childPara->pcName = (CHAR *)name; //拷贝进程名字
childPara->policy = mainThread->policy; //拷贝调度模式
childPara->usTaskPrio = mainThread->priority; //拷贝优先级
childPara->processID = childProcessCB->processID; //拷贝进程ID
if (mainThread->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
childPara->uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
} else if (mainThread->taskStatus & OS_TASK_FLAG_DETACHED) {
......@@ -1746,10 +1746,10 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
if (OsProcessIsUserMode(childProcessCB)) {//是否是用户进程
SCHEDULER_LOCK(intSave);
OsUserCloneParentStack(childTaskCB, OsCurrTaskGet());//任务栈拷贝
OsUserCloneParentStack(childTaskCB, OsCurrTaskGet());//拷贝当前任务上下文给新的任务
SCHEDULER_UNLOCK(intSave);
}
OS_TASK_PRI_QUEUE_ENQUEUE(childProcessCB, childTaskCB);//将task加入进程的就绪队列
OS_TASK_PRI_QUEUE_ENQUEUE(childProcessCB, childTaskCB);//将task加入进程的就绪队列
childTaskCB->taskStatus |= OS_TASK_STATUS_READY;//任务状态贴上就绪标签
return LOS_OK;
}
......
......@@ -102,8 +102,8 @@ typedef struct ProcessCB {
priority hash table */ //进程的线程组调度优先级哈希表
volatile UINT32 threadNumber; /**< Number of threads alive under this process */ //此进程下的活动线程数
UINT32 threadCount; /**< Total number of threads created under this process */ //在此进程下创建的线程总数
LOS_DL_LIST waitList; /**< The process holds the waitLits to support wait/waitpid *///进程持有等待链表以支持wait/waitpid
#if (LOSCFG_KERNEL_SMP == YES)
LOS_DL_LIST waitList; /**< The process holds the waitLits to support wait/waitpid *///父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 timerCpu; /**< CPU core number of this task is delayed or pended *///统计各线程被延期或阻塞的时间
#endif
UINTPTR sigHandler; /**< signal handler */ //信号处理函数,处理如 SIGSYS 等信号
......@@ -130,15 +130,16 @@ typedef struct ProcessCB {
mode_t umask;
} LosProcessCB;
#define CLONE_VM 0x00000100
#define CLONE_FS 0x00000200
#define CLONE_FILES 0x00000400
#define CLONE_SIGHAND 0x00000800
#define CLONE_PTRACE 0x00002000
#define CLONE_VFORK 0x00004000
#define CLONE_PARENT 0x00008000
#define CLONE_THREAD 0x00010000
#define CLONE_VM 0x00000100 //子进程与父进程运行于相同的内存空间
#define CLONE_FS 0x00000200 //子进程与父进程共享相同的文件系统,包括root、当前目录、umask
#define CLONE_FILES 0x00000400 //子进程与父进程共享相同的文件描述符(file descriptor)表
#define CLONE_SIGHAND 0x00000800 //子进程与父进程共享相同的信号处理(signal handler)表
#define CLONE_PTRACE 0x00002000 //若父进程被trace,子进程也被trace
#define CLONE_VFORK 0x00004000 //父进程被挂起,直至子进程释放虚拟内存资源
#define CLONE_PARENT 0x00008000 //创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子”
#define CLONE_THREAD 0x00010000 //Linux 2.4中增加以支持POSIX线程标准,子进程与父进程共享相同的线程群
//CLONE_NEWNS 在新的namespace启动子进程,namespace描述了进程的文件hierarchy
//CLONE_PID 子进程在创建时PID与父进程一致
#define OS_PCB_FROM_PID(processID) (((LosProcessCB *)g_processCBArray) + (processID))//通过数组找到LosProcessCB
#define OS_PCB_FROM_SIBLIST(ptr) LOS_DL_LIST_ENTRY((ptr), LosProcessCB, siblingList)//通过siblingList节点找到 LosProcessCB
#define OS_PCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY((ptr), LosProcessCB, pendList) //通过pendlist节点找到 LosProcessCB
......@@ -425,38 +426,38 @@ STATIC INLINE User *OsCurrUserGet(VOID)//获取当前进程的所属用户
/*
* return immediately if no child has exited.
*/
#define LOS_WAIT_WNOHANG (1 << 0U)
#define LOS_WAIT_WNOHANG (1 << 0U) //如果没有孩子退出,请立即返回 no hang
/*
* return if a child has stopped (but not traced via ptrace(2)).
* Status for traced children which have stopped is provided even
* if this option is not specified.
*/
#define LOS_WAIT_WUNTRACED (1 << 1U)
#define LOS_WAIT_WUNTRACED (1 << 1U) //如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。untraced
/*
* return if a stopped child has been resumed by delivery of SIGCONT.
* (For Linux-only options, see below.)
*/
#define LOS_WAIT_WCONTINUED (1 << 3U)
#define LOS_WAIT_WCONTINUED (1 << 3U) //可获取子进程恢复执行的状态,也就是可获取continued状态 continued
/*
* Indicates that you are already in a wait state
*/
#define OS_PROCESS_WAIT (1 << 15U)
#define OS_PROCESS_WAIT (1 << 15U) //表示已经处于等待状态
/*
* Wait for any child process to finish
*/
#define OS_PROCESS_WAIT_ANY (1 << 0U)
#define OS_PROCESS_WAIT_ANY (1 << 0U) //等待任意子进程完成
/*
* Wait for the child process specified by the pid to finish
*/
#define OS_PROCESS_WAIT_PRO (1 << 1U)
#define OS_PROCESS_WAIT_PRO (1 << 1U) //等待pid指定的子进程完成
/*
* Waits for any child process in the specified process group to finish.
* Waits for any child process in the specified process group to finish. //等待指定进程组中的任何子进程完成
*/
#define OS_PROCESS_WAIT_GID (1 << 2U)
......
......@@ -315,7 +315,7 @@ int SysWait(int pid, USER int *status, int options, void *rusage)
return LOS_Wait(pid, status, (unsigned int)options, NULL);
}
//系统调用之fork ,建议去 https://gitee.com/weharmony/kernel_liteos_a_note fork 一下? :P
int SysFork(void)
{
return OsClone(CLONE_SIGHAND, 0, 0);
......@@ -890,7 +890,7 @@ OUT:
//系统调用之获取线程的用户态区域
char *SysGetThreadArea(void)
{
return (char *)(OsCurrTaskGet()->userArea);//直接返回使用区域
return (char *)(OsCurrTaskGet()->userArea);//直接返回用户区域
}
//系统调用之设置任务为分离模式
int SysUserThreadSetDeatch(unsigned int taskID)
......
git add -A
git commit -m '进程的自然消亡过程注解
git commit -m 'v45.01 (fork篇) | fork是如何做到调用一次,返回两次的 ?
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://my.oschina.net/weharmony
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册