更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_signal.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "los_signal.h"
33#include "pthread.h"
34#include "los_process_pri.h"
35#include "los_sched_pri.h"
36#include "los_hw_pri.h"
37#include "user_copy.h"
38#ifdef LOSCFG_SECURITY_CAPABILITY
39#include "capability_api.h"
40#endif
41#include "los_atomic.h"
42
43#ifdef LOSCFG_KERNEL_VM
44
45int raise(int sig)
46{
47 (VOID)sig;
48 PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
49 errno = ENOSYS;
50 return -1;
51}
52
53#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
54#define UINT64_BIT_SIZE 64
55
56/**
57 * @brief 判定信号signo是否存在信号集中。如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1
58 * @param set
59 * @param signo
60 * @return int
61 */
62int OsSigIsMember(const sigset_t *set, int signo)
63{
64 int ret = LOS_NOK;
65 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
66 //在musl中,sig No bits 00000100表示sig No 3,但是在SIGNO2SET中 1<<3 = 00001000,因此signo需要减1
67 signo -= 1;
68 /* Verify the signal */
69 if (GOOD_SIGNO(signo)) {//有效信号判断
70 /* Check if the signal is in the set */
71 ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);//检查信号是否还在集合中
72 }
73
74 return ret;
75}
76
77STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
78{
79 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
80 SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
81 while (tmpInfoNode != NULL) {
82 if (tmpInfoNode->info.si_signo == signo) {
83 /* copy tmpinfo to unbinfo. */
84 (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
85 /* delete tmpinfo from tmpList. */
86 *prevHook = tmpInfoNode->next;
87 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
88 tmpInfoNode = *prevHook;
89 break;
90 }
91 prevHook = &tmpInfoNode->next;
92 tmpInfoNode = tmpInfoNode->next;
93 }
94}
95
96STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
97{
98 /* try to find the old siginfo */
99 SigInfoListNode *tmp = sigcb->tmpInfoListHead;
100 while (tmp != NULL) {
101 if (tmp->info.si_signo == info->si_signo) {
102 /* found it, break. */
103 break;
104 }
105 tmp = tmp->next;
106 }
107
108 if (tmp == NULL) {
109 /* none, alloc new one */
111 if (tmp == NULL) {
112 return LOS_NOK;
113 }
114 tmp->next = sigcb->tmpInfoListHead;
115 sigcb->tmpInfoListHead = tmp;
116 }
117
118 (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));
119
120 return LOS_OK;
121}
122
124{
125 while (sigcb->tmpInfoListHead != NULL) {
126 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
127 sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next;
128 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
129 }
130}
131STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
132{
133 sig_cb *sigcb = &taskCB->sig;
134
135 if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
136 OsMoveTmpInfoToUnbInfo(sigcb, signo);
138 taskCB->ops->wake(taskCB);
139 OsSigEmptySet(&sigcb->sigwaitmask);
140 }
141}
142///< 唤醒被挂起的处于等待指定信号的任务
144{
145 if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_PID(taskCB->processID))) {
146 return 0;
147 }
148
149 if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) { // @note_thinking 这个判断会不会有问题 ?
150 return 0;
151 }
152
153 switch (taskCB->waitFlag) {
154 case OS_TASK_WAIT_PROCESS:
155 case OS_TASK_WAIT_GID:
156 case OS_TASK_WAIT_ANYPROCESS:
157 OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
158 break;
159 case OS_TASK_WAIT_JOIN:
161 taskCB->ops->wake(taskCB);
162 break;
163 case OS_TASK_WAIT_SIGNAL://等待普通信号
164 OsSigWaitTaskWake(taskCB, signo);
165 break;
166 case OS_TASK_WAIT_LITEIPC://等待liteipc信号
167 OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
168 taskCB->ops->wake(taskCB);
169 break;
170 case OS_TASK_WAIT_FUTEX://等待快锁信号
171 OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);//从哈希桶中删除快锁
172 OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
173 taskCB->ops->wake(taskCB);
174 break;
175 default:
176 break;
177 }
178
179 return 0;
180}
181///给任务(线程)发送一个信号
182int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
183{
184 bool masked = FALSE;
185 sig_cb *sigcb = &stcb->sig;
186
187 OS_RETURN_IF_NULL(sigcb);
188 /* If signo is 0, not send signal, just check process or pthread exist */
189 if (info->si_signo == 0) {//如果信号为0,则不发送信号,只是作为检查进程和线程是否还存在.
190 return 0;
191 }
192 masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);//@note_thinking 这里还有 masked= -1的情况要处理!!!
193 if (masked) {//如果信号被屏蔽了,要看等待信号集,sigwaitmask
194 /* If signal is in wait list and mask list, need unblock it */ //如果信号在等待列表和掩码列表中,需要解除阻止
195 if (LOS_ListEmpty(&sigcb->waitList) ||
196 (!LOS_ListEmpty(&sigcb->waitList) && !OsSigIsMember(&sigcb->sigwaitmask, info->si_signo))) {
197 OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);//将信号加入挂起/待办集
198 }
199 } else {//信号没有被屏蔽的处理
200 /* unmasked signal actions */
201 OsSigAddSet(&sigcb->sigFlag, info->si_signo);//不屏蔽的信号集
202 }
203
204 if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
205 return -ENOMEM;
206 }
207
208 return OsPendingTaskWake(stcb, info->si_signo);
209}
210
211void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
212{
213 sigset_t unmaskset;
214
215 rtcb->sig.sigprocmask = set;
216 unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);//过滤出没有被屏蔽的信号集
217 if (unmaskset != NULL_SIGNAL_SET) {
218 /* pendlist do */
219 rtcb->sig.sigFlag |= unmaskset; //加入不屏蔽信号集
220 rtcb->sig.sigPendFlag ^= unmaskset;//从挂起/待办集中去掉unmaskset
221 }
222}
223
224/**
225 * @brief
226 * @verbatim
227 向信号集设置信号屏蔽的方法
228 SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
229 SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
230 SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
231 * @endverbatim
232 */
233int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldsetl)
234{
235 LosTaskCB *spcb = NULL;
236 int ret = LOS_OK;
237 unsigned int intSave;
238 sigset_t set;
239
240 SCHEDULER_LOCK(intSave);
241 spcb = OsCurrTaskGet();
242 /* If requested, copy the old mask to user. | 如果需要,请将旧掩码复制给用户*/
243 if (oldsetl != NULL) {
244 *(sigset_t *)oldsetl = spcb->sig.sigprocmask;
245 }
246 /* If requested, modify the current signal mask. | 如有要求,修改当前信号屏蔽*/
247 if (setl != NULL) {
248 set = *(sigset_t *)setl;
249 /* Okay, determine what we are supposed to do */
250 switch (how) {
251 /* Set the union of the current set and the signal
252 * set pointed to by set as the new sigprocmask.
253 */
254 case SIG_BLOCK:
255 spcb->sig.sigprocmask |= set;//增加信号屏蔽位
256 break;
257 /* Set the intersection of the current set and the
258 * signal set pointed to by set as the new sigprocmask.
259 */
260 case SIG_UNBLOCK:
261 spcb->sig.sigprocmask &= ~(set);//解除信号屏蔽位
262 break;
263 /* Set the signal set pointed to by set as the new sigprocmask. */
264 case SIG_SETMASK:
265 spcb->sig.sigprocmask = set;//设置一个新的屏蔽掩码
266 break;
267 default:
268 ret = -EINVAL;
269 break;
270 }
271 /* If pending mask not in sigmask, need set sigflag. */
272 OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);//更新与屏蔽信号相关的变量
273 }
274 SCHEDULER_UNLOCK(intSave);
275
276 return ret;
277}
278///让进程的每一个task执行参数函数
280{
281 int ret;
282
283 /* Visit the main thread last (if present) */
284 LosTaskCB *taskCB = NULL;//遍历进程的 threadList 链表,里面存放的都是task节点
285 LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {//遍历进程的任务列表
286 ret = handler(taskCB, arg);//回调参数函数
287 OS_RETURN_IF(ret != 0, ret);//这个宏的意思就是只有ret = 0时,啥也不处理.其余就返回 ret
288 }
289 return LOS_OK;
290}
291///信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend
292static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
293{
294 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//先把参数解出来
295 int ret;
296 int isMember;
297
298 if (tcb == NULL) {
299 return 0;
300 }
301
302 /* If the default tcb is not setted, then set this one as default. */
303 if (!info->defaultTcb) {//如果没有默认发送方的任务,即默认参数任务.
304 info->defaultTcb = tcb;
305 }
306
307 isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);//任务是否在等待这个信号
308 if (isMember && (!info->awakenedTcb)) {//是在等待,并尚未向该任务时发送信号时
309 /* This means the task is waiting for this signal. Stop looking for it and use this tcb.
310 * The requirement is: if more than one task in this task group is waiting for the signal,
311 * then only one indeterminate task in the group will receive the signal.
312 */
313 ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号,注意这是给其他任务发送信号,tcb不是当前任务
314 OS_RETURN_IF(ret < 0, ret);//这种写法很有意思
315
316 /* set this tcb as awakenedTcb */
317 info->awakenedTcb = tcb;
318 OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
319 }
320 /* Is this signal unblocked on this thread? */
321 isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);//任务是否屏蔽了这个信号
322 if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {//没有屏蔽,有唤醒任务没有接收任务.
323 /* if unblockedTcb of this signal is not setted, then set it. */
324 if (!info->unblockedTcb) {
325 info->unblockedTcb = tcb;
326 }
327
328 ret = OsTcbDispatch(tcb, info->sigInfo);//向任务发送信号
329 OS_RETURN_IF(ret < 0, ret);
330 /* set this tcb as receivedTcb */
331 info->receivedTcb = tcb;//设置这个任务为接收任务
332 OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
333 }
334 return 0; /* Keep searching */
335}
336///进程收到 SIGKILL 信号后,通知任务tcb处理.
337static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
338{
339 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//转参
340
341 return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
342}
343
344//处理信号发送
345static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
346{
347 LosTaskCB *tcb = NULL;
348
349 if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {//信号即没有指定接收task 也没有指定被唤醒task
350 if (info->unblockedTcb) {//如果进程信号信息体中有阻塞task
351 tcb = info->unblockedTcb;//
352 } else if (info->defaultTcb) {//如果有默认的发送方task
353 tcb = info->defaultTcb;
354 } else {
355 return;
356 }
357 /* Deliver the signal to the selected task */
358 (void)OsTcbDispatch(tcb, sigInfo);//向所选任务发送信号
359 }
360}
361///给参数进程发送参数信号
363{
364 int ret;
365 struct ProcessSignalInfo info = {
366 .sigInfo = sigInfo, //信号内容
367 .defaultTcb = NULL, //以下四个值将在OsSigProcessForeachChild中根据条件完善
368 .unblockedTcb = NULL,
369 .awakenedTcb = NULL,
370 .receivedTcb = NULL
371 };
372 //总之是要从进程中找个至少一个任务来接受这个信号,优先级
373 //awakenedTcb > receivedTcb > unblockedTcb > defaultTcb
374 if (info.sigInfo == NULL){
375 return -EFAULT;
376 }
377 /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号
378 if (info.sigInfo->si_signo == SIGKILL) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14
379 OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);//信号集中增加信号
381 return 0;
382 } else {
383 ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//进程通知所有task处理信号
384 }
385 if (ret < 0) {
386 return ret;
387 }
388 SigProcessLoadTcb(&info, sigInfo);//确保能给一个任务发送信号
389 return 0;
390}
391///信号集全部清0
392int OsSigEmptySet(sigset_t *set)
393{
394 *set = NULL_SIGNAL_SET;
395 return 0;
396}
397
398/* Privilege process can't send to kernel and privilege process */ //内核进程组和用户特权进程组无法发送
400{
401 UINT32 gid = spcb->group->groupID;
402
403 if (gid == OS_KERNEL_PROCESS_GROUP) {//内核进程组
404 return -EPERM;
405 } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {//用户特权进程组
406 return -EPERM;
407 }
408
409 return 0;
410}
411///信号分发,发送信号权限/进程组过滤.
412int OsDispatch(pid_t pid, siginfo_t *info, int permission)
413{
414 if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
415 return -ESRCH;
416 }
417 LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程
418 if (OsProcessIsUnused(spcb)) {//进程是否还在使用,不一定是当前进程但必须是个有效进程
419 return -ESRCH;
420 }
421
422 /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
423 if (OsProcessIsInactive(spcb)) {//不向非活动进程发送信息,但返回OK
424 return LOS_OK;
425 }
426
427#ifdef LOSCFG_SECURITY_CAPABILITY //启用能力安全模式
428 LosProcessCB *current = OsCurrProcessGet();//获取当前进程,检查当前进程是否有发送信号的权限.
429 /* Kernel process always has kill permission and user process should check permission *///内核进程总是有kill权限,用户进程需要检查权限
430 if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {//用户进程检查能力范围
431 if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
432 return -EPERM;
433 }
434 }
435#endif
436 if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
437 return -EPERM;
438 }
439 return OsSigProcessSend(spcb, info);//给参数进程发送信号
440}
441
442/**
443 * @brief
444 * @verbatim
445 用于向进程或进程组发送信号
446 shell命令 kill 14 7(kill -14 7效果相同)
447 发送信号14(SIGALRM默认行为为进程终止)给7号进程
448 * @endverbatim
449 */
450int OsKill(pid_t pid, int sig, int permission)
451{
452 siginfo_t info;
453 int ret;
454
455 /* Make sure that the para is valid */
456 if (!GOOD_SIGNO(sig)) {
457 return -EINVAL;
458 }
459
460 /* Create the siginfo structure */ //创建信号结构体
461 info.si_signo = sig; //信号编号
462 info.si_code = SI_USER; //来自用户进程信号
463 info.si_value.sival_ptr = NULL;
464
465 if (pid > 0) {
466 /* Send the signal to the specify process */
467 ret = OsDispatch(pid, &info, permission);//发送信号
468 } else if (pid == -1) {
469 /* Send SIG to all processes */
470 ret = OsSendSignalToAllProcess(&info, permission);
471 } else {
472 /* Send SIG to all processes in process group PGRP.
473 If PGRP is zero, send SIG to all processes in
474 the current process's process group. */
475 ret = OsSendSignalToProcessGroup(pid, &info, permission);
476 }
477 return ret;
478}
479///给发送信号过程加锁
480int OsKillLock(pid_t pid, int sig)
481{
482 int ret;
483 unsigned int intSave;
484
485 SCHEDULER_LOCK(intSave);
486 ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);//用户权限向进程发送信号
487 SCHEDULER_UNLOCK(intSave);
488 return ret;
489}
491{
492 siginfo_t info;
493 LosTaskCB *taskCB = OsGetTaskCB(taskID);
495 if (ret != LOS_OK) {
496 return -ret;
497 }
498
499 /* Create the siginfo structure */
500 info.si_signo = signo;
501 info.si_code = SI_USER;
502 info.si_value.sival_ptr = NULL;
503
504 /* Dispatch the signal to thread, bypassing normal task group thread
505 * dispatch rules. */
506 return OsTcbDispatch(taskCB, &info);
507}
508///发送信号
509int OsPthreadKill(UINT32 tid, int signo)
510{
511 int ret;
512 UINT32 intSave;
513
514 /* Make sure that the signal is valid */
515 OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
516 if (OS_TID_CHECK_INVALID(tid)) {
517 return -ESRCH;
518 }
519
520 /* Keep things stationary through the following */
521 SCHEDULER_LOCK(intSave);
522 ret = OsTaskKillUnsafe(tid, signo);
523 SCHEDULER_UNLOCK(intSave);
524 return ret;
525}
526///向信号集中加入signo信号
527int OsSigAddSet(sigset_t *set, int signo)
528{
529 /* Verify the signal */
530 if (!GOOD_SIGNO(signo)) {
531 return -EINVAL;
532 } else {
533 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
534 signo -= 1;// 信号范围是 [1 ~ 64 ],而保存变量位的范围是[0 ~ 63]
535 /* Add the signal to the set */
536 *set |= SIGNO2SET((unsigned int)signo);//填充信号集
537 return LOS_OK;
538 }
539}
540///获取阻塞当前任务的信号集
541int OsSigPending(sigset_t *set)
542{
543 LosTaskCB *tcb = NULL;
544 unsigned int intSave;
545
546 if (set == NULL) {
547 return -EFAULT;
548 }
549
550 SCHEDULER_LOCK(intSave);
551 tcb = OsCurrTaskGet();
552 *set = tcb->sig.sigPendFlag;//被阻塞的信号集
553 SCHEDULER_UNLOCK(intSave);
554 return LOS_OK;
555}
556
558{
559 int count;
560
561 if (n == 0) {
562 return -1;
563 }
564 for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
565 return (count < UINT64_BIT_SIZE) ? count : (-1);
566}
567///等待信号时间
568int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
569{
570 LosTaskCB *task = NULL;
571 sig_cb *sigcb = NULL;
572 int ret;
573
574 task = OsCurrTaskGet();
575 sigcb = &task->sig;
576
577 if (sigcb->waitList.pstNext == NULL) {
578 LOS_ListInit(&sigcb->waitList);//初始化信号等待链表
579 }
580 /* If pendingflag & set > 0, shound clear pending flag */
581 sigset_t clear = sigcb->sigPendFlag & *set;
582 if (clear) {
583 sigcb->sigPendFlag ^= clear;
584 ret = FindFirstSetedBit((UINT64)clear) + 1;
585 OsMoveTmpInfoToUnbInfo(sigcb, ret);
586 } else {
587 OsSigAddSet(set, SIGKILL);//kill 9 14 必须要处理
588 OsSigAddSet(set, SIGSTOP);//终止进程的信号也必须处理
589
590 sigcb->sigwaitmask |= *set;//按位加到等待集上,也就是说sigwaitmask的信号来了都是要处理的.
591 OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
592 ret = task->ops->wait(task, &sigcb->waitList, timeout);
593 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
594 ret = -EAGAIN;
595 }
596 sigcb->sigwaitmask = NULL_SIGNAL_SET;
597 }
598 if (info != NULL) {
599 (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
600 }
601 return ret;
602}
603///让当前任务等待的信号
604int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
605{
606 int ret;
607 unsigned int intSave;
608
609 SCHEDULER_LOCK(intSave);
610
611 ret = OsSigTimedWaitNoLock(set, info, timeout);//以不加锁的方式等待
612
613 SCHEDULER_UNLOCK(intSave);
614 return ret;
615}
616///通过信号挂起当前任务
617int OsPause(void)
618{
619 LosTaskCB *spcb = NULL;
620 sigset_t oldSigprocmask;
621
622 spcb = OsCurrTaskGet();
623 oldSigprocmask = spcb->sig.sigprocmask;
624 return OsSigSuspend(&oldSigprocmask);
625}
626///用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
627int OsSigSuspend(const sigset_t *set)
628{
629 unsigned int intSave;
630 LosTaskCB *rtcb = NULL;
631 sigset_t setSuspend;
632 int ret;
633
634 if (set == NULL) {
635 return -EINVAL;
636 }
637 SCHEDULER_LOCK(intSave);
638 rtcb = OsCurrTaskGet();
639
640 /* Wait signal calc */
641 setSuspend = FULL_SIGNAL_SET & (~(*set));
642
643 /* If pending mask not in sigmask, need set sigflag */
644 OsSigMaskSwitch(rtcb, *set);
645
646 if (rtcb->sig.sigFlag > 0) {
647 SCHEDULER_UNLOCK(intSave);
648
649 /*
650 * If rtcb->sig.sigFlag > 0, it means that some signal have been
651 * received, and we need to do schedule to handle the signal directly.
652 */
653 LOS_Schedule();
654 return -EINTR;
655 } else {
656 ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
657 if (ret < 0) {
658 PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
659 }
660 }
661
662 SCHEDULER_UNLOCK(intSave);
663 return -EINTR;
664}
665
666/**
667 * @brief
668 * @verbatim
669 信号安装,函数用于改变进程接收到特定信号后的行为。
670 sig:信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。
671 act:设置对signal信号的新处理方式。
672 oldact:原来对信号的处理方式。
673 如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
674 返回值:0 表示成功,-1 表示有错误发生。
675 * @endverbatim
676 */
677int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
678{
679 UINTPTR addr;
680 sigaction_t action;
681
682 if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
683 return -EINVAL;
684 }
685 //将数据从用户空间拷贝到内核空间
686 if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
687 return -EFAULT;
688 }
689
690 if (sig == SIGSYS) {//鸿蒙此处通过错误的系统调用 来安装信号处理函数,有点巧妙.
691 addr = OsGetSigHandler();//是否已存在信号处理函数
692 if (addr == 0) {//进程没有设置信号处理函数时
693 OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);//设置进程信号处理函数
694 //void (*sa_handler)(int); //信号处理函数——普通版
695 //void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数——高级版
696 return LOS_OK;
697 }
698 return -EINVAL;
699 }
700
701 return LOS_OK;
702}
703
704VOID OsSigIntLock(VOID)
705{
706 LosTaskCB *task = OsCurrTaskGet();
707 sig_cb *sigcb = &task->sig;
708
709 (VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
710}
711
713{
714 LosTaskCB *task = OsCurrTaskGet();
715 sig_cb *sigcb = &task->sig;
716
717 (VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
718}
719
720/**
721 * @brief 保存信号上下文
722 * @verbatim
723 产生系统调用时,也就是软中断时,保存用户栈寄存器现场信息
724 改写PC寄存器的值
725 * @endverbatim
726 */
727VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
728{
729 UINTPTR sigHandler;
730 UINT32 intSave;
731 LosTaskCB *task = OsCurrTaskGet();
732 LosProcessCB *process = OsCurrProcessGet();
733 sig_cb *sigcb = &task->sig;
734
735 /* A thread is not allowed to interrupt the processing of its signals during a system call */
736 if (sigcb->sigIntLock > 0) {
737 return sp;
738 }
739
740 if (OsTaskIsKilled(task)) {
741 OsRunningTaskToExit(task, 0);
742 return sp;
743 }
744
745 SCHEDULER_LOCK(intSave);
746 if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
747 sigHandler = OsGetSigHandler();
748 if (sigHandler == 0) {
749 sigcb->sigFlag = 0;
750 process->sigShare = 0;
751 SCHEDULER_UNLOCK(intSave);
752 PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
753 return sp;
754 }
755 /* One pthread do the share signal */
756 sigcb->sigFlag |= process->sigShare;
757 UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1;
758 UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
759 OsMoveTmpInfoToUnbInfo(sigcb, signo);
760 OsProcessExitCodeSignalSet(process, signo);
761 sigcb->sigContext = sp;
762
763 OsInitSignalContext(sp, newSp, sigHandler, signo, sigVal);//初始化信号上下文
764
765 /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
766 sigcb->sigFlag ^= 1ULL << (signo - 1);
767 sigcb->count++;
768 SCHEDULER_UNLOCK(intSave);
769 return newSp;
770 }
771
772 SCHEDULER_UNLOCK(intSave);
773 return sp;
774}
775
776/**
777 * @brief
778 * @verbatim
779 恢复信号上下文,由系统调用之__NR_sigreturn产生,这是一个内部产生的系统调用.
780 为什么要恢复呢?
781 因为系统调用的执行由任务内核态完成,使用的栈也是内核栈,CPU相关寄存器记录的都是内核栈的内容,
782 而系统调用完成后,需返回任务的用户栈执行,这时需将CPU各寄存器回到用户态现场
783 所以函数的功能就变成了还原寄存器的值
784 * @endverbatim
785 */
787{
788 UINT32 intSave;
789
790 LosTaskCB *task = OsCurrTaskGet();
791 sig_cb *sigcb = &task->sig;
792
793 SCHEDULER_LOCK(intSave);
794 if (sigcb->count != 1) {
795 SCHEDULER_UNLOCK(intSave);
796 PRINT_ERR("sig error count : %d\n", sigcb->count);
797 return sp;
798 }
799
800 LosProcessCB *process = OsCurrProcessGet();
801 VOID *saveContext = sigcb->sigContext;
802 sigcb->sigContext = NULL;
803 sigcb->count--;
804 process->sigShare = 0; //回到用户态,信号共享清0
805 OsProcessExitCodeSignalClear(process);//清空进程退出码
806 SCHEDULER_UNLOCK(intSave);
807 return saveContext;
808}
809
810#endif
macro EXC_SP_SET reg1 mrc 获取CPU信息 and mov mul reg0 计算当前CPU栈的偏移位置 ldr reg1 相减得到栈顶 mov sp
Definition: asm.h:57
BOOL IsCapPermit(UINT32 capIndex)
Definition: capability.c:43
STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
Atomic addition.
Definition: los_atomic.h:173
STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
Atomic subtraction.
Definition: los_atomic.h:217
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
VOID LOS_Schedule(VOID)
Trigger active task scheduling.
Definition: los_sched.c:469
原子操作 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-atomic....
volatile INT32 Atomic
Definition: los_atomic.h:102
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
从哈希桶上删除快锁
Definition: los_futex.c:302
VOID OsInitSignalContext(const VOID *sp, VOID *signalContext, UINTPTR sigHandler, UINT32 signo, UINT32 param)
初始化信号上下文
Definition: los_hw.c:138
LITE_OS_SEC_TEXT INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission)
Definition: los_process.c:262
LITE_OS_SEC_TEXT VOID OsSetSigHandler(UINTPTR addr)
设置进程的信号处理函数
Definition: los_process.c:2259
LITE_OS_SEC_TEXT UINTPTR OsGetSigHandler(VOID)
获取进程的信号处理函数
Definition: los_process.c:2264
LITE_OS_SEC_TEXT INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission)
Definition: los_process.c:242
VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
Definition: los_process.c:326
STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)
进程不活跃函数定义:身上贴有不使用且不活跃标签的进程
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
STATIC INLINE VOID OsProcessExitCodeSignalSet(LosProcessCB *processCB, UINT32 signal)
设置进程退出信号(0 ~ 7)
STATIC INLINE VOID OsProcessExitCodeSignalClear(LosProcessCB *processCB)
清除进程退出信号(0 ~ 7)
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
STATIC INLINE BOOL OsProcessIDUserCheckInvalid(UINT32 pid)
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
VOID * OsSaveSignalContext(VOID *sp, VOID *newSp)
保存信号上下文
Definition: los_signal.c:727
void OsSigMaskSwitch(LosTaskCB *const rtcb, sigset_t set)
Definition: los_signal.c:211
int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
等待信号时间
Definition: los_signal.c:568
STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
唤醒被挂起的处于等待指定信号的任务
Definition: los_signal.c:131
int OsSigAddSet(sigset_t *set, int signo)
向信号集中加入signo信号
Definition: los_signal.c:527
int OsPause(void)
通过信号挂起当前任务
Definition: los_signal.c:617
int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
Definition: los_signal.c:677
VOID * OsRestorSignalContext(VOID *sp)
Definition: los_signal.c:786
STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
Definition: los_signal.c:77
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
给任务(线程)发送一个信号
Definition: los_signal.c:182
int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldsetl)
Definition: los_signal.c:233
STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
Definition: los_signal.c:143
int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
让进程的每一个task执行参数函数
Definition: los_signal.c:279
int OsSigEmptySet(sigset_t *set)
信号集全部清0
Definition: los_signal.c:392
VOID OsSigIntUnlock(VOID)
Definition: los_signal.c:712
static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend
Definition: los_signal.c:292
VOID OsClearSigInfoTmpList(sig_cb *sigcb)
Definition: los_signal.c:123
STATIC int FindFirstSetedBit(UINT64 n)
Definition: los_signal.c:557
int OsPthreadKill(UINT32 tid, int signo)
发送信号
Definition: los_signal.c:509
static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
Definition: los_signal.c:399
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
信号分发,发送信号权限/进程组过滤.
Definition: los_signal.c:412
int OsKillLock(pid_t pid, int sig)
给发送信号过程加锁
Definition: los_signal.c:480
int OsSigPending(sigset_t *set)
获取阻塞当前任务的信号集
Definition: los_signal.c:541
static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
进程收到 SIGKILL 信号后,通知任务tcb处理.
Definition: los_signal.c:337
VOID OsSigIntLock(VOID)
Definition: los_signal.c:704
int OsKill(pid_t pid, int sig, int permission)
Definition: los_signal.c:450
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
Definition: los_signal.c:345
int OsSigSuspend(const sigset_t *set)
用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
Definition: los_signal.c:627
INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
Definition: los_signal.c:490
int OsSigIsMember(const sigset_t *set, int signo)
判定信号signo是否存在信号集中。如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1
Definition: los_signal.c:62
STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
Definition: los_signal.c:96
int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
让当前任务等待的信号
Definition: los_signal.c:604
int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
给参数进程发送参数信号
Definition: los_signal.c:362
struct sigaction sigaction_t
Definition: los_signal.h:186
static int GOOD_SIGNO(unsigned int sig)
信号ID是否有效
Definition: los_signal.h:158
INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB)
Definition: los_task.c:1380
LITE_OS_SEC_TEXT VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status)
Definition: los_task.c:908
STATIC INLINE LosTaskCB * OsGetTaskCB(UINT32 taskID)
通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
Definition: los_task_pri.h:250
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
设置事件阻塞掩码,即设置任务的等待事件.
Definition: los_task_pri.h:289
STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
清除事件阻塞掩码,即任务不再等待任何事件.
Definition: los_task_pri.h:298
int(* ForEachTaskCB)(LosTaskCB *tcb, void *arg)
回调任务函数,例如:进程被kill 9 时,通知所有任务善后处理
Definition: los_task_pri.h:222
STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
Definition: los_task_pri.h:260
signed int INT32
Definition: los_typedef.h:60
long unsigned int UINT64
Definition: los_typedef.h:66
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
size_t bool
Definition: shell_list.h:44
struct LOS_DL_LIST * pstNext
Definition: los_list.h:84
sigset_t sigShare
UINT16 processStatus
User * user
进程的拥有者
LOS_DL_LIST threadSiblingList
ProcessGroup * group
LosTaskCB * defaultTcb
Definition: los_task_pri.h:216
LosTaskCB * unblockedTcb
Definition: los_task_pri.h:217
LosTaskCB * receivedTcb
Definition: los_task_pri.h:219
LosTaskCB * awakenedTcb
Definition: los_task_pri.h:218
siginfo_t * sigInfo
Definition: los_task_pri.h:215
UINT32(* wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout)
任务等待
VOID(* wake)(LosTaskCB *taskCB)
任务唤醒
siginfo_t info
Definition: los_signal.h:215
struct SigInfoListNode * next
Definition: los_signal.h:214
FutexNode futex
指明任务在等待哪把快锁,一次只等一锁,锁和任务的关系是(1:N)关系
sig_cb sig
信号控制块,用于异步通信,类似于 linux singal模块
UINT32 processID
const SchedOps * ops
UINT16 waitFlag
UINT32 userID
用户ID [0,60000],0为root用户
信号控制块(描述符)
Definition: los_signal.h:220
unsigned int sigIntLock
信号中断锁
Definition: los_signal.h:229
unsigned int count
信号数量
Definition: los_signal.h:231
SigInfoListNode * tmpInfoListHead
Definition: los_signal.h:228
sigset_t sigwaitmask
Definition: los_signal.h:226
sigset_t sigprocmask
Signals that are blocked | 任务屏蔽了哪些信号
Definition: los_signal.h:223
LOS_DL_LIST waitList
待链表,上面挂的是等待信号到来的任务, 请查找 OsTaskWait(&sigcb->waitList, timeout, TRUE) 理解
Definition: los_signal.h:225
sigset_t sigPendFlag
信号阻塞标签集,记录那些信号来过,任务依然阻塞的集合.即:这些信号不能唤醒任务
Definition: los_signal.h:222
siginfo_t sigunbinfo
Definition: los_signal.h:227
void * sigContext
信号上下文
Definition: los_signal.h:230
sigset_t sigFlag
不屏蔽的信号集
Definition: los_signal.h:221
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
size_t LOS_ArchCopyFromUser(void *dst, const void *src, size_t len)
Definition: user_copy.c:58