From 169574a2a7bd690d653e5254e4335c181306c906 Mon Sep 17 00:00:00 2001 From: kuangyufei Date: Wed, 16 Dec 2020 18:33:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A6=82=E4=BD=95=E8=B7=A8CPU=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=BB=BB=E5=8A=A1=3F=E6=B3=A8=E8=A7=A3=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E4=BB=BB=E5=8A=A1=E6=98=AF=E5=A6=82=E4=BD=95=E8=87=AA?= =?UTF-8?q?=E6=9D=80=E5=92=8C=E8=A2=AB=E4=BB=96=E6=9D=80=E7=9A=84.=20?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=20@note=5Fpic=20=E5=8F=AF=E4=BB=A5=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E5=85=A8=E9=83=A8=E5=AD=97=E7=AC=A6=E5=9B=BE=20?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=20@note=5Fwhy=20=E6=98=AF=E6=B3=A8=E8=80=85?= =?UTF-8?q?=E5=B0=9A=E6=9C=AA=E7=9C=8B=E6=98=8E=E7=99=BD=E7=9A=84=E5=9C=B0?= =?UTF-8?q?=E6=96=B9=EF=BC=8C=E5=A6=82=E6=9E=9C=E6=82=A8=E7=9C=8B=E6=98=8E?= =?UTF-8?q?=E7=99=BD=E4=BA=86=EF=BC=8C=E8=AF=B7=E5=91=8A=E8=AF=89=E6=B3=A8?= =?UTF-8?q?=E8=80=85=E5=AE=8C=E5=96=84=20=E6=90=9C=E7=B4=A2=20@note=5Fthin?= =?UTF-8?q?king=20=E6=98=AF=E6=B3=A8=E8=80=85=E7=9A=84=E6=80=9D=E8=80=83?= =?UTF-8?q?=E5=92=8C=E5=90=90=E6=A7=BD=E7=9A=84=E5=9C=B0=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/base/core/los_process.c | 6 +- kernel/base/core/los_task.c | 55 +- kernel/base/include/los_process_pri.h | 2 +- kernel/base/include/los_signal.h | 453 ++++---- kernel/base/include/los_task_pri.h | 16 +- kernel/base/ipc/los_sem.c | 596 +++++------ kernel/base/ipc/los_signal.c | 1396 +++++++++++++------------ kernel/base/misc/kill_shellcmd.c | 202 ++-- security/cap/capability_type.h | 136 +-- syscall/ipc_syscall.c | 599 +++++------ zzz/git/push.sh | 2 +- 11 files changed, 1782 insertions(+), 1681 deletions(-) diff --git a/kernel/base/core/los_process.c b/kernel/base/core/los_process.c index 2c13a784..dd0708b4 100644 --- a/kernel/base/core/los_process.c +++ b/kernel/base/core/los_process.c @@ -67,12 +67,12 @@ extern "C" { //LITE_OS_SEC_BSS 和 LITE_OS_SEC_DATA_INIT 是告诉编译器这些全局变量放在哪个数据段 LITE_OS_SEC_BSS LosProcessCB *g_runProcess[LOSCFG_KERNEL_CORE_NUM];// CPU内核个数,超过一个就实现了并行 LITE_OS_SEC_BSS LosProcessCB *g_processCBArray = NULL; // 进程池数组 -LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_freeProcess;// 空闲状态下的进程链表, .个人觉得应该取名为 g_freeProcessList +LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_freeProcess;// 空闲状态下的进程链表, .个人觉得应该取名为 g_freeProcessList @note_thinking LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_processRecyleList;// 需要回收的进程列表 LITE_OS_SEC_BSS UINT32 g_userInitProcess = OS_INVALID_VALUE;// 用户态的初始init进程,用户态下其他进程由它 fork LITE_OS_SEC_BSS UINT32 g_kernelInitProcess = OS_INVALID_VALUE;// 内核态初始Kprocess进程,内核态下其他进程由它 fork LITE_OS_SEC_BSS UINT32 g_kernelIdleProcess = OS_INVALID_VALUE;// 内核态idle进程,由Kprocess fork -LITE_OS_SEC_BSS UINT32 g_processMaxNum;// 进程最大数量 +LITE_OS_SEC_BSS UINT32 g_processMaxNum;// 进程最大数量,默认64个 LITE_OS_SEC_BSS ProcessGroup *g_processGroup = NULL;// 全局进程组,负责管理所有进程组 //将task从该进程的就绪队列中摘除,如果需要进程也从进程就绪队列中摘除 LITE_OS_SEC_TEXT_INIT VOID OsTaskSchedQueueDequeue(LosTaskCB *taskCB, UINT16 status) @@ -2003,7 +2003,7 @@ LITE_OS_SEC_TEXT VOID OsSetSigHandler(UINTPTR addr) { OsCurrProcessGet()->sigHandler = addr; } -//获取进程的中断处理函数 +//获取进程的信号处理函数 LITE_OS_SEC_TEXT UINTPTR OsGetSigHandler(VOID) { return OsCurrProcessGet()->sigHandler; diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index 3759a753..957c313a 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -569,7 +569,12 @@ STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal) (VOID)syncSignal; #endif } -//同步信号等待 +/****************************************** +等待任务的同步信号, +A --发送syncSignal-- > B +B --回一个syncSignal-- > A +如此A就知道B此时还在 +*******************************************/ LITE_OS_SEC_TEXT UINT32 OsTaskSyncWait(const LosTaskCB *taskCB) { #if (LOSCFG_KERNEL_SMP_TASK_SYNC == YES) @@ -1086,38 +1091,46 @@ LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *taskCB) * 3. Do the deletion in hard-irq * then LOS_TaskDelete will directly return with 'ret' value. */ + /**************************************************************** + 检查是否需要对正在运行的任务执行删除操作,如果需要删除,则返回TRUE。 + 如果满足以下情况,则返回FALSE: + 1.如果启用了SMP,则跨CPU执行删除 + 2.禁用抢占时执行删除 + 3.在硬irq中删除 + 然后LOS_TaskDelete将直接返回ret值 + ****************************************************************/ STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) { /* init default out return value */ *ret = LOS_OK; #if (LOSCFG_KERNEL_SMP == YES) - /* ASYNCHRONIZED. No need to do task lock checking */ - if (taskCB->currCpu != ArchCurrCpuid()) { + /* ASYNCHRONIZED. No need to do task lock checking *///异步操作,不需要进行任务锁检查 + if (taskCB->currCpu != ArchCurrCpuid()) {//任务运行在其他CPU,跨核心执行删除 /* * the task is running on another cpu. * mask the target task with "kill" signal, and trigger mp schedule * which might not be essential but the deletion could more in time. */ - taskCB->signal = SIGNAL_KILL; - LOS_MpSchedule(taskCB->currCpu); - *ret = OsTaskSyncWait(taskCB); + taskCB->signal = SIGNAL_KILL; //贴上干掉标记 + LOS_MpSchedule(taskCB->currCpu);//通知任务所属CPU发生调度 + *ret = OsTaskSyncWait(taskCB); //同步等待可怜的任务被干掉 return FALSE; } #endif - if (!OsPreemptableInSched()) { + if (!OsPreemptableInSched()) {//如果任务正在运行且调度程序已锁定,则无法删除它 /* If the task is running and scheduler is locked then you can not delete it */ *ret = LOS_ERRNO_TSK_DELETE_LOCKED; return FALSE; } - if (OS_INT_ACTIVE) { + if (OS_INT_ACTIVE) {//硬中断进行中...会屏蔽掉所有信号,当然包括kill了 /* * delete running task in interrupt. * mask "kill" signal and later deletion will be handled. */ - taskCB->signal = SIGNAL_KILL; + taskCB->signal = SIGNAL_KILL;//硬中断后将处理删除。 return FALSE; } @@ -1594,13 +1607,17 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID) /* * Description : Process pending signals tagged by others cores - *///处理由其他CPU核标记为挂起信号 + */ + /****************************************************** + 由其他CPU核触发阻塞进程的信号 + 函数由汇编代码调用 ..\arch\arm\arm\src\los_dispatch.S + ******************************************************/ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskProcSignal(VOID) { Percpu *percpu = NULL; LosTaskCB *runTask = NULL; UINT32 intSave, ret; -//私有且不可中断,无需保护。这个任务在其他CPU核看到它时总是在运行,所以它在执行代码的同时也可以继续接收信号 + //私有且不可中断,无需保护。这个任务在其他CPU核看到它时总是在运行,所以它在执行代码的同时也可以继续接收信号 /* * private and uninterruptable, no protection needed. * while this task is always running when others cores see it, @@ -1611,28 +1628,28 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskProcSignal(VOID) goto EXIT; } - if (runTask->signal & SIGNAL_KILL) { + if (runTask->signal & SIGNAL_KILL) {//意思是其他cpu发起了要干掉你的信号 /* * clear the signal, and do the task deletion. if the signaled task has been * scheduled out, then this deletion will wait until next run. - *///清除信号,删除任务。如果发出信号的任务已出调度就绪队列,则此删除将等待下次运行 + *///如果发出信号的任务已出调度就绪队列,则此删除将等待下次运行 SCHEDULER_LOCK(intSave); - runTask->signal = SIGNAL_NONE; - ret = OsTaskDeleteUnsafe(runTask, OS_PRO_EXIT_OK, intSave); + runTask->signal = SIGNAL_NONE;//清除信号, + ret = OsTaskDeleteUnsafe(runTask, OS_PRO_EXIT_OK, intSave);//任务的自杀行动,这可是正在运行的任务. if (ret) { PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret); } - } else if (runTask->signal & SIGNAL_SUSPEND) { - runTask->signal &= ~SIGNAL_SUSPEND; + } else if (runTask->signal & SIGNAL_SUSPEND) {//意思是其他cpu发起了要挂起你的信号 + runTask->signal &= ~SIGNAL_SUSPEND;// /* suspend killed task may fail, ignore the result */ (VOID)LOS_TaskSuspend(runTask->taskID); #if (LOSCFG_KERNEL_SMP == YES) - } else if (runTask->signal & SIGNAL_AFFI) { + } else if (runTask->signal & SIGNAL_AFFI) {//意思是下次调度其他cpu要媾和你 runTask->signal &= ~SIGNAL_AFFI; /* pri-queue has updated, notify the target cpu */ - LOS_MpSchedule((UINT32)runTask->cpuAffiMask); + LOS_MpSchedule((UINT32)runTask->cpuAffiMask);//任务队列已更新,通知目标cpu #endif } diff --git a/kernel/base/include/los_process_pri.h b/kernel/base/include/los_process_pri.h index fc7553bf..b8cbd7bb 100644 --- a/kernel/base/include/los_process_pri.h +++ b/kernel/base/include/los_process_pri.h @@ -106,7 +106,7 @@ typedef struct ProcessCB { #if (LOSCFG_KERNEL_SMP == YES) UINT32 timerCpu; /**< CPU core number of this task is delayed or pended *///统计各线程被延期或阻塞的时间 #endif - UINTPTR sigHandler; /**< signal handler */ //信号处理函数 + UINTPTR sigHandler; /**< signal handler */ //信号处理函数,处理如 SIGSYS 等信号 sigset_t sigShare; /**< signal share bit */ //信号共享位 #if (LOSCFG_KERNEL_LITEIPC == YES) ProcIpcInfo ipcInfo; /**< memory pool for lite ipc */ //用于进程间通讯的 内存文件系统,设备装载点为 /dev/litepc diff --git a/kernel/base/include/los_signal.h b/kernel/base/include/los_signal.h index d0160b23..62c0b437 100644 --- a/kernel/base/include/los_signal.h +++ b/kernel/base/include/los_signal.h @@ -1,203 +1,250 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _LOS_SIGNAL_H -#define _LOS_SIGNAL_H - -#include -#include -#include -#include -#include "los_event.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#define LOS_BIT_SET(val, bit) ((val) = (val) | (1ULL << (UINT32)(bit))) -#define LOS_BIT_CLR(val, bit) ((val) = (val) & ~(1ULL << (UINT32)(bit))) -#define LOS_IS_BIT_SET(val, bit) (bool)((((val) >> (UINT32)(bit)) & 1ULL)) - -#define OS_SYSCALL_SET_CPSR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs) - 4)) = (cpsr)) -#define OS_SYSCALL_SET_SR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs))) = (cpsr)) -#define OS_SYSCALL_GET_CPSR(regs) (*((unsigned long *)((UINTPTR)(regs) - 4))) -#define SIG_STOP_VISIT 1 - -#define OS_KERNEL_KILL_PERMISSION 0U //内核级 kill 权限 -#define OS_USER_KILL_PERMISSION 3U //用户级 kill 权限 - -#define OS_RETURN_IF(expr, errcode) \ - if ((expr)) { \ - return errcode; \ - } - -#define OS_RETURN_IF_VOID(expr) \ - if ((expr)) { \ - return; \ - } -#define OS_GOTO_EXIT_IF(expr, errcode) \ - if (expr) { \ - ret = errcode; \ - goto EXIT; \ - } -#define OS_GOTO_EXIT_IF_ONLY(expr) \ - if (expr) { \ - goto EXIT; \ - } - -#define OS_RETURN_VOID_IF_NULL(pPara) \ - if (NULL == (pPara)) { \ - return; \ - } -#define OS_RETURN_IF_NULL(pPara) \ - if (NULL == (pPara)) { \ - return (-EINVAL); \ - } - -#define OS_GOTO_EXIT_IF_NULL(pPara) \ - if (NULL == (pPara)) { \ - ret = -EINVAL; \ - goto EXIT; \ - } - -typedef void (*sa_sighandler_t)(int); -typedef void (*sa_siginfoaction_t)(int, siginfo_t *, void *); - -#define SIGNO2SET(s) ((sigset_t)1ULL << (s)) -#define NULL_SIGNAL_SET ((sigset_t)0ULL) //设置成没有信号 -#define FULL_SIGNAL_SET ((sigset_t)~0ULL) //设置成满格信号 - -static inline int GOOD_SIGNO(unsigned int sig) -{ - return (sig < _NSIG) ? 1 : 0; -} -/******************************************************************** -Musl官网 http://musl.libc.org/ -musl是构建在Linux系统调用API之上的C标准库的实现,包括在基本语言标准POSIX中定义的接口, -以及广泛认可的扩展。musl是轻量级的,快速的,简单的,自由的. -********************************************************************/ - -#define MAX_SIG_ARRAY_IN_MUSL 128 - -typedef struct { - unsigned long sig[MAX_SIG_ARRAY_IN_MUSL / sizeof(unsigned long)]; -} sigset_t_l; - -typedef struct sigaction sigaction_t; - -struct sigactq { - struct sigactq *flink; /* Forward link */ - sigaction_t act; /* Sigaction data */ - uint8_t signo; /* Signal associated with action */ -}; -typedef struct sigactq sigactq_t; - -struct sq_entry_s { - struct sq_entry_s *flink; -}; -typedef struct sq_entry_s sq_entry_t; - -struct sigpendq { - struct sigpendq *flink; /* Forward link */ - siginfo_t info; /* Signal information */ - uint8_t type; /* (Used to manage allocations) */ -}; -typedef struct sigpendq sigpendq_t; - -struct sq_queue_s { - sq_entry_t *head; - sq_entry_t *tail; -}; -typedef struct sq_queue_s sq_queue_t; - -#define TASK_IRQ_CONTEXT \ - unsigned int R0; \ - unsigned int R1; \ - unsigned int R2; \ - unsigned int R3; \ - unsigned int R12; \ - unsigned int USP; \ - unsigned int ULR; \ - unsigned int CPSR; \ - unsigned int PC; - -typedef struct { - TASK_IRQ_CONTEXT -} TaskIrqDataSize; - -typedef struct { - TASK_IRQ_CONTEXT - unsigned int R7; - unsigned int count; -} sig_switch_context; - -typedef struct {//信号控制块(描述符) - sigset_t sigFlag; - sigset_t sigPendFlag; - sigset_t sigprocmask; /* Signals that are blocked */ //信号屏蔽 - sq_queue_t sigactionq; - LOS_DL_LIST waitList; //等待链表 - sigset_t sigwaitmask; /* Waiting for pending signals */ //等待挂起的信号 - siginfo_t sigunbinfo; /* Signal info when task unblocked */ //任务解除阻止时的信号信息 - sig_switch_context context; -} sig_cb; - -#define SIGEV_THREAD_ID 4 - -int sys_sigqueue(pid_t, int, const union sigval); -int sys_sigpending(sigset_t *); -int sys_rt_sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *ts, size_t sigsetsize); -int sys_sigsuspend(const sigset_t *); -int OsKillLock(pid_t pid, int sig); -int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact); -int OsSigprocMask(int how, const sigset_t_l *set, sigset_t_l *oldset); -int OsPthreadKill(UINT32 tid, int signo); -int OsSigEmptySet(sigset_t *); -int OsSigAddSet(sigset_t *, int); -int OsSigIsMember(const sigset_t *, int); -void OsSaveSignalContext(unsigned int *sp); -void OsRestorSignalContext(unsigned int *sp); -int OsKill(pid_t pid, int sig, int permission); -int OsDispatch(pid_t pid, siginfo_t *info, int permission); -int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout); -int OsPause(void); -int OsSigPending(sigset_t *set); -int OsSigSuspend(const sigset_t *set); - -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#endif /* _LOS_SIGNAL_H */ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOS_SIGNAL_H +#define _LOS_SIGNAL_H + +#include +#include +#include +#include +#include "los_event.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ +/******************************************** +https://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html +信号本质:用于进程之间的异步通信 +软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟, +在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中唯一 +的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。 +进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程 +发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息。 + +信号量定义如下: 见于..\third_party\musl\arch\aarch64\bits\signal.h +#define SIGHUP 1 //终端挂起或者控制进程终止 +#define SIGINT 2 //键盘中断(如break键被按下) +#define SIGQUIT 3 //键盘的退出键被按下 +#define SIGILL 4 //非法指令 +#define SIGTRAP 5 //跟踪陷阱(trace trap),启动进程,跟踪代码的执行 +#define SIGABRT 6 //由abort(3)发出的退出指令 +#define SIGIOT SIGABRT +#define SIGBUS 7 //总线错误 +#define SIGFPE 8 //浮点异常 +#define SIGKILL 9 //常用的命令 kill 9 123 +#define SIGUSR1 10 //用户自定义信号1 +#define SIGSEGV 11 //无效的内存引用, 段违例(segmentation violation),进程试图去访问其虚地址空间以外的位置 +#define SIGUSR2 12 //用户自定义信号2 +#define SIGPIPE 13 //向某个非读管道中写入数据 +#define SIGALRM 14 //由alarm(2)发出的信号,默认行为为进程终止 +#define SIGTERM 15 //软件终止(software termination) +#define SIGSTKFLT 16 +#define SIGCHLD 17 //子进程结束信号 +#define SIGCONT 18 //进程继续(曾被停止的进程) +#define SIGSTOP 19 //终止进程 +#define SIGTSTP 20 //控制终端(tty)上 按下停止键 +#define SIGTTIN 21 //后台进程企图从控制终端读 +#define SIGTTOU 22 //后台进程企图从控制终端写 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL 29 +#define SIGPWR 30 //电源故障 +#define SIGSYS 31 //系统调用中参数错,如系统调用号非法 +#define SIGUNUSED SIGSYS + +#define _NSIG 65 //信号范围,不超过_NSIG +********************************************/ + +#define LOS_BIT_SET(val, bit) ((val) = (val) | (1ULL << (UINT32)(bit))) //按位设置 +#define LOS_BIT_CLR(val, bit) ((val) = (val) & ~(1ULL << (UINT32)(bit))) //按位清除 +#define LOS_IS_BIT_SET(val, bit) (bool)((((val) >> (UINT32)(bit)) & 1ULL)) //位是否设置为1 + +#define OS_SYSCALL_SET_CPSR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs) - 4)) = (cpsr)) +#define OS_SYSCALL_SET_SR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs))) = (cpsr)) +#define OS_SYSCALL_GET_CPSR(regs) (*((unsigned long *)((UINTPTR)(regs) - 4))) +#define SIG_STOP_VISIT 1 + +#define OS_KERNEL_KILL_PERMISSION 0U //内核级 kill 权限 +#define OS_USER_KILL_PERMISSION 3U //用户级 kill 权限 + +#define OS_RETURN_IF(expr, errcode) \ + if ((expr)) { \ + return errcode; \ + } + +#define OS_RETURN_IF_VOID(expr) \ + if ((expr)) { \ + return; \ + } +#define OS_GOTO_EXIT_IF(expr, errcode) \ + if (expr) { \ + ret = errcode; \ + goto EXIT; \ + } +#define OS_GOTO_EXIT_IF_ONLY(expr) \ + if (expr) { \ + goto EXIT; \ + } + +#define OS_RETURN_VOID_IF_NULL(pPara) \ + if (NULL == (pPara)) { \ + return; \ + } +#define OS_RETURN_IF_NULL(pPara) \ + if (NULL == (pPara)) { \ + return (-EINVAL); \ + } + +#define OS_GOTO_EXIT_IF_NULL(pPara) \ + if (NULL == (pPara)) { \ + ret = -EINVAL; \ + goto EXIT; \ + } + +typedef void (*sa_sighandler_t)(int); +typedef void (*sa_siginfoaction_t)(int, siginfo_t *, void *); + +#define SIGNO2SET(s) ((sigset_t)1ULL << (s)) +#define NULL_SIGNAL_SET ((sigset_t)0ULL) //设置成没有信号 +#define FULL_SIGNAL_SET ((sigset_t)~0ULL) //设置成满格信号 +//信号量是否有效 +static inline int GOOD_SIGNO(unsigned int sig) +{ + return (sig < _NSIG) ? 1 : 0;// +} +/******************************************************************** +Musl官网 http://musl.libc.org/ +musl是构建在Linux系统调用API之上的C标准库的实现,包括在基本语言标准POSIX中定义的接口, +以及广泛认可的扩展。musl是轻量级的,快速的,简单的,自由的. +********************************************************************/ + +#define MAX_SIG_ARRAY_IN_MUSL 128 + +typedef struct { + unsigned long sig[MAX_SIG_ARRAY_IN_MUSL / sizeof(unsigned long)]; +} sigset_t_l; + +typedef struct sigaction sigaction_t; + +struct sigactq { + struct sigactq *flink; /* Forward link */ + sigaction_t act; /* Sigaction data */ + uint8_t signo; /* Signal associated with action */ +}; +typedef struct sigactq sigactq_t; + +struct sq_entry_s { + struct sq_entry_s *flink; +}; +typedef struct sq_entry_s sq_entry_t; + +struct sigpendq { + struct sigpendq *flink; /* Forward link */ + siginfo_t info; /* Signal information */ + uint8_t type; /* (Used to manage allocations) */ +}; +typedef struct sigpendq sigpendq_t; + +struct sq_queue_s { + sq_entry_t *head; + sq_entry_t *tail; +}; +typedef struct sq_queue_s sq_queue_t; + +#define TASK_IRQ_CONTEXT \ + unsigned int R0; \ + unsigned int R1; \ + unsigned int R2; \ + unsigned int R3; \ + unsigned int R12; \ + unsigned int USP; \ + unsigned int ULR; \ + unsigned int CPSR; \ + unsigned int PC; + +typedef struct {//任务中断上下文 + TASK_IRQ_CONTEXT +} TaskIrqDataSize; + +typedef struct {//信号切换上下文 + TASK_IRQ_CONTEXT + unsigned int R7; + unsigned int count; +} sig_switch_context; + +typedef struct {//信号控制块(描述符) + sigset_t sigFlag; + sigset_t sigPendFlag; + sigset_t sigprocmask; /* Signals that are blocked */ //进程屏蔽了哪些信号 + sq_queue_t sigactionq; //信号捕捉队列 + LOS_DL_LIST waitList; //等待链表,上面挂的可是等待信号到来的任务, 请查找 OsTaskWait(&sigcb->waitList, timeout, TRUE) 理解 + sigset_t sigwaitmask; /* Waiting for pending signals */ //等待挂起的信号,意思就是位信号来了都要处理,比如 SIGKILL,SIGSTOP信号 + siginfo_t sigunbinfo; /* Signal info when task unblocked */ //任务解除阻止时的信号信息 + sig_switch_context context; //信号切换上下文,用于保存切换现场 +} sig_cb; + +#define SIGEV_THREAD_ID 4 + +int sys_sigqueue(pid_t, int, const union sigval); +int sys_sigpending(sigset_t *); +int sys_rt_sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *ts, size_t sigsetsize); +int sys_sigsuspend(const sigset_t *); +int OsKillLock(pid_t pid, int sig); +int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact); +int OsSigprocMask(int how, const sigset_t_l *set, sigset_t_l *oldset); +int OsPthreadKill(UINT32 tid, int signo); +int OsSigEmptySet(sigset_t *); +int OsSigAddSet(sigset_t *, int); +int OsSigIsMember(const sigset_t *, int); +void OsSaveSignalContext(unsigned int *sp); +void OsRestorSignalContext(unsigned int *sp); +int OsKill(pid_t pid, int sig, int permission); +int OsDispatch(pid_t pid, siginfo_t *info, int permission); +int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout); +int OsPause(void); +int OsSigPending(sigset_t *set); +int OsSigSuspend(const sigset_t *set); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_SIGNAL_H */ diff --git a/kernel/base/include/los_task_pri.h b/kernel/base/include/los_task_pri.h index 38b9c77a..c3af1373 100644 --- a/kernel/base/include/los_task_pri.h +++ b/kernel/base/include/los_task_pri.h @@ -55,10 +55,10 @@ extern "C" { * * Task siginal types. */ -#define SIGNAL_NONE 0U -#define SIGNAL_KILL (1U << 0) -#define SIGNAL_SUSPEND (1U << 1) -#define SIGNAL_AFFI (1U << 2) +#define SIGNAL_NONE 0U //无信号 +#define SIGNAL_KILL (1U << 0) //干掉 +#define SIGNAL_SUSPEND (1U << 1) //挂起 +#define SIGNAL_AFFI (1U << 2) //CPU 亲和力,一个任务被切换后被同一个CPU再次执行,则亲和力高 /* scheduler lock */ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁 @@ -317,8 +317,8 @@ typedef struct { UINT32 priBitMap; /**< BitMap for recording the change of task priority, //任务在执行过程中优先级会经常变化,这个变量用来记录所有曾经变化 the priority can not be greater than 31 */ //过的优先级,例如 ..01001011 曾经有过 0,1,3,6 优先级 INT32 errorNo; /**< Error Num */ - UINT32 signal; /**< Task signal */ //任务信号 注意这个信号和 下面的sig是完全不一样的两个东东。 - sig_cb sig; //信号控制块,和上面的signal是两个东西,独立使用。鸿蒙这样放在一块会误导开发者! + UINT32 signal; /**< Task signal */ //任务信号类型,(SIGNAL_NONE,SIGNAL_KILL,SIGNAL_SUSPEND,SIGNAL_AFFI) + sig_cb sig; //信号控制块,这里用于进程间通讯的信号,类似于 linux singal模块 #if (LOSCFG_KERNEL_SMP == YES) UINT16 currCpu; /**< CPU core number of this task is running on */ //正在运行此任务的CPU内核号 UINT16 lastCpu; /**< CPU core number of this task is running on last time */ //上次运行此任务的CPU内核号 @@ -356,7 +356,7 @@ typedef struct { LosTaskCB *newTask; } LosTask; -struct ProcessSignalInfo {//进程信号信息 +struct ProcessSignalInfo {//进程信号描述符 siginfo_t *sigInfo; /**< Signal to be dispatched */ //要发送的信号 例如 9 代表 kill process信号 LosTaskCB *defaultTcb; /**< Default TCB */ //默认task,指的是信号的发送方 LosTaskCB *unblockedTcb; /**< The signal unblock on this TCB*/ //解除阻塞这个task的信号 @@ -364,7 +364,7 @@ struct ProcessSignalInfo {//进程信号信息 LosTaskCB *receivedTcb; /**< This TCB received the signal */ //指定task接收信号 }; -typedef int (*ForEachTaskCB)(LosTaskCB *tcb, void *arg);//函数指针 +typedef int (*ForEachTaskCB)(LosTaskCB *tcb, void *arg);//每个任务的回调函数,可用于进程被kill 9 时,通知所有任务善后处理 /** * @ingroup los_task diff --git a/kernel/base/ipc/los_sem.c b/kernel/base/ipc/los_sem.c index a417be22..ffe7e9d8 100644 --- a/kernel/base/ipc/los_sem.c +++ b/kernel/base/ipc/los_sem.c @@ -1,298 +1,298 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "los_sem_pri.h" -#include "los_sem_debug_pri.h" -#include "los_err_pri.h" -#include "los_task_pri.h" -#include "los_exc.h" -#include "los_spinlock.h" -#include "los_mp.h" -#include "los_percpu_pri.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif /* __cplusplus */ - -#if (LOSCFG_BASE_IPC_SEM == YES) - -#if (LOSCFG_BASE_IPC_SEM_LIMIT <= 0) -#error "sem maxnum cannot be zero" -#endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */ - -LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList;//可用的信号量列表,干嘛不用freeList? 可以看出这里是另一个人写的代码 -LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;//信号池,一次分配 LOSCFG_BASE_IPC_SEM_LIMIT 个信号量 - -/* - * Description : Initialize the semaphore doubly linked list - * Return : LOS_OK on success, or error code on failure - */ -LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)//信号量初始化 -{ - LosSemCB *semNode = NULL; - UINT32 index; - - LOS_ListInit(&g_unusedSemList);//初始 - /* system resident memory, don't free */ - g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));//分配信号池 - if (g_allSem == NULL) { - return LOS_ERRNO_SEM_NO_MEMORY; - } - - for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) { - semNode = ((LosSemCB *)g_allSem) + index;//拿信号控制块, 可以直接g_allSem[index]来嘛 - semNode->semID = SET_SEM_ID(0, index);//保存ID - semNode->semStat = OS_SEM_UNUSED;//标记未使用 - LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);//通过semList把 信号块挂到空闲链表上 - } - - if (OsSemDbgInitHook() != LOS_OK) { - return LOS_ERRNO_SEM_NO_MEMORY; - } - return LOS_OK; -} - -/* - * Description : Create a semaphore, - * Input : count --- semaphore count, - * maxCount --- Max number of available semaphores, - * semHandle --- Index of semaphore, - * Return : LOS_OK on success ,or error code on failure - */ -LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle) -{ - UINT32 intSave; - LosSemCB *semCreated = NULL; - LOS_DL_LIST *unusedSem = NULL; - UINT32 errNo; - UINT32 errLine; - - if (semHandle == NULL) { - return LOS_ERRNO_SEM_PTR_NULL; - } - - if (count > maxCount) {//信号量不能大于最大值,两参数都是外面给的 - OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW); - } - - SCHEDULER_LOCK(intSave);//进入临界区了,拿自旋锁 - - if (LOS_ListEmpty(&g_unusedSemList)) {//没有可分配的空闲信号提供 - SCHEDULER_UNLOCK(intSave); - OsSemInfoGetFullDataHook(); - OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY); - } - - unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList);//拿第一个出来创建 - LOS_ListDelete(unusedSem);//从空闲链表上摘除 - semCreated = GET_SEM_LIST(unusedSem);//通过semList挂到链表上的,这里也要通过它把LosSemCB头查到. 进程,线程等结构体也都是这么干的. - semCreated->semCount = count;//设置数量 - semCreated->semStat = OS_SEM_USED;//设置可用状态 - semCreated->maxSemCount = maxCount;//设置最大信号数量 - LOS_ListInit(&semCreated->semList);//初始化链表,后续阻塞任务通过task->pendList挂到semList链表上,就知道哪些任务在等它了. - *semHandle = semCreated->semID;//参数带走 semID - - OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count); - - SCHEDULER_UNLOCK(intSave); - return LOS_OK; - -ERR_HANDLER: - OS_RETURN_ERROR_P2(errLine, errNo); -} -//对外接口 创建信号 -LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle) -{ - return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle); -} -//对外接口 创建一个最大信号数为1的信号量,可以当互斥锁用 -LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle) -{ - return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle); -} -//对外接口 删除信号量,参数就是 semID -LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) -{ - UINT32 intSave; - LosSemCB *semDeleted = NULL; - UINT32 errNo; - UINT32 errLine; - - if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) { - OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); - } - - semDeleted = GET_SEM(semHandle);//通过ID拿到信号量实体 - - SCHEDULER_LOCK(intSave); - - if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {//参数判断 - SCHEDULER_UNLOCK(intSave); - OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); - } - - if (!LOS_ListEmpty(&semDeleted->semList)) {//当前还有任务挂在这个信号上面,当然不能删除 - SCHEDULER_UNLOCK(intSave); - OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);//这个宏很有意思,里面goto到ERR_HANDLER - } - - LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);//通过semList从尾部插入空闲链表 - semDeleted->semStat = OS_SEM_UNUSED;//状态变成了未使用 - semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));//设置ID - - OsSemDbgUpdateHook(semDeleted->semID, NULL, 0); - - SCHEDULER_UNLOCK(intSave); - return LOS_OK; - -ERR_HANDLER: - OS_RETURN_ERROR_P2(errLine, errNo); -} -//对外接口 挂起信号 -LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) -{ - UINT32 intSave; - LosSemCB *semPended = GET_SEM(semHandle);//通过ID拿到信号体 - UINT32 retErr = LOS_OK; - LosTaskCB *runTask = NULL; - - if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) { - OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID); - } - - if (OS_INT_ACTIVE) { - PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n"); - OsBackTrace(); - return LOS_ERRNO_SEM_PEND_INTERR; - } - - runTask = OsCurrTaskGet();//获取当前任务 - if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { - OsBackTrace(); - return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK; - } - - SCHEDULER_LOCK(intSave); - - if ((semPended->semStat == OS_SEM_UNUSED) || (semPended->semID != semHandle)) { - retErr = LOS_ERRNO_SEM_INVALID; - goto OUT; - } - - /* Update the operate time, no matter the actual Pend success or not */ - OsSemDbgTimeUpdateHook(semHandle); - - if (semPended->semCount > 0) {//还有资源可用,返回肯定得成功,semCount=0时代表没资源了,task会必须去睡眠了 - semPended->semCount--;//资源少了一个 - goto OUT;//注意这里 retErr = LOS_OK ,所以返回是OK的 - } else if (!timeout) { - retErr = LOS_ERRNO_SEM_UNAVAILABLE; - goto OUT; - } - - if (!OsPreemptableInSched()) {//不能申请调度 (不能调度的原因是因为没有持有调度任务自旋锁) - PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n"); - OsBackTrace(); - retErr = LOS_ERRNO_SEM_PEND_IN_LOCK; - goto OUT; - } - - runTask->taskSem = (VOID *)semPended;//标记当前任务在等这个信号量 - retErr = OsTaskWait(&semPended->semList, timeout, TRUE);//任务进入等待状态,当前任务会挂到semList上,并在其中切换任务上下文 - if (retErr == LOS_ERRNO_TSK_TIMEOUT) {//注意:这里是涉及到task切换的,把自己挂起,唤醒其他task - runTask->taskSem = NULL; - retErr = LOS_ERRNO_SEM_TIMEOUT; - } - -OUT: - SCHEDULER_UNLOCK(intSave); - return retErr; -} -//释放信号 -LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched) -{ - LosSemCB *semPosted = NULL; - LosTaskCB *resumedTask = NULL; - - if (GET_SEM_INDEX(semHandle) >= LOSCFG_BASE_IPC_SEM_LIMIT) { - return LOS_ERRNO_SEM_INVALID; - } - - semPosted = GET_SEM(semHandle); - if ((semPosted->semID != semHandle) || (semPosted->semStat == OS_SEM_UNUSED)) { - return LOS_ERRNO_SEM_INVALID; - } - - /* Update the operate time, no matter the actual Post success or not */ - OsSemDbgTimeUpdateHook(semHandle); - - if (semPosted->semCount == OS_SEM_COUNT_MAX) {//当前信号资源不能大于最大资源量 - return LOS_ERRNO_SEM_OVERFLOW; - } - if (!LOS_ListEmpty(&semPosted->semList)) {//当前有任务挂在semList上,要去唤醒任务 - resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));//semList上面挂的都是task->pendlist节点,取第一个task下来唤醒 - resumedTask->taskSem = NULL;//任务不用等信号了,重新变成NULL值 - OsTaskWake(resumedTask);//唤醒任务,注意resumedTask一定不是当前任务,OsTaskWake里面并不会自己切换任务上下文,只是设置状态 - if (needSched != NULL) {//参数不为空,就返回需要调度的标签 - *needSched = TRUE;//TRUE代表需要调度 - } - } else {//当前没有任务挂在semList上, - semPosted->semCount++;//信号资源多一个 - } - - return LOS_OK; -} -//对外接口 释放信号 -LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle) -{ - UINT32 intSave; - UINT32 ret; - BOOL needSched = FALSE; - - SCHEDULER_LOCK(intSave); - ret = OsSemPostUnsafe(semHandle, &needSched); - SCHEDULER_UNLOCK(intSave); - if (needSched) {//需要调度的情况 - LOS_MpSchedule(OS_MP_CPU_ALL);//向所有CPU发送调度指令 - LOS_Schedule();////发起调度 - } - - return ret; -} -#endif /* (LOSCFG_BASE_IPC_SEM == YES) */ - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_sem_pri.h" +#include "los_sem_debug_pri.h" +#include "los_err_pri.h" +#include "los_task_pri.h" +#include "los_exc.h" +#include "los_spinlock.h" +#include "los_mp.h" +#include "los_percpu_pri.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#if (LOSCFG_BASE_IPC_SEM == YES) + +#if (LOSCFG_BASE_IPC_SEM_LIMIT <= 0) +#error "sem maxnum cannot be zero" +#endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */ + +LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList;//可用的信号量列表,干嘛不用freeList? 可以看出这里是另一个人写的代码 +LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;//信号池,一次分配 LOSCFG_BASE_IPC_SEM_LIMIT 个信号量 + +/* + * Description : Initialize the semaphore doubly linked list + * Return : LOS_OK on success, or error code on failure + */ +LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)//信号量初始化 +{ + LosSemCB *semNode = NULL; + UINT32 index; + + LOS_ListInit(&g_unusedSemList);//初始 + /* system resident memory, don't free */ + g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));//分配信号池 + if (g_allSem == NULL) { + return LOS_ERRNO_SEM_NO_MEMORY; + } + + for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) { + semNode = ((LosSemCB *)g_allSem) + index;//拿信号控制块, 可以直接g_allSem[index]来嘛 + semNode->semID = SET_SEM_ID(0, index);//保存ID + semNode->semStat = OS_SEM_UNUSED;//标记未使用 + LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);//通过semList把 信号块挂到空闲链表上 + } + + if (OsSemDbgInitHook() != LOS_OK) { + return LOS_ERRNO_SEM_NO_MEMORY; + } + return LOS_OK; +} + +/* + * Description : Create a semaphore, + * Input : count --- semaphore count, + * maxCount --- Max number of available semaphores, + * semHandle --- Index of semaphore, + * Return : LOS_OK on success ,or error code on failure + */ +LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle) +{ + UINT32 intSave; + LosSemCB *semCreated = NULL; + LOS_DL_LIST *unusedSem = NULL; + UINT32 errNo; + UINT32 errLine; + + if (semHandle == NULL) { + return LOS_ERRNO_SEM_PTR_NULL; + } + + if (count > maxCount) {//信号量不能大于最大值,两参数都是外面给的 + OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW); + } + + SCHEDULER_LOCK(intSave);//进入临界区了,拿自旋锁 + + if (LOS_ListEmpty(&g_unusedSemList)) {//没有可分配的空闲信号提供 + SCHEDULER_UNLOCK(intSave); + OsSemInfoGetFullDataHook(); + OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY); + } + + unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList);//拿第一个出来创建 + LOS_ListDelete(unusedSem);//从空闲链表上摘除 + semCreated = GET_SEM_LIST(unusedSem);//通过semList挂到链表上的,这里也要通过它把LosSemCB头查到. 进程,线程等结构体也都是这么干的. + semCreated->semCount = count;//设置数量 + semCreated->semStat = OS_SEM_USED;//设置可用状态 + semCreated->maxSemCount = maxCount;//设置最大信号数量 + LOS_ListInit(&semCreated->semList);//初始化链表,后续阻塞任务通过task->pendList挂到semList链表上,就知道哪些任务在等它了. + *semHandle = semCreated->semID;//参数带走 semID + + OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count); + + SCHEDULER_UNLOCK(intSave); + return LOS_OK; + +ERR_HANDLER: + OS_RETURN_ERROR_P2(errLine, errNo); +} +//对外接口 创建信号 +LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle) +{ + return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle); +} +//对外接口 创建一个最大信号数为1的信号量,可以当互斥锁用 +LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle) +{ + return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle); +} +//对外接口 删除信号量,参数就是 semID +LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) +{ + UINT32 intSave; + LosSemCB *semDeleted = NULL; + UINT32 errNo; + UINT32 errLine; + + if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) { + OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); + } + + semDeleted = GET_SEM(semHandle);//通过ID拿到信号量实体 + + SCHEDULER_LOCK(intSave); + + if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {//参数判断 + SCHEDULER_UNLOCK(intSave); + OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); + } + + if (!LOS_ListEmpty(&semDeleted->semList)) {//当前还有任务挂在这个信号上面,当然不能删除 + SCHEDULER_UNLOCK(intSave); + OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);//这个宏很有意思,里面goto到ERR_HANDLER + } + + LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);//通过semList从尾部插入空闲链表 + semDeleted->semStat = OS_SEM_UNUSED;//状态变成了未使用 + semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));//设置ID + + OsSemDbgUpdateHook(semDeleted->semID, NULL, 0); + + SCHEDULER_UNLOCK(intSave); + return LOS_OK; + +ERR_HANDLER: + OS_RETURN_ERROR_P2(errLine, errNo); +} +//对外接口 等待信号 +LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) +{ + UINT32 intSave; + LosSemCB *semPended = GET_SEM(semHandle);//通过ID拿到信号体 + UINT32 retErr = LOS_OK; + LosTaskCB *runTask = NULL; + + if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) { + OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID); + } + + if (OS_INT_ACTIVE) { + PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n"); + OsBackTrace(); + return LOS_ERRNO_SEM_PEND_INTERR; + } + + runTask = OsCurrTaskGet();//获取当前任务 + if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { + OsBackTrace(); + return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK; + } + + SCHEDULER_LOCK(intSave); + + if ((semPended->semStat == OS_SEM_UNUSED) || (semPended->semID != semHandle)) { + retErr = LOS_ERRNO_SEM_INVALID; + goto OUT; + } + + /* Update the operate time, no matter the actual Pend success or not */ + OsSemDbgTimeUpdateHook(semHandle); + + if (semPended->semCount > 0) {//还有资源可用,返回肯定得成功,semCount=0时代表没资源了,task会必须去睡眠了 + semPended->semCount--;//资源少了一个 + goto OUT;//注意这里 retErr = LOS_OK ,所以返回是OK的 + } else if (!timeout) { + retErr = LOS_ERRNO_SEM_UNAVAILABLE; + goto OUT; + } + + if (!OsPreemptableInSched()) {//不能申请调度 (不能调度的原因是因为没有持有调度任务自旋锁) + PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n"); + OsBackTrace(); + retErr = LOS_ERRNO_SEM_PEND_IN_LOCK; + goto OUT; + } + + runTask->taskSem = (VOID *)semPended;//标记当前任务在等这个信号量 + retErr = OsTaskWait(&semPended->semList, timeout, TRUE);//任务进入等待状态,当前任务会挂到semList上,并在其中切换任务上下文 + if (retErr == LOS_ERRNO_TSK_TIMEOUT) {//注意:这里是涉及到task切换的,把自己挂起,唤醒其他task + runTask->taskSem = NULL; + retErr = LOS_ERRNO_SEM_TIMEOUT; + } + +OUT: + SCHEDULER_UNLOCK(intSave); + return retErr; +} +//释放信号 +LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched) +{ + LosSemCB *semPosted = NULL; + LosTaskCB *resumedTask = NULL; + + if (GET_SEM_INDEX(semHandle) >= LOSCFG_BASE_IPC_SEM_LIMIT) { + return LOS_ERRNO_SEM_INVALID; + } + + semPosted = GET_SEM(semHandle); + if ((semPosted->semID != semHandle) || (semPosted->semStat == OS_SEM_UNUSED)) { + return LOS_ERRNO_SEM_INVALID; + } + + /* Update the operate time, no matter the actual Post success or not */ + OsSemDbgTimeUpdateHook(semHandle); + + if (semPosted->semCount == OS_SEM_COUNT_MAX) {//当前信号资源不能大于最大资源量 + return LOS_ERRNO_SEM_OVERFLOW; + } + if (!LOS_ListEmpty(&semPosted->semList)) {//当前有任务挂在semList上,要去唤醒任务 + resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));//semList上面挂的都是task->pendlist节点,取第一个task下来唤醒 + resumedTask->taskSem = NULL;//任务不用等信号了,重新变成NULL值 + OsTaskWake(resumedTask);//唤醒任务,注意resumedTask一定不是当前任务,OsTaskWake里面并不会自己切换任务上下文,只是设置状态 + if (needSched != NULL) {//参数不为空,就返回需要调度的标签 + *needSched = TRUE;//TRUE代表需要调度 + } + } else {//当前没有任务挂在semList上, + semPosted->semCount++;//信号资源多一个 + } + + return LOS_OK; +} +//对外接口 释放信号 +LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle) +{ + UINT32 intSave; + UINT32 ret; + BOOL needSched = FALSE; + + SCHEDULER_LOCK(intSave); + ret = OsSemPostUnsafe(semHandle, &needSched); + SCHEDULER_UNLOCK(intSave); + if (needSched) {//需要调度的情况 + LOS_MpSchedule(OS_MP_CPU_ALL);//向所有CPU发送调度指令 + LOS_Schedule();////发起调度 + } + + return ret; +} +#endif /* (LOSCFG_BASE_IPC_SEM == YES) */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/kernel/base/ipc/los_signal.c b/kernel/base/ipc/los_signal.c index 128ae3c9..1686d2e0 100644 --- a/kernel/base/ipc/los_signal.c +++ b/kernel/base/ipc/los_signal.c @@ -1,692 +1,704 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "los_signal.h" -#include "pthread.h" -#include "los_process_pri.h" -#include "los_hw_pri.h" -#include "user_copy.h" -#ifdef LOSCFG_SECURITY_CAPABILITY -#include "capability_api.h" -#endif - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -int raise(int sig) -{ - (VOID)sig; - PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__); - errno = ENOSYS; - return -1; -} - -#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag)) -#define UINT64_BIT_SIZE 64 -//信号是否为数字 -int OsSigIsMember(const sigset_t *set, int signo) -{ - int ret = LOS_NOK; - /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ - //@note_why 这里对musl的说明没看明白,为什么要-1呢? - signo -= 1; - /* Verify the signal */ - if (GOOD_SIGNO(signo)) { - /* Check if the signal is in the set */ - ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0); - } - - return ret; -} - -int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info) -{ - bool masked = FALSE; - sig_cb *sigcb = &stcb->sig; - - OS_RETURN_IF_NULL(sigcb); - /* If signo is 0, not send signal, just check process or pthread exist */ - if (info->si_signo == 0) { - return 0; - } - masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo); - if (masked) { - /* If signal is in wait list and mask list, need unblock it */ - if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) { - OsTaskWake(stcb); - OsSigEmptySet(&sigcb->sigwaitmask); - } else { - OsSigAddSet(&sigcb->sigPendFlag, info->si_signo); - } - } else { - /* unmasked signal actions */ - OsSigAddSet(&sigcb->sigFlag, info->si_signo); - if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) { - OsTaskWake(stcb); - OsSigEmptySet(&sigcb->sigwaitmask); - } - } - (void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t)); - return 0; -} - -void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set) -{ - sigset_t unmaskset; - - rtcb->sig.sigprocmask = set; - unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag); - if (unmaskset != NULL_SIGNAL_SET) { - /* pendlist do */ - rtcb->sig.sigFlag |= unmaskset; - rtcb->sig.sigPendFlag ^= unmaskset; - } -} - -int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset) -{ - LosTaskCB *spcb = NULL; - sigset_t oldSigprocmask; - int ret = LOS_OK; - unsigned int intSave; - sigset_t set; - int retVal; - - if (setl != NULL) { - retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); - if (retVal != 0) { - return -EFAULT; - } - } - SCHEDULER_LOCK(intSave); - spcb = OsCurrTaskGet(); - /* If requested, copy the old mask to user. */ - oldSigprocmask = spcb->sig.sigprocmask; - - /* If requested, modify the current signal mask. */ - if (setl != NULL) { - /* Okay, determine what we are supposed to do */ - switch (how) { - /* Set the union of the current set and the signal - * set pointed to by set as the new sigprocmask. - */ - case SIG_BLOCK: - spcb->sig.sigprocmask |= set; - break; - /* Set the intersection of the current set and the - * signal set pointed to by set as the new sigprocmask. - */ - case SIG_UNBLOCK: - spcb->sig.sigprocmask &= ~(set); - break; - /* Set the signal set pointed to by set as the new sigprocmask. */ - case SIG_SETMASK: - spcb->sig.sigprocmask = set; - break; - default: - ret = -EINVAL; - break; - } - /* If pending mask not in sigmask, need set sigflag. */ - OsSigMaskSwitch(spcb, spcb->sig.sigprocmask); - } - SCHEDULER_UNLOCK(intSave); - - if (oldset != NULL) { - retVal = LOS_ArchCopyToUser(&(oldset->sig[0]), &oldSigprocmask, sizeof(sigset_t)); - if (retVal != 0) { - return -EFAULT; - } - } - return ret; -} -//让进程的每一个task执行参数函数 -int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg) -{ - int ret; - - /* Visit the main thread last (if present) */ //最后访问主线程(如果有) - LosTaskCB *taskCB = NULL;//遍历进程的 threadList 链表,里面存放的都是task节点 - LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) { - ret = handler(taskCB, arg);//这里是个参数函数,执行这个参数函数 - OS_RETURN_IF(ret != 0, ret);//这个宏的意思就是只有ret = 0时,啥也不处理.其余就返回 ret - } - return LOS_OK; -} -//信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend -static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg) -{ - struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//先把参数解出来 - int ret; - int isMember; - - if (tcb == NULL) { - return 0; - } - - /* If the default tcb is not setted, then set this one as default. */ - if (!info->defaultTcb) {//如果没有默认发送方的TCB,就给一个. - info->defaultTcb = tcb; - } - - isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo); - if (isMember && (!info->awakenedTcb)) {//这意味着任务正在等待此信号。 - /* This means the task is waiting for this signal. Stop looking for it and use this tcb. - * The requirement is: if more than one task in this task group is waiting for the signal, - * then only one indeterminate task in the group will receive the signal. - */ - ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号 - OS_RETURN_IF(ret < 0, ret);//这种写法很有意思 - - /* set this tcb as awakenedTcb */ - info->awakenedTcb = tcb; - OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */ - } - /* Is this signal unblocked on this thread? */ - isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo); - if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) { - /* if unblockedTcb of this signal is not setted, then set it. */ - if (!info->unblockedTcb) { - info->unblockedTcb = tcb; - } - - ret = OsTcbDispatch(tcb, info->sigInfo); - OS_RETURN_IF(ret < 0, ret); - /* set this tcb as receivedTcb */ - info->receivedTcb = tcb; - OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */ - } - return 0; /* Keep searching */ -} -//干掉 task 的信号 -static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg) -{ - struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg; - - if ((tcb != NULL) && (info != NULL) && (info->sigInfo != NULL)) {//进程有信号 - sig_cb *sigcb = &tcb->sig; - if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->sigInfo->si_signo)) {//waitlist 不为空 且 有信号 - OsTaskWake(tcb);//唤醒这个任务,加入进程的就绪队列 - OsSigEmptySet(&sigcb->sigwaitmask);//清空信号 - } - } - return 0; -} -//进程加载task控制块信号 -static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo) -{ - LosTaskCB *tcb = NULL; - - if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {//信号即没有指定接收task 也没有指定被唤醒task - if (info->unblockedTcb) {//如果进程信号信息体中有阻塞task - tcb = info->unblockedTcb;// - } else if (info->defaultTcb) {//如果有默认的发送方task - tcb = info->defaultTcb; - } else { - return; - } - /* Deliver the signal to the selected task */ - (void)OsTcbDispatch(tcb, sigInfo);//向所选任务发送信号 - } -} -//给参数进程发送参数信号 -int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo) -{ - int ret; - struct ProcessSignalInfo info = { - .sigInfo = sigInfo, - .defaultTcb = NULL, - .unblockedTcb = NULL, - .awakenedTcb = NULL, - .receivedTcb = NULL - }; - - /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号 - if ((info.sigInfo != NULL) && (info.sigInfo->si_signo == SIGKILL)) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14 - (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);//给进程的所有task发送信号 - OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo); - OsWaitSignalToWakeProcess(spcb);//等待信号唤醒进程 - return 0; - } else { - ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//给进程所有task发送信号 - } - if (ret < 0) { - return ret; - } - SigProcessLoadTcb(&info, sigInfo); - return 0; -} -//清空信号 -int OsSigEmptySet(sigset_t *set) -{ - *set = NULL_SIGNAL_SET; - return 0; -} - -/* Privilege process can't send to kernel and privilege process */ //特权进程无法发送到内核和特权进程 -static int OsSignalPermissionToCheck(const LosProcessCB *spcb) -{ - UINT32 gid = spcb->group->groupID; - - if (gid == OS_KERNEL_PROCESS_GROUP) {//内核进程组 - return -EPERM; - } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {//用户特权进程组 - return -EPERM; - } - - return 0; -} -//发送信号 -int OsDispatch(pid_t pid, siginfo_t *info, int permission) -{ - LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程 - if (OsProcessIsUnused(spcb)) { - return -ESRCH; - } -#ifdef LOSCFG_SECURITY_CAPABILITY //启用安全模式 - LosProcessCB *current = OsCurrProcessGet();//获取当前进程 - - /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */ - if (OsProcessIsInactive(spcb)) {//如果要终止的进程处于非活动状态,但仍然存在,应该返回OK - return LOS_OK; - } - - /* Kernel process always has kill permission and user process should check permission *///内核进程总是有kill权限,用户进程应该检查权限 - if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) { - if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) { - return -EPERM; - } - } -#endif - if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) { - return -EPERM; - } - return OsSigProcessSend(spcb, info);//发送信号 -} -//发送信号14(SIGALRM默认行为为进程终止)给7号进程:kill 14 7(kill -14 7效果相同), -int OsKill(pid_t pid, int sig, int permission) -{ - siginfo_t info; - int ret; - - /* Make sure that the para is valid */ - if (!GOOD_SIGNO(sig) || pid < 0) {//有效信号 - return -EINVAL; - } - if (OsProcessIDUserCheckInvalid(pid)) {//检查参数 - return -ESRCH; - } - - /* Create the siginfo structure */ //创建信号结构体 - info.si_signo = sig; //信号编号 - info.si_code = SI_USER; //表示用户信号 - info.si_value.sival_ptr = NULL; - - /* Send the signal */ - ret = OsDispatch(pid, &info, permission);//发送信号 - return ret; -} - -int OsKillLock(pid_t pid, int sig) -{ - int ret; - unsigned int intSave; - - SCHEDULER_LOCK(intSave); - ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION); - SCHEDULER_UNLOCK(intSave); - return ret; -} - -int OsPthreadKill(UINT32 tid, int signo) -{ - LosTaskCB *stcb = NULL; - siginfo_t info; - - int ret; - UINT32 intSave; - - /* Make sure that the signal is valid */ - OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL); - if (OS_TID_CHECK_INVALID(tid)) { - return -ESRCH; - } - - /* Create the siginfo structure */ - info.si_signo = signo; - info.si_code = SI_USER; - info.si_value.sival_ptr = NULL; - /* Keep things stationary through the following */ - SCHEDULER_LOCK(intSave); - /* Get the TCB associated with the thread */ - stcb = OsGetTaskCB(tid); - OS_GOTO_EXIT_IF(stcb == NULL, -ESRCH); - - ret = OsUserTaskOperatePermissionsCheck(stcb); - OS_GOTO_EXIT_IF(ret != LOS_OK, -ret); - - /* Dispatch the signal to thread, bypassing normal task group thread - * dispatch rules. */ - ret = OsTcbDispatch(stcb, &info); -EXIT: - SCHEDULER_UNLOCK(intSave); - return ret; -} - -int OsSigAddSet(sigset_t *set, int signo) -{ - /* Verify the signal */ - if (!GOOD_SIGNO(signo)) { - return -EINVAL; - } else { - /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ - signo -= 1; - /* Add the signal to the set */ - *set |= SIGNO2SET((unsigned int)signo); - return LOS_OK; - } -} - -int OsSigPending(sigset_t *set) -{ - LosTaskCB *tcb = NULL; - unsigned int intSave; - - if (set == NULL) { - return -EFAULT; - } - - SCHEDULER_LOCK(intSave); - tcb = OsCurrTaskGet(); - *set = tcb->sig.sigPendFlag; - SCHEDULER_UNLOCK(intSave); - return LOS_OK; -} - -STATIC int FindFirstSetedBit(UINT64 n) -{ - int count; - - if (n == 0) { - return -1; - } - for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {} - return (count < UINT64_BIT_SIZE) ? count : (-1); -} - -int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout) -{ - LosTaskCB *task = NULL; - sig_cb *sigcb = NULL; - int ret; - - task = OsCurrTaskGet(); - sigcb = &task->sig; - - if (sigcb->waitList.pstNext == NULL) { - LOS_ListInit(&sigcb->waitList);//初始化信号等待链表 - } - /* If pendingflag & set > 0, shound clear pending flag */ - sigset_t clear = sigcb->sigPendFlag & *set; - if (clear) { - sigcb->sigPendFlag ^= clear; - ret = FindFirstSetedBit((UINT64)clear) + 1; - } else { - OsSigAddSet(set, SIGKILL); - OsSigAddSet(set, SIGSTOP); - - sigcb->sigwaitmask |= *set; - ret = OsTaskWait(&sigcb->waitList, timeout, TRUE);//将当前任务挂到waitlist上 - if (ret == LOS_ERRNO_TSK_TIMEOUT) { - ret = -EAGAIN; - } - sigcb->sigwaitmask = NULL_SIGNAL_SET; - } - if (info != NULL) { - (void) memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t)); - } - return ret; -} -// -int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout) -{ - int ret; - unsigned int intSave; - - SCHEDULER_LOCK(intSave); - - ret = OsSigTimedWaitNoLock(set, info, timeout); - - SCHEDULER_UNLOCK(intSave); - return ret; -} - -int OsPause(void) -{ - LosTaskCB *spcb = NULL; - sigset_t oldSigprocmask; - - spcb = OsCurrTaskGet(); - oldSigprocmask = spcb->sig.sigprocmask; - return OsSigSuspend(&oldSigprocmask); -} -//暂停信号 -int OsSigSuspend(const sigset_t *set) -{ - unsigned int intSave; - LosTaskCB *rtcb = NULL; - unsigned int sigTempProcMask; - sigset_t setSuspend; - int ret; - - if (set == NULL) { - return -EINVAL; - } - SCHEDULER_LOCK(intSave); - rtcb = OsCurrTaskGet(); - sigTempProcMask = rtcb->sig.sigprocmask; - - /* Wait signal calc */ - setSuspend = FULL_SIGNAL_SET & (~(*set)); - - /* If pending mask not in sigmask, need set sigflag */ - OsSigMaskSwitch(rtcb, *set); - ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER); - if (ret < 0) { - PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret); - } - /* Restore old sigprocmask */ - OsSigMaskSwitch(rtcb, sigTempProcMask); - - SCHEDULER_UNLOCK(intSave); - return -EINTR; -} - -int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact) -{ - UINTPTR addr; - sigaction_t action; - - if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) { - return -EINVAL; - } - if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) { - return -EFAULT; - } - - if (sig == SIGSYS) { - addr = OsGetSigHandler(); - if (addr == 0) { - OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler); - return LOS_OK; - } - return -EINVAL; - } - - return LOS_OK; -} - -void OsSaveSignalContext(unsigned int *sp) -{ - UINTPTR sigHandler; - UINT32 intSave; - LosTaskCB *task = NULL; - LosProcessCB *process = NULL; - sig_cb *sigcb = NULL; - unsigned long cpsr; - - OS_RETURN_IF_VOID(sp == NULL); - cpsr = OS_SYSCALL_GET_CPSR(sp); - - OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE)); - SCHEDULER_LOCK(intSave); - task = OsCurrTaskGet(); - process = OsCurrProcessGet(); - sigcb = &task->sig; - - if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) { - sigHandler = OsGetSigHandler(); - if (sigHandler == 0) { - sigcb->sigFlag = 0; - process->sigShare = 0; - SCHEDULER_UNLOCK(intSave); - PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID); - return; - } - /* One pthread do the share signal */ - sigcb->sigFlag |= process->sigShare; - unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; - OsProcessExitCodeSignalSet(process, signo); - sigcb->context.CPSR = cpsr; - sigcb->context.PC = sp[REG_PC]; - sigcb->context.USP = sp[REG_SP]; - sigcb->context.ULR = sp[REG_LR]; - sigcb->context.R0 = sp[REG_R0]; - sigcb->context.R1 = sp[REG_R1]; - sigcb->context.R2 = sp[REG_R2]; - sigcb->context.R3 = sp[REG_R3]; - sigcb->context.R7 = sp[REG_R7]; - sigcb->context.R12 = sp[REG_R12]; - sp[REG_PC] = sigHandler; - sp[REG_R0] = signo; - sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); - /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ - sigcb->sigFlag ^= 1ULL << (signo - 1); - sigcb->context.count++; - } - - SCHEDULER_UNLOCK(intSave); -} - -void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7) -{ - UINTPTR sigHandler; - LosTaskCB *task = NULL; - LosProcessCB *process = NULL; - sig_cb *sigcb = NULL; - unsigned long cpsr; - UINT32 intSave; - TaskIrqContext *context = (TaskIrqContext *)(sp); - - OS_RETURN_IF_VOID(sp == NULL); - cpsr = context->CPSR; - OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE)); - - SCHEDULER_LOCK(intSave); - task = OsCurrTaskGet(); - process = OsCurrProcessGet(); - sigcb = &task->sig; - if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) { - sigHandler = OsGetSigHandler(); - if (sigHandler == 0) { - sigcb->sigFlag = 0; - process->sigShare = 0; - SCHEDULER_UNLOCK(intSave); - PRINT_ERR("The current process pid =%d starts fail!\n", task->processID); - return; - } - sigcb->sigFlag |= process->sigShare; - unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; - OsProcessExitCodeSignalSet(process, signo); - (VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize)); - sigcb->context.R7 = r7; - context->PC = sigHandler; - context->R0 = signo; - context->R1 = (UINT32)(UINTPTR)sigcb->sigunbinfo.si_value.sival_ptr; - /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ - sigcb->sigFlag ^= 1ULL << (signo - 1); - sigcb->context.count++; - } - SCHEDULER_UNLOCK(intSave); -} - -void OsRestorSignalContext(unsigned int *sp) -{ - LosTaskCB *task = NULL; /* Do not adjust this statement */ - LosProcessCB *process = NULL; - sig_cb *sigcb = NULL; - UINT32 intSave; - - SCHEDULER_LOCK(intSave); - task = OsCurrTaskGet(); - sigcb = &task->sig; - - if (sigcb->context.count != 1) { - SCHEDULER_UNLOCK(intSave); - PRINT_ERR("sig error count : %d\n", sigcb->context.count); - return; - } - - process = OsCurrProcessGet(); - sp[REG_PC] = sigcb->context.PC; - OS_SYSCALL_SET_CPSR(sp, sigcb->context.CPSR); - sp[REG_SP] = sigcb->context.USP; - sp[REG_LR] = sigcb->context.ULR; - sp[REG_R0] = sigcb->context.R0; - sp[REG_R1] = sigcb->context.R1; - sp[REG_R2] = sigcb->context.R2; - sp[REG_R3] = sigcb->context.R3; - sp[REG_R7] = sigcb->context.R7; - sp[REG_R12] = sigcb->context.R12; - sigcb->context.count--; - process->sigShare = 0; - OsProcessExitCodeSignalClear(process); - SCHEDULER_UNLOCK(intSave); -} - -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_signal.h" +#include "pthread.h" +#include "los_process_pri.h" +#include "los_hw_pri.h" +#include "user_copy.h" +#ifdef LOSCFG_SECURITY_CAPABILITY +#include "capability_api.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +int raise(int sig) +{ + (VOID)sig; + PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__); + errno = ENOSYS; + return -1; +} + +#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag)) +#define UINT64_BIT_SIZE 64 +/**************************************************** +用来检测参数signum 代表的信号是否已加入至参数set信号集里。 +如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1 +****************************************************/ +int OsSigIsMember(const sigset_t *set, int signo) +{ + int ret = LOS_NOK; + /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ + //在musl中,sig No bits 00000100表示sig No 3,但是在SIGNO2SET中 1<<3 = 00001000,因此signo需要减1 + signo -= 1; + /* Verify the signal */ + if (GOOD_SIGNO(signo)) {//有效信号判断 + /* Check if the signal is in the set */ + ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);//检查信号是否还在集合中 + } + + return ret; +} +//给任务(线程)发送一个信号 +int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info) +{ + bool masked = FALSE; + sig_cb *sigcb = &stcb->sig; + + OS_RETURN_IF_NULL(sigcb); + /* If signo is 0, not send signal, just check process or pthread exist */ + if (info->si_signo == 0) { + return 0; + } + masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);//@note_thinking 这里还有 masked= -1的情况要处理!!! + if (masked) {//集合中已有该信号 + /* If signal is in wait list and mask list, need unblock it */ //如果信号在等待列表和掩码列表中,需要解除阻止 + if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) {//等待 + OsTaskWake(stcb); + OsSigEmptySet(&sigcb->sigwaitmask); + } else { + OsSigAddSet(&sigcb->sigPendFlag, info->si_signo); + } + } else {// + /* unmasked signal actions */ + OsSigAddSet(&sigcb->sigFlag, info->si_signo); + if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) { + OsTaskWake(stcb); + OsSigEmptySet(&sigcb->sigwaitmask); + } + } + (void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t)); + return 0; +} + +void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set) +{ + sigset_t unmaskset; + + rtcb->sig.sigprocmask = set; + unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag); + if (unmaskset != NULL_SIGNAL_SET) { + /* pendlist do */ + rtcb->sig.sigFlag |= unmaskset; + rtcb->sig.sigPendFlag ^= unmaskset; + } +} +//设置进程的信号掩码 +int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset) +{ + LosTaskCB *spcb = NULL; + sigset_t oldSigprocmask; + int ret = LOS_OK; + unsigned int intSave; + sigset_t set; + int retVal; + + if (setl != NULL) { + retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); + if (retVal != 0) { + return -EFAULT; + } + } + SCHEDULER_LOCK(intSave); + spcb = OsCurrTaskGet(); + /* If requested, copy the old mask to user. */ //如果需要,请将旧掩码复制给用户 + oldSigprocmask = spcb->sig.sigprocmask; + + /* If requested, modify the current signal mask. */ //如有要求,修改当前信号屏蔽 + if (setl != NULL) { + /* Okay, determine what we are supposed to do */ + switch (how) { + /* Set the union of the current set and the signal + * set pointed to by set as the new sigprocmask. + */ + case SIG_BLOCK: + spcb->sig.sigprocmask |= set;//增加信号屏蔽位 + break; + /* Set the intersection of the current set and the + * signal set pointed to by set as the new sigprocmask. + */ + case SIG_UNBLOCK: + spcb->sig.sigprocmask &= ~(set);//解除信号屏蔽位 + break; + /* Set the signal set pointed to by set as the new sigprocmask. */ + case SIG_SETMASK: + spcb->sig.sigprocmask = set;//设置一个新的屏蔽掩码 + break; + default: + ret = -EINVAL; + break; + } + /* If pending mask not in sigmask, need set sigflag. */ + OsSigMaskSwitch(spcb, spcb->sig.sigprocmask); + } + SCHEDULER_UNLOCK(intSave); + + if (oldset != NULL) { + retVal = LOS_ArchCopyToUser(&(oldset->sig[0]), &oldSigprocmask, sizeof(sigset_t)); + if (retVal != 0) { + return -EFAULT; + } + } + return ret; +} +//让进程的每一个task执行参数函数 +int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg) +{ + int ret; + + /* Visit the main thread last (if present) */ //最后访问主线程(如果有) + LosTaskCB *taskCB = NULL;//遍历进程的 threadList 链表,里面存放的都是task节点 + LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {//遍历进程的任务列表 + ret = handler(taskCB, arg);//回调参数函数 + OS_RETURN_IF(ret != 0, ret);//这个宏的意思就是只有ret = 0时,啥也不处理.其余就返回 ret + } + return LOS_OK; +} +//信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend +static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg) +{ + struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//先把参数解出来 + int ret; + int isMember; + + if (tcb == NULL) { + return 0; + } + + /* If the default tcb is not setted, then set this one as default. */ + if (!info->defaultTcb) {//如果没有默认发送方的TCB,就给一个. + info->defaultTcb = tcb; + } + + isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo); + if (isMember && (!info->awakenedTcb)) {//这意味着任务正在等待此信号。 + /* This means the task is waiting for this signal. Stop looking for it and use this tcb. + * The requirement is: if more than one task in this task group is waiting for the signal, + * then only one indeterminate task in the group will receive the signal. + */ + ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号 + OS_RETURN_IF(ret < 0, ret);//这种写法很有意思 + + /* set this tcb as awakenedTcb */ + info->awakenedTcb = tcb; + OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */ + } + /* Is this signal unblocked on this thread? */ + isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo); + if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) { + /* if unblockedTcb of this signal is not setted, then set it. */ + if (!info->unblockedTcb) { + info->unblockedTcb = tcb; + } + + ret = OsTcbDispatch(tcb, info->sigInfo); + OS_RETURN_IF(ret < 0, ret); + /* set this tcb as receivedTcb */ + info->receivedTcb = tcb; + OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */ + } + return 0; /* Keep searching */ +} +//SIGKILL 干掉进程引发处理函数 +static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg) +{ + struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//转参 + + if ((tcb != NULL) && (info != NULL) && (info->sigInfo != NULL)) {//进程有信号 + sig_cb *sigcb = &tcb->sig; + if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->sigInfo->si_signo)) {//waitlist 不为空 且 有信号 + OsTaskWake(tcb);//唤醒这个任务,加入进程的就绪队列 + OsSigEmptySet(&sigcb->sigwaitmask);//清空信号等待位,啥意思? + } + } + return 0; +} +//进程加载task控制块信号 +static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo) +{ + LosTaskCB *tcb = NULL; + + if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {//信号即没有指定接收task 也没有指定被唤醒task + if (info->unblockedTcb) {//如果进程信号信息体中有阻塞task + tcb = info->unblockedTcb;// + } else if (info->defaultTcb) {//如果有默认的发送方task + tcb = info->defaultTcb; + } else { + return; + } + /* Deliver the signal to the selected task */ + (void)OsTcbDispatch(tcb, sigInfo);//向所选任务发送信号 + } +} +//给参数进程发送参数信号 +int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo) +{ + int ret; + struct ProcessSignalInfo info = { + .sigInfo = sigInfo, //信号内容 + .defaultTcb = NULL, + .unblockedTcb = NULL, + .awakenedTcb = NULL, + .receivedTcb = NULL + }; + + /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号 + if ((info.sigInfo != NULL) && (info.sigInfo->si_signo == SIGKILL)) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14 + (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);//进程要被干掉了,信息要通知其所有task知道 + OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo); + OsWaitSignalToWakeProcess(spcb);//等待信号唤醒进程 + return 0; + } else { + ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//给进程所有task发送信号 + } + if (ret < 0) { + return ret; + } + SigProcessLoadTcb(&info, sigInfo); + return 0; +} +//清空信号 +int OsSigEmptySet(sigset_t *set) +{ + *set = NULL_SIGNAL_SET; + return 0; +} + +/* Privilege process can't send to kernel and privilege process */ //特权进程无法发送到内核和特权进程 +static int OsSignalPermissionToCheck(const LosProcessCB *spcb) +{ + UINT32 gid = spcb->group->groupID; + + if (gid == OS_KERNEL_PROCESS_GROUP) {//内核进程组 + return -EPERM; + } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {//用户特权进程组 + return -EPERM; + } + + return 0; +} +//发送信号 +int OsDispatch(pid_t pid, siginfo_t *info, int permission) +{ + LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程 + if (OsProcessIsUnused(spcb)) {//进程是否还在使用 + return -ESRCH; + } +#ifdef LOSCFG_SECURITY_CAPABILITY //启用能力安全模式 + LosProcessCB *current = OsCurrProcessGet();//获取当前进程 + + /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */ + if (OsProcessIsInactive(spcb)) {//如果要终止的进程处于非活动状态,但仍然存在,应该返回OK + return LOS_OK; + } + + /* Kernel process always has kill permission and user process should check permission *///内核进程总是有kill权限,用户进程需要检查权限 + if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {//用户进程检查能力范围 + if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) { + return -EPERM; + } + } +#endif + if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {// + return -EPERM; + } + return OsSigProcessSend(spcb, info);//给参数进程发送信号 +} +/************************************************ +shell命令 kill 14 7(kill -14 7效果相同) +发送信号14(SIGALRM默认行为为进程终止)给7号进程 +************************************************/ +int OsKill(pid_t pid, int sig, int permission) +{ + siginfo_t info; + int ret; + + /* Make sure that the para is valid */ + if (!GOOD_SIGNO(sig) || pid < 0) {//有效信号 [0,64] + return -EINVAL; + } + if (OsProcessIDUserCheckInvalid(pid)) {//检查参数进程 + return -ESRCH; + } + + /* Create the siginfo structure */ //创建信号结构体 + info.si_signo = sig; //信号编号 + info.si_code = SI_USER; //来自用户进程信号 + info.si_value.sival_ptr = NULL; + + /* Send the signal */ + ret = OsDispatch(pid, &info, permission);//发送信号 + return ret; +} +//给发送杀死进程信号的过程加锁 +int OsKillLock(pid_t pid, int sig) +{ + int ret; + unsigned int intSave; + + SCHEDULER_LOCK(intSave); + ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);//用户进程申请干掉其他进程,能成功吗? 满足条件就行 + SCHEDULER_UNLOCK(intSave); + return ret; +} +//发送信号干掉线程 +int OsPthreadKill(UINT32 tid, int signo) +{ + LosTaskCB *stcb = NULL; + siginfo_t info; + + int ret; + UINT32 intSave; + + /* Make sure that the signal is valid */ + OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL); + if (OS_TID_CHECK_INVALID(tid)) { + return -ESRCH; + } + + /* Create the siginfo structure */ + info.si_signo = signo; //信号编号 如 SIGKILL + info.si_code = SI_USER; //来自用户进程信号 + info.si_value.sival_ptr = NULL; + /* Keep things stationary through the following */ + SCHEDULER_LOCK(intSave); + /* Get the TCB associated with the thread */ + stcb = OsGetTaskCB(tid); + OS_GOTO_EXIT_IF(stcb == NULL, -ESRCH); + + ret = OsUserTaskOperatePermissionsCheck(stcb);//用户态操作权限检查 + OS_GOTO_EXIT_IF(ret != LOS_OK, -ret); + + /* Dispatch the signal to thread, bypassing normal task group thread + * dispatch rules. */ + ret = OsTcbDispatch(stcb, &info);//将信号发送到线程,将绕过正常的任务组线程调度规则 +EXIT: + SCHEDULER_UNLOCK(intSave); + return ret; +} + +int OsSigAddSet(sigset_t *set, int signo) +{ + /* Verify the signal */ + if (!GOOD_SIGNO(signo)) { + return -EINVAL; + } else { + /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ + signo -= 1; + /* Add the signal to the set */ + *set |= SIGNO2SET((unsigned int)signo); + return LOS_OK; + } +} +// +int OsSigPending(sigset_t *set) +{ + LosTaskCB *tcb = NULL; + unsigned int intSave; + + if (set == NULL) { + return -EFAULT; + } + + SCHEDULER_LOCK(intSave); + tcb = OsCurrTaskGet(); + *set = tcb->sig.sigPendFlag; + SCHEDULER_UNLOCK(intSave); + return LOS_OK; +} + +STATIC int FindFirstSetedBit(UINT64 n) +{ + int count; + + if (n == 0) { + return -1; + } + for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {} + return (count < UINT64_BIT_SIZE) ? count : (-1); +} + +int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout) +{ + LosTaskCB *task = NULL; + sig_cb *sigcb = NULL; + int ret; + + task = OsCurrTaskGet(); + sigcb = &task->sig; + + if (sigcb->waitList.pstNext == NULL) { + LOS_ListInit(&sigcb->waitList);//初始化信号等待链表 + } + /* If pendingflag & set > 0, shound clear pending flag */ + sigset_t clear = sigcb->sigPendFlag & *set; + if (clear) { + sigcb->sigPendFlag ^= clear; + ret = FindFirstSetedBit((UINT64)clear) + 1; + } else { + OsSigAddSet(set, SIGKILL);//kill 9 14 必须要处理 + OsSigAddSet(set, SIGSTOP);//终止进程的信号也必须处理 + + sigcb->sigwaitmask |= *set;//按位加到等待集上,也就是说sigwaitmask的信号来了都是要处理的. + ret = OsTaskWait(&sigcb->waitList, timeout, TRUE);//将当前任务挂到waitlist上 + if (ret == LOS_ERRNO_TSK_TIMEOUT) { + ret = -EAGAIN; + } + sigcb->sigwaitmask = NULL_SIGNAL_SET; + } + if (info != NULL) { + (void) memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t)); + } + return ret; +} +// +int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout) +{ + int ret; + unsigned int intSave; + + SCHEDULER_LOCK(intSave); + + ret = OsSigTimedWaitNoLock(set, info, timeout); + + SCHEDULER_UNLOCK(intSave); + return ret; +} + +int OsPause(void) +{ + LosTaskCB *spcb = NULL; + sigset_t oldSigprocmask; + + spcb = OsCurrTaskGet(); + oldSigprocmask = spcb->sig.sigprocmask; + return OsSigSuspend(&oldSigprocmask); +} +//暂停信号 +int OsSigSuspend(const sigset_t *set) +{ + unsigned int intSave; + LosTaskCB *rtcb = NULL; + unsigned int sigTempProcMask; + sigset_t setSuspend; + int ret; + + if (set == NULL) { + return -EINVAL; + } + SCHEDULER_LOCK(intSave); + rtcb = OsCurrTaskGet(); + sigTempProcMask = rtcb->sig.sigprocmask; + + /* Wait signal calc */ + setSuspend = FULL_SIGNAL_SET & (~(*set)); + + /* If pending mask not in sigmask, need set sigflag */ + OsSigMaskSwitch(rtcb, *set); + ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER); + if (ret < 0) { + PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret); + } + /* Restore old sigprocmask */ + OsSigMaskSwitch(rtcb, sigTempProcMask); + + SCHEDULER_UNLOCK(intSave); + return -EINTR; +} +/************************************************** +安装信号,函数用于改变进程接收到特定信号后的行为。 +sig:信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。 +act:指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理; +oldact:指向的对象用来保存返回的原来对相应信号的处理,可指定oldact为NULL。 +如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。 +**************************************************/ +int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact) +{ + UINTPTR addr; + sigaction_t action; + + if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) { + return -EINVAL; + } + if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) { + return -EFAULT; + } + + if (sig == SIGSYS) {//系统调用中参数错,如系统调用号非法 + addr = OsGetSigHandler();//获取进程信号处理函数 + if (addr == 0) { + OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);//设置进程信号处理函数 + return LOS_OK; + } + return -EINVAL; + } + + return LOS_OK; +} +//保存信号现场 +void OsSaveSignalContext(unsigned int *sp) +{ + UINTPTR sigHandler; + UINT32 intSave; + LosTaskCB *task = NULL; + LosProcessCB *process = NULL; + sig_cb *sigcb = NULL; + unsigned long cpsr; + + OS_RETURN_IF_VOID(sp == NULL); + cpsr = OS_SYSCALL_GET_CPSR(sp); + + OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE)); + SCHEDULER_LOCK(intSave); + task = OsCurrTaskGet(); + process = OsCurrProcessGet(); + sigcb = &task->sig; + + if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) { + sigHandler = OsGetSigHandler(); + if (sigHandler == 0) { + sigcb->sigFlag = 0; + process->sigShare = 0; + SCHEDULER_UNLOCK(intSave); + PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID); + return; + } + /* One pthread do the share signal */ + sigcb->sigFlag |= process->sigShare; + unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; + OsProcessExitCodeSignalSet(process, signo); + sigcb->context.CPSR = cpsr; + sigcb->context.PC = sp[REG_PC]; + sigcb->context.USP = sp[REG_SP]; + sigcb->context.ULR = sp[REG_LR]; + sigcb->context.R0 = sp[REG_R0]; + sigcb->context.R1 = sp[REG_R1]; + sigcb->context.R2 = sp[REG_R2]; + sigcb->context.R3 = sp[REG_R3]; + sigcb->context.R7 = sp[REG_R7]; + sigcb->context.R12 = sp[REG_R12]; + sp[REG_PC] = sigHandler; + sp[REG_R0] = signo; + sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); + /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ + sigcb->sigFlag ^= 1ULL << (signo - 1); + sigcb->context.count++; + } + + SCHEDULER_UNLOCK(intSave); +} +//保存信号中断现场 +void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7) +{ + UINTPTR sigHandler; + LosTaskCB *task = NULL; + LosProcessCB *process = NULL; + sig_cb *sigcb = NULL; + unsigned long cpsr; + UINT32 intSave; + TaskIrqContext *context = (TaskIrqContext *)(sp); + + OS_RETURN_IF_VOID(sp == NULL); + cpsr = context->CPSR; + OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE)); + + SCHEDULER_LOCK(intSave); + task = OsCurrTaskGet(); + process = OsCurrProcessGet(); + sigcb = &task->sig; + if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) { + sigHandler = OsGetSigHandler(); + if (sigHandler == 0) { + sigcb->sigFlag = 0; + process->sigShare = 0; + SCHEDULER_UNLOCK(intSave); + PRINT_ERR("The current process pid =%d starts fail!\n", task->processID); + return; + } + sigcb->sigFlag |= process->sigShare; + unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; + OsProcessExitCodeSignalSet(process, signo); + (VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize)); + sigcb->context.R7 = r7; + context->PC = sigHandler; + context->R0 = signo; + context->R1 = (UINT32)(UINTPTR)sigcb->sigunbinfo.si_value.sival_ptr; + /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ + sigcb->sigFlag ^= 1ULL << (signo - 1); + sigcb->context.count++; + } + SCHEDULER_UNLOCK(intSave); +} +//恢复信号上下文 +void OsRestorSignalContext(unsigned int *sp) +{ + LosTaskCB *task = NULL; /* Do not adjust this statement */ + LosProcessCB *process = NULL; + sig_cb *sigcb = NULL; + UINT32 intSave; + + SCHEDULER_LOCK(intSave); + task = OsCurrTaskGet(); + sigcb = &task->sig; + + if (sigcb->context.count != 1) { + SCHEDULER_UNLOCK(intSave); + PRINT_ERR("sig error count : %d\n", sigcb->context.count); + return; + } + + process = OsCurrProcessGet(); + sp[REG_PC] = sigcb->context.PC; + OS_SYSCALL_SET_CPSR(sp, sigcb->context.CPSR); + sp[REG_SP] = sigcb->context.USP; + sp[REG_LR] = sigcb->context.ULR; + sp[REG_R0] = sigcb->context.R0; + sp[REG_R1] = sigcb->context.R1; + sp[REG_R2] = sigcb->context.R2; + sp[REG_R3] = sigcb->context.R3; + sp[REG_R7] = sigcb->context.R7; + sp[REG_R12] = sigcb->context.R12; + sigcb->context.count--; + process->sigShare = 0; + OsProcessExitCodeSignalClear(process); + SCHEDULER_UNLOCK(intSave); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/kernel/base/misc/kill_shellcmd.c b/kernel/base/misc/kill_shellcmd.c index 10589af5..921557ec 100644 --- a/kernel/base/misc/kill_shellcmd.c +++ b/kernel/base/misc/kill_shellcmd.c @@ -1,93 +1,109 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "stdio.h" -#include "stdlib.h" -#include "los_signal.h" -#include "los_printf.h" -#include "los_task_pri.h" -#include "los_process_pri.h" -#include "log.h" -#ifdef LOSCFG_SHELL -#include "shcmd.h" -#include "shell.h" -#endif - -LITE_OS_SEC_TEXT_MINOR VOID OsPrintKillUsage(VOID) -{ - PRINTK("\nkill: usage: kill [sigspec] [pid]\n"); -} -// shell kill 命令用于发送特定信号给指定进程。kill [signo | -signo] [pid] -LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdKill(INT32 argc, const CHAR **argv) -{ -#define ARG_NUM 2 - INT32 sigNo = 0; - INT32 pidNo = 0; - INT32 ret; - CHAR *endPtr = NULL; - - if (argc == ARG_NUM) { - sigNo = strtoul(argv[0], &endPtr, 0); - if (*endPtr != 0) { - PRINTK("\nsigNo can't access %s.\n", argv[0]); - goto ERROR; - } - endPtr = NULL; - pidNo = strtoul(argv[1], &endPtr, 0); - if (*endPtr != 0) { - PRINTK("\npidNo can't access %s.\n", argv[1]); - goto ERROR; - } - - ret = OsKill(pidNo, abs(sigNo), OS_USER_KILL_PERMISSION);// OS_USER_KILL_PERMISSION 干掉用户进程 - HILOG_INFO(LOG_CORE, "Send signal(%d) to pidNo = %d!\n", abs(sigNo), pidNo); - if (ret == -1) { - HILOG_ERROR(LOG_CORE, "Kill fail ret = %d! Operation not permitted\n", ret); - goto ERROR; - } - if (ret < 0) { - PRINTK("\n Kill fail ret = %d! process not exist or sigNo is invalid\n", ret); - goto ERROR; - } - } else { - PRINTK("\nPara number errno!\n"); - goto ERROR; - } - return 0; -ERROR: - OsPrintKillUsage();//失败时 打印 kill 的用法 - return 0; -} - -#ifdef LOSCFG_SHELL -SHELLCMD_ENTRY(kill_shellcmd, CMD_TYPE_EX, "kill", 2, (CmdCallBackFunc)OsShellCmdKill);//采用shell命令静态注册方式 -#endif - +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdio.h" +#include "stdlib.h" +#include "los_signal.h" +#include "los_printf.h" +#include "los_task_pri.h" +#include "los_process_pri.h" +#include "log.h" +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#include "shell.h" +#endif + +LITE_OS_SEC_TEXT_MINOR VOID OsPrintKillUsage(VOID) +{ + PRINTK("\nkill: usage: kill [sigspec] [pid]\n"); +} +/********************************************* +命令功能 +命令用于发送特定信号给指定进程。 + +命令格式 +kill [signo | -signo] [pid] + +参数 参数说明 取值范围 +signo 信号ID [1,30] +pid 进程ID [1,MAX_INT] + +须知: signo有效范围为[0,64],建议取值范围为[1,30],其余为保留内容。 + +使用指南 +必须指定发送的信号编号及进程号。 +进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为[1-256]。 +*********************************************/ +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdKill(INT32 argc, const CHAR **argv) +{ +#define ARG_NUM 2 + INT32 sigNo = 0; + INT32 pidNo = 0; + INT32 ret; + CHAR *endPtr = NULL; + + if (argc == ARG_NUM) { + sigNo = strtoul(argv[0], &endPtr, 0); + if (*endPtr != 0) { + PRINTK("\nsigNo can't access %s.\n", argv[0]); + goto ERROR; + } + endPtr = NULL; + pidNo = strtoul(argv[1], &endPtr, 0); + if (*endPtr != 0) { + PRINTK("\npidNo can't access %s.\n", argv[1]); + goto ERROR; + } + + ret = OsKill(pidNo, abs(sigNo), OS_USER_KILL_PERMISSION);// OS_USER_KILL_PERMISSION 干掉用户进程 + HILOG_INFO(LOG_CORE, "Send signal(%d) to pidNo = %d!\n", abs(sigNo), pidNo); + if (ret == -1) { + HILOG_ERROR(LOG_CORE, "Kill fail ret = %d! Operation not permitted\n", ret); + goto ERROR; + } + if (ret < 0) { + PRINTK("\n Kill fail ret = %d! process not exist or sigNo is invalid\n", ret); + goto ERROR; + } + } else { + PRINTK("\nPara number errno!\n"); + goto ERROR; + } + return 0; +ERROR: + OsPrintKillUsage();//失败时 打印 kill 的用法 + return 0; +} + +#ifdef LOSCFG_SHELL +SHELLCMD_ENTRY(kill_shellcmd, CMD_TYPE_EX, "kill", 2, (CmdCallBackFunc)OsShellCmdKill);//采用shell命令静态注册方式 +#endif + diff --git a/security/cap/capability_type.h b/security/cap/capability_type.h index 3908dcb5..e83598d2 100644 --- a/security/cap/capability_type.h +++ b/security/cap/capability_type.h @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CAPABILITY_TYPE_H -#define CAPABILITY_TYPE_H - -// posix capabilities //posix 接口能力范围 -#define CAP_CHOWN 0 //修改拥有者 -#define CAP_DAC_EXECUTE 1 // -#define CAP_DAC_WRITE 2 -#define CAP_DAC_READ_SEARCH 3 -#define CAP_FOWNER 4 -#define CAP_KILL 5 //kill -#define CAP_SETGID 6 //设置用户组ID -#define CAP_SETUID 7 //设置用户ID - -// socket capabilities //网络能力 -#define CAP_NET_BIND_SERVICE 8 //绑定端口 -#define CAP_NET_BROADCAST 9 //网络广播 -#define CAP_NET_ADMIN 10 //网络管理 -#define CAP_NET_RAW 11 //网络读写访问 - -// fs capabilities //文件系统能力 -#define CAP_FS_MOUNT 12 //挂载 -#define CAP_FS_FORMAT 13 //格式化 - -// process capabilities //进程调度能力, -#define CAP_SCHED_SETPRIORITY 14 //设置调度优先级 - -// time capabilities //时间能力 -#define CAP_SET_TIMEOFDAY 15 //重置系统时间 -#define CAP_CLOCK_SETTIME 16 //设置时钟 - -// process capabilities //进程能力 -#define CAP_CAPSET 17 //设置进程能力的能力 - -// reboot capability //重新启动功能 -#define CAP_REBOOT 18 //重启系统 -// self deined privileged syscalls //自定义特权系统调用 -#define CAP_SHELL_EXEC 19 //自定义 shell 命令 +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CAPABILITY_TYPE_H +#define CAPABILITY_TYPE_H + +// posix capabilities //posix 接口能力范围 +#define CAP_CHOWN 0 //修改拥有者 +#define CAP_DAC_EXECUTE 1 // +#define CAP_DAC_WRITE 2 +#define CAP_DAC_READ_SEARCH 3 +#define CAP_FOWNER 4 +#define CAP_KILL 5 //杀死(进程,线程 ==)能力 +#define CAP_SETGID 6 //设置用户组ID +#define CAP_SETUID 7 //设置用户ID + +// socket capabilities //网络能力 +#define CAP_NET_BIND_SERVICE 8 //绑定端口 +#define CAP_NET_BROADCAST 9 //网络广播 +#define CAP_NET_ADMIN 10 //网络管理 +#define CAP_NET_RAW 11 //网络读写访问 + +// fs capabilities //文件系统能力 +#define CAP_FS_MOUNT 12 //挂载 +#define CAP_FS_FORMAT 13 //格式化 + +// process capabilities //进程调度能力, +#define CAP_SCHED_SETPRIORITY 14 //设置调度优先级 + +// time capabilities //时间能力 +#define CAP_SET_TIMEOFDAY 15 //重置系统时间 +#define CAP_CLOCK_SETTIME 16 //设置时钟 + +// process capabilities //进程能力 +#define CAP_CAPSET 17 //设置进程能力的能力 + +// reboot capability //重新启动功能 +#define CAP_REBOOT 18 //重启系统 +// self deined privileged syscalls //自定义特权系统调用 +#define CAP_SHELL_EXEC 19 //自定义 shell 命令 #endif \ No newline at end of file diff --git a/syscall/ipc_syscall.c b/syscall/ipc_syscall.c index 0e82a0f6..0016b30a 100644 --- a/syscall/ipc_syscall.c +++ b/syscall/ipc_syscall.c @@ -1,295 +1,304 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "mqueue.h" -#include -#include -#include -#include "time_posix.h" -#include "user_copy.h" -#include "los_signal.h" -#include "los_strncpy_from_user.h" -//创建和打开一个posix消息队列 -mqd_t SysMqOpen(const char *mqName, int openFlag, mode_t mode, struct mq_attr *attr) -{ - mqd_t ret; - int retValue; - char kMqName[PATH_MAX + 1] = { 0 }; - - retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); - if (retValue < 0) { - return retValue; - } - ret = mq_open(kMqName, openFlag, mode, attr); - if (ret == -1) { - return (mqd_t)-get_errno(); - } - return ret; -} -//关闭一个消息队列 -int SysMqClose(mqd_t personal) -{ - int ret; - - ret = mq_close(personal); - if (ret < 0) { - return -get_errno(); - } - return ret; -} - -int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) -{ - int ret; - struct mq_attr knew, kold; - - if (new != NULL) { - ret = LOS_ArchCopyFromUser(&knew, new, sizeof(struct mq_attr)); - if (ret != 0) { - return -EFAULT; - } - } - ret = mq_getsetattr(mqd, new ? &knew : NULL, old ? &kold : NULL); - if (ret < 0) { - return -get_errno(); - } - if (old != NULL) { - ret = LOS_ArchCopyToUser(old, &kold, sizeof(struct mq_attr)); - if (ret != 0) { - return -EFAULT; - } - } - return ret; -} - -int SysMqUnlink(const char *mqName) -{ - int ret; - int retValue; - char kMqName[PATH_MAX + 1] = { 0 }; - - retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); - if (retValue < 0) { - return retValue; - } - - ret = mq_unlink(kMqName); - if (ret < 0) { - return -get_errno(); - } - return ret; -} - -int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, - const struct timespec *absTimeout) -{ - int ret; - struct timespec timeout; - char *msgIntr = NULL; - - if (absTimeout != NULL) { - ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); - if (ret != 0) { - return -EFAULT; - } - } - if (msgLen == 0) { - return -EINVAL; - } - msgIntr = (char *)malloc(msgLen); - if (msgIntr == NULL) { - return -ENOMEM; - } - ret = LOS_ArchCopyFromUser(msgIntr, msg, msgLen); - if (ret != 0) { - free(msgIntr); - return -EFAULT; - } - ret = mq_timedsend(personal, msgIntr, msgLen, msgPrio, absTimeout ? &timeout : NULL); - free(msgIntr); - if (ret < 0) { - return -get_errno(); - } - return ret; -} - -ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, - const struct timespec *absTimeout) -{ - int ret, receiveLen; - struct timespec timeout; - char *msgIntr = NULL; - unsigned int kMsgPrio; - - if (absTimeout != NULL) { - ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); - if (ret != 0) { - return -EFAULT; - } - } - if (msgLen == 0) { - return -EINVAL; - } - msgIntr = (char *)malloc(msgLen); - if (msgIntr == NULL) { - return -ENOMEM; - } - receiveLen = mq_timedreceive(personal, msgIntr, msgLen, &kMsgPrio, absTimeout ? &timeout : NULL); - if (receiveLen < 0) { - free(msgIntr); - return -get_errno(); - } - - if (msgPrio != NULL) { - ret = LOS_ArchCopyToUser(msgPrio, &kMsgPrio, sizeof(unsigned int)); - if (ret != 0) { - free(msgIntr); - return -EFAULT; - } - } - - ret = LOS_ArchCopyToUser(msg, msgIntr, receiveLen); - free(msgIntr); - if (ret != 0) { - return -EFAULT; - } - return receiveLen; -} - -int SysSigAction(int sig, const sigaction_t *restrict sa, sigaction_t *restrict old, size_t sigsetsize) -{ - return OsSigAction(sig, sa, old); -} - -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 */ - return OsSigprocMask(how, setl, oldl); -} - -int SysKill(pid_t pid, int sig) -{ - return OsKillLock(pid, sig); -} - -int SysPthreadKill(pid_t pid, int sig) -{ - return OsPthreadKill(pid, sig); -} - -int SysSigTimedWait(const sigset_t_l *setl, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) -{ - sigset_t set; - unsigned int tick; - int retVal, ret; - siginfo_t infoIntr; - struct timespec timeoutIntr; - - retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); - if (retVal != 0) { - return -EFAULT; - } - - if (timeout == NULL) { - tick = LOS_WAIT_FOREVER; - } else { - retVal = LOS_ArchCopyFromUser(&timeoutIntr, timeout, sizeof(struct timespec)); - if (retVal != 0) { - return -EFAULT; - } - if (!ValidTimeSpec(&timeoutIntr)) { - return -EINVAL; - } - tick = OsTimeSpec2Tick(&timeoutIntr); - } - ret = OsSigTimedWait(&set, &infoIntr, tick); - if (ret < 0) { - return ret; - } - if (info != NULL) { - retVal = LOS_ArchCopyToUser(info, &infoIntr, sizeof(siginfo_t)); - if (retVal != 0) { - return -EFAULT; - } - } - return (ret == 0 ? infoIntr.si_signo : ret); -} - -int SysPause(void) -{ - return OsPause(); -} - -int SysSigPending(sigset_t_l *setl) -{ - sigset_t set; - int ret; - - ret = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); - if (ret != 0) { - return -EFAULT; - } - ret = OsSigPending(&set); - if (ret != LOS_OK) { - return ret; - } - ret = LOS_ArchCopyToUser(&(setl->sig[0]), &set, sizeof(sigset_t)); - if (ret != LOS_OK) { - return -EFAULT; - } - return ret; -} - -int SysSigSuspend(sigset_t_l *setl) -{ - sigset_t set; - int retVal; - - retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); - if (retVal != 0) { - return -EFAULT; - } - - return OsSigSuspend(&set); -} - -int SysMkFifo(const char *pathName, mode_t mode) -{ - int retValue; - char kPathName[PATH_MAX + 1] = { 0 }; - - retValue = LOS_StrncpyFromUser(kPathName, pathName, PATH_MAX); - if (retValue < 0) { - return retValue; - } - return mkfifo(kPathName, mode); -} - +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mqueue.h" +#include +#include +#include +#include "time_posix.h" +#include "user_copy.h" +#include "los_signal.h" +#include "los_strncpy_from_user.h" +//创建和打开一个posix消息队列 +mqd_t SysMqOpen(const char *mqName, int openFlag, mode_t mode, struct mq_attr *attr) +{ + mqd_t ret; + int retValue; + char kMqName[PATH_MAX + 1] = { 0 }; + + retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); + if (retValue < 0) { + return retValue; + } + ret = mq_open(kMqName, openFlag, mode, attr); + if (ret == -1) { + return (mqd_t)-get_errno(); + } + return ret; +} +//关闭一个消息队列 +int SysMqClose(mqd_t personal) +{ + int ret; + + ret = mq_close(personal); + if (ret < 0) { + return -get_errno(); + } + return ret; +} + +int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) +{ + int ret; + struct mq_attr knew, kold; + + if (new != NULL) { + ret = LOS_ArchCopyFromUser(&knew, new, sizeof(struct mq_attr)); + if (ret != 0) { + return -EFAULT; + } + } + ret = mq_getsetattr(mqd, new ? &knew : NULL, old ? &kold : NULL); + if (ret < 0) { + return -get_errno(); + } + if (old != NULL) { + ret = LOS_ArchCopyToUser(old, &kold, sizeof(struct mq_attr)); + if (ret != 0) { + return -EFAULT; + } + } + return ret; +} + +int SysMqUnlink(const char *mqName) +{ + int ret; + int retValue; + char kMqName[PATH_MAX + 1] = { 0 }; + + retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); + if (retValue < 0) { + return retValue; + } + + ret = mq_unlink(kMqName); + if (ret < 0) { + return -get_errno(); + } + return ret; +} + +int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, + const struct timespec *absTimeout) +{ + int ret; + struct timespec timeout; + char *msgIntr = NULL; + + if (absTimeout != NULL) { + ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); + if (ret != 0) { + return -EFAULT; + } + } + if (msgLen == 0) { + return -EINVAL; + } + msgIntr = (char *)malloc(msgLen); + if (msgIntr == NULL) { + return -ENOMEM; + } + ret = LOS_ArchCopyFromUser(msgIntr, msg, msgLen); + if (ret != 0) { + free(msgIntr); + return -EFAULT; + } + ret = mq_timedsend(personal, msgIntr, msgLen, msgPrio, absTimeout ? &timeout : NULL); + free(msgIntr); + if (ret < 0) { + return -get_errno(); + } + return ret; +} + +ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, + const struct timespec *absTimeout) +{ + int ret, receiveLen; + struct timespec timeout; + char *msgIntr = NULL; + unsigned int kMsgPrio; + + if (absTimeout != NULL) { + ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); + if (ret != 0) { + return -EFAULT; + } + } + if (msgLen == 0) { + return -EINVAL; + } + msgIntr = (char *)malloc(msgLen); + if (msgIntr == NULL) { + return -ENOMEM; + } + receiveLen = mq_timedreceive(personal, msgIntr, msgLen, &kMsgPrio, absTimeout ? &timeout : NULL); + if (receiveLen < 0) { + free(msgIntr); + return -get_errno(); + } + + if (msgPrio != NULL) { + ret = LOS_ArchCopyToUser(msgPrio, &kMsgPrio, sizeof(unsigned int)); + if (ret != 0) { + free(msgIntr); + return -EFAULT; + } + } + + ret = LOS_ArchCopyToUser(msg, msgIntr, receiveLen); + free(msgIntr); + if (ret != 0) { + return -EFAULT; + } + return receiveLen; +} +//系统调用之捕捉信号,鸿蒙内核只捕捉了SIGSYS 信号 +int SysSigAction(int sig, const sigaction_t *restrict sa, sigaction_t *restrict old, size_t sigsetsize) +{ + return OsSigAction(sig, sa, old); +} + +/***************************************************** +系统调用之进程信号屏蔽, +什么意思?简单说就是 一个信号来了进程要不要处理,阻塞就是不处理,注意不能阻塞SIGKILL和SIGSTOP信号,必须要处理. + +how +SIG_BLOCK 加入信号到进程屏蔽。set包含了希望阻塞的附加信号 +SIG_UNBLOCK 从进程屏蔽里将信号删除。set包含了希望解除阻塞的信号 +SIG_SETMASK 将set的值设定为新的进程屏蔽 +*****************************************************/ +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 */ + return OsSigprocMask(how, setl, oldl); +} +//系统调用之干掉进程 +int SysKill(pid_t pid, int sig) +{ + return OsKillLock(pid, sig); +} +//系统调用之干掉线程 +int SysPthreadKill(pid_t pid, int sig) +{ + return OsPthreadKill(pid, sig); +} + +int SysSigTimedWait(const sigset_t_l *setl, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) +{ + sigset_t set; + unsigned int tick; + int retVal, ret; + siginfo_t infoIntr; + struct timespec timeoutIntr; + + retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); + if (retVal != 0) { + return -EFAULT; + } + + if (timeout == NULL) { + tick = LOS_WAIT_FOREVER; + } else { + retVal = LOS_ArchCopyFromUser(&timeoutIntr, timeout, sizeof(struct timespec)); + if (retVal != 0) { + return -EFAULT; + } + if (!ValidTimeSpec(&timeoutIntr)) { + return -EINVAL; + } + tick = OsTimeSpec2Tick(&timeoutIntr); + } + ret = OsSigTimedWait(&set, &infoIntr, tick); + if (ret < 0) { + return ret; + } + if (info != NULL) { + retVal = LOS_ArchCopyToUser(info, &infoIntr, sizeof(siginfo_t)); + if (retVal != 0) { + return -EFAULT; + } + } + return (ret == 0 ? infoIntr.si_signo : ret); +} + +int SysPause(void) +{ + return OsPause(); +} + +int SysSigPending(sigset_t_l *setl) +{ + sigset_t set; + int ret; + + ret = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); + if (ret != 0) { + return -EFAULT; + } + ret = OsSigPending(&set); + if (ret != LOS_OK) { + return ret; + } + ret = LOS_ArchCopyToUser(&(setl->sig[0]), &set, sizeof(sigset_t)); + if (ret != LOS_OK) { + return -EFAULT; + } + return ret; +} + +int SysSigSuspend(sigset_t_l *setl) +{ + sigset_t set; + int retVal; + + retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); + if (retVal != 0) { + return -EFAULT; + } + + return OsSigSuspend(&set); +} + +int SysMkFifo(const char *pathName, mode_t mode) +{ + int retValue; + char kPathName[PATH_MAX + 1] = { 0 }; + + retValue = LOS_StrncpyFromUser(kPathName, pathName, PATH_MAX); + if (retValue < 0) { + return retValue; + } + return mkfifo(kPathName, mode); +} + diff --git a/zzz/git/push.sh b/zzz/git/push.sh index 6d7036bb..62dfdf97 100644 --- a/zzz/git/push.sh +++ b/zzz/git/push.sh @@ -1,5 +1,5 @@ git add -A -git commit -m '完善对进程/任务注解 +git commit -m '如何跨CPU删除任务?注解一个任务是如何自杀和被他杀的. 搜索 @note_pic 可以查看全部字符图 搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善 搜索 @note_thinking 是注者的思考和吐槽的地方 -- GitLab