los_signal.h 11.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/*
 * 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 <stddef.h>
#include <limits.h>
#include <sys/types.h>
#include <signal.h>
#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
48 49 50 51 52

信号是Linux系统中用于进程间互相通信或者操作的一种机制,信号可以在任何时候发给某一进程,而无需知道该进程的状态。
如果该进程当前并未处于执行状态,则该信号就由内核保存起来,直到该进程被调度执行并传递给它为止。
如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

53
软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,
54 55
在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中异步通信机制,
一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
56 57 58 59 60 61 62 63 64 65
进程之间可以互相通过系统调用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)发出的退出指令
66
#define SIGIOT    SIGABRT //abort发出的信号
67 68
#define SIGBUS    7	//总线错误 
#define SIGFPE    8	//浮点异常
69
#define SIGKILL   9		//常用的命令 kill 9 123 | 不能被忽略、处理和阻塞
70 71 72 73 74
#define SIGUSR1   10	//用户自定义信号1 
#define SIGSEGV   11	//无效的内存引用, 段违例(segmentation     violation),进程试图去访问其虚地址空间以外的位置 
#define SIGUSR2   12	//用户自定义信号2
#define SIGPIPE   13	//向某个非读管道中写入数据 
#define SIGALRM   14	//由alarm(2)发出的信号,默认行为为进程终止
75 76
#define SIGTERM   15	//终止信号
#define SIGSTKFLT 16	//栈溢出
77 78
#define SIGCHLD   17	//子进程结束信号
#define SIGCONT   18	//进程继续(曾被停止的进程)
79
#define SIGSTOP   19	//终止进程  	 | 不能被忽略、处理和阻塞
80
#define SIGTSTP   20	//控制终端(tty)上 按下停止键
81 82 83 84 85 86 87 88 89 90 91
#define SIGTTIN   21	//进程停止,后台进程企图从控制终端读
#define SIGTTOU   22	//进程停止,后台进程企图从控制终端写
#define SIGURG    23	//I/O有紧急数据到达当前进程
#define SIGXCPU   24	//进程的CPU时间片到期
#define SIGXFSZ   25	//文件大小的超出上限
#define SIGVTALRM 26	//虚拟时钟超时
#define SIGPROF   27	//profile时钟超时
#define SIGWINCH  28	//窗口大小改变
#define SIGIO     29	//I/O相关
#define SIGPOLL   29	//
#define SIGPWR    30	//电源故障,关机
92
#define SIGSYS    31	//系统调用中参数错,如系统调用号非法 
93
#define SIGUNUSED SIGSYS		//系统调用异常
94 95 96 97 98 99 100 101 102 103 104 105 106

#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

107 108
#define OS_KERNEL_KILL_PERMISSION 0U	//内核态 kill 权限
#define OS_USER_KILL_PERMISSION   3U	//用户态 kill 权限
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147

#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))
148 149 150
#define NULL_SIGNAL_SET ((sigset_t)0ULL)	//信号集全部清0
#define FULL_SIGNAL_SET ((sigset_t)~0ULL)	//信号集全部置1
//信号ID是否有效
151 152 153 154 155 156 157 158 159 160
static inline int GOOD_SIGNO(unsigned int sig)
{
    return (sig < _NSIG) ? 1 : 0;// 
}
/********************************************************************
Musl官网 http://musl.libc.org/ 
musl是构建在Linux系统调用API之上的C标准库的实现,包括在基本语言标准POSIX中定义的接口,
以及广泛认可的扩展。musl是轻量级的,快速的,简单的,自由的.
********************************************************************/

161
#define MAX_SIG_ARRAY_IN_MUSL 128 //128个信号
162 163 164 165 166

typedef struct {
    unsigned long sig[MAX_SIG_ARRAY_IN_MUSL / sizeof(unsigned long)];
} sigset_t_l;

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
/***************************************************
struct sigaction {
	union {
		void (*sa_handler)(int); //信号处理函数——普通版
		void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数——高级版
	} __sa_handler;
	sigset_t sa_mask;//指定信号处理程序执行过程中需要阻塞的信号;
	int sa_flags;	 //标示位
					 //	SA_RESTART:使被信号打断的syscall重新发起。
					 //	SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
					 //	SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到SIGCHLD信号,这时子进程如果退出也不会成为僵 尸进程。
					 //	SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
					 //	SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
					 //	SA_SIGINFO:使用sa_sigaction成员而不是sa_handler作为信号处理函数。
	void (*sa_restorer)(void);
};
****************************************************/
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
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;

205
struct sq_queue_s {//信号队列
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
    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;

222
typedef struct {//中断上下文
223 224 225 226 227
    TASK_IRQ_CONTEXT
} TaskIrqDataSize;

typedef struct {//信号切换上下文
    TASK_IRQ_CONTEXT
228
    unsigned int R7;	//存放系统调用的ID
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
229
    unsigned int count;	//记录是否保存了任务上下文
230 231 232
} sig_switch_context;

typedef struct {//信号控制块(描述符)
233
    sigset_t sigFlag;		//信号标签集
234
    sigset_t sigPendFlag;	//信号阻塞标签集,记录因哪些信号被阻塞
235 236
    sigset_t sigprocmask; /* Signals that are blocked            */	//进程屏蔽了哪些信号
    sq_queue_t sigactionq;	//信号捕捉队列					
237
    LOS_DL_LIST waitList;	//等待链表,上面挂的是等待信号到来的任务, 请查找 OsTaskWait(&sigcb->waitList, timeout, TRUE)	理解						
238 239
    sigset_t sigwaitmask; /* Waiting for pending signals         */	//任务在等待阻塞信号
    siginfo_t sigunbinfo; /* Signal info when task unblocked     */	//任务解锁时的信号信息
240
    sig_switch_context context;	//信号切换上下文, 用于保存切换现场, 比如发生系统调用时的返回,涉及同一个任务的两个栈进行切换							
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
} 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 */