linux手册翻译——sigaltstack(2)

\color{#A00000}{NAME}
sigaltstack - set or/and get 信号的堆栈上下文

\color{#A00000}{SYNOPSIS}

       #include <signal.h>
       int sigaltstack(const stack_t *restrict ss, stack_t *restrict old_ss);

       Feature Test Macro Requirements for glibc (see
       feature_test_macros(7)):

       sigaltstack():
           _XOPEN_SOURCE >= 500
               || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
               || /* Glibc <= 2.19: */ _BSD_SOURCE

\color{#A00000}{DESCRIPTION}
sigaltstack() 允许线程定义新的备用信号堆栈和/或获取现有备用信号堆栈的状态。如果信号处理程序的建立(请参阅 sigaction(2))指定使用备用堆栈,即设置了SA_ONSTACK参数,则在信号处理程序的执行期间使用备用信号堆栈。
使用备用信号堆栈的一般步骤如下:

  1. 分配一块内存区域用于备用信号堆栈。
  2. 使用 sigaltstack() 通知系统备用信号堆栈的存在和位置。
  3. 使用 sigaction(2) 建立信号处理程序时,通过指定 SA_ONSTACK 标志通知系统应在备用信号堆栈上执行信号处理程序。

ss 参数用于指定新的备用信号堆栈,而 old_ss 参数用于获取有关当前建立的信号堆栈的信息。如果我们只对执行其中一项任务感兴趣,则可以将另一个参数指定为 NULL。

stack_t 类型定义如下:

           typedef struct {
               void  *ss_sp;     /* Base address of stack */
               int    ss_flags;  /* Flags */
               size_t ss_size;   /* Number of bytes in stack */
           } stack_t;

ss.ss_flags

此字段包含 0 或以下标志,此字段也是必须要配置的,起码要是0,否则将会备用栈配置会无效

  • SS_AUTODISARM (since Linux 4.7)
    在进入信号处理程序之前,清楚对备用信号栈的设置,并在信号处理程序返回时恢复。
    添加此标志是为了使使用 swapcontext(3) 从信号处理程序中切换出来是安全的。 如果没有这个标志,随后处理的信号将破坏切换离开的信号处理程序的状态。 在不支持此标志的内核上,提供此标志时 sigaltstack() 会失败并显示错误 EINVAL。
    根据我的理解是,如果没有这个标志,那么每一个信号都将使用备用栈,如果当前正在处理信号处理程序,那么当前的rsp指向的是备用信号堆栈的栈顶,如果此时新的信号到达,那么将继续使用备用栈,没有问题,但是如果在执行信号处理程序时用swapcontext切换了出去,那么rsp将不再指向备用堆栈,此时若新的信号到达,则将从信号备用栈的顶端开始使用,这样就会出现后来的信号处理程序覆盖前面处理程序栈的情况。

ss.ss_sp

该字段指定堆栈的起始地址。 当在备用堆栈上调用信号处理程序时,内核会自动将 ss.ss_sp 中给出的地址与底层硬件架构的合适地址边界对齐。

ss.ss_size

此字段指定堆栈的大小。 常量 SIGSTKSZ(8KB)定义了足够满足信号堆栈的通常大小要求的栈空间大小,常量 MINSIGSTKSZ(2KB)定义执行信号处理程序所需的最小大小。

要禁用现有备用信号堆栈,请将 ss.ss_flags 指定为 SS_DISABLE。 在这种情况下,内核会忽略 ss.ss_flags 中的任何其他标志以及 ss 中的其余字段。即若ss.ss_flags指定了SS_DISABLE,那么就停用备用信号堆栈

如果 old_ss 不为 NULL,则它用于返回有关在调用 sigaltstack() 之前生效的备用信号堆栈的信息。 old_ss.ss_sp 和 old_ss.ss_size 字段返回该堆栈的起始地址和大小。 old_ss.ss_flags 可能返回以下任一值:

  • SS_ONSTACK
    该线程当前正在备用信号堆栈上执行,即正在备用栈上执行信号处理程序。 (请注意,如果线程当前正在其上执行,则无法更改备用信号堆栈。)
  • SS_DISABLE
    备用信号堆栈当前已禁用,线程当前正在使用 SS_AUTODISARM 标志建立的备用信号堆栈上执行。 在这种情况下,使用 swapcontext(3) 切换信号处理程序是安全的。 还可以使用对 sigaltstack() 的进一步调用来设置不同的替代信号堆栈。
  • SS_AUTODISARM
    如上所述,备用信号堆栈已被标记为AUTODISARM。

通过将 ss 指定为 NULL,并将 old_ss 指定为非 NULL 值,可以获得备用信号堆栈的当前设置而无需更改它们。
\color{#A00000}{RETURN VALUE}
sigaltstack() 成功时返回 0,失败时返回 -1,并设置 errno 以指示错误。

\color{#A00000}{ERRORS}
EFAULT
ss 或 old_ss 不为 NULL 并指向进程地址空间之外的区域。

EINVAL
ss 不是 NULL 并且 ss_flags 字段包含无效标志。

ENOMEM
新备用信号堆栈 ss.ss_size 的指定大小小于 MINSIGSTKSZ。

EPERM
尝试在备用信号堆栈处于活动状态时更改它(即,线程已经在当前备用信号堆栈上执行)。

\color{#A00000}{ATTRIBUTES}

Interface Attribute Value
sigaltstack() Thread safety MT-Safe

\color{#A00000}{NOTES}
备用信号堆栈最常见的用法是处理标准堆栈可用空间耗尽时生成的 SIGSEGV 信号:在这种情况下,无法在标准堆栈上调用 SIGSEGV 的信号处理程序;如果我们想处理它,我们必须使用备用信号堆栈。
如果线程可能耗尽其标准堆栈,则建立备用信号堆栈很有用。堆栈增长得太大以至于遇到向上增长的堆,或者它达到了调用 setrlimit(RLIMIT_STACK, &rlim) 设置的限制,都意味着标准的堆栈被用尽,此时内核会向线程发送一个 SIGSEGV 信号。在这些情况下,捕获此信号的唯一方法是在备用信号堆栈上。

在 Linux 支持的大多数硬件架构上,堆栈向下增长。 sigaltstack() 自动考虑堆栈增长的方向。

从在备用信号堆栈上执行的信号处理程序时调用的函数或者触发新的信号处理函数都将使用备用信号堆栈。与标准堆栈不同,系统不会自动扩展备用信号堆栈。超过备用信号堆栈的分配大小将导致不可预测的结果。

成功调用 execve(2) 会删除任何现有的备用信号堆栈。通过 fork(2) 或clone(2)创建的子进程继承其父进程的备用信号堆栈设置的副本。但是对于clone(2)创建的线程,将禁用在父进程中建立的任何备用信号堆栈。

sigaltstack() 取代了旧的 sigstack() 调用。为了向后兼容,glibc 还提供了 sigstack()。所有新应用程序都应使用 sigaltstack() 编写。历史 4.2BSD 有一个 sigstack() 系统调用。它使用了一个稍微不同的结构,主要的缺点是调用者必须知道堆栈增长的方向。

\color{#A00000}{BUGS}
在 Linux 2.2 及更早版本中,唯一可以在 ss.sa_flags 中指定的标志是 SS_DISABLE。 在 Linux 2.4 内核发布之前,进行了更改以允许 sigaltstack() 允许 ss.ss_flags==SS_ONSTACK 具有与 ss.ss_flags==0 相同的含义(即,将 SS_ONSTACK 包含在 ss .ss_flags 是空操作)。 在其他实现中,根据 POSIX.1,SS_ONSTACK 仅作为 old_ss.ss_flags 中的报告标志出现。 在 Linux 上,没有必要在 ss.ss_flags 中指定 SS_ONSTACK,并且确实应该出于可移植性考虑避免这样做:如果 SS_ONSTACK 在 ss.ss_flags 中指定,则其他各种系统都会出错。

\color{#A00000}{EXAMPLES}
以下代码段演示了如何使用 sigaltstack()(和 sigaction(2))来安装备用信号堆栈,该堆栈由 SIGSEGV 信号的处理程序使用:

           stack_t ss;

           ss.ss_sp = malloc(SIGSTKSZ);
           if (ss.ss_sp == NULL) {
               perror("malloc");
               exit(EXIT_FAILURE);
           }

           ss.ss_size = SIGSTKSZ;
           ss.ss_flags = 0;
           if (sigaltstack(&ss, NULL) == -1) {
               perror("sigaltstack");
               exit(EXIT_FAILURE);
           }

           sa.sa_flags = SA_ONSTACK;
           sa.sa_handler = handler();      /* Address of a signal handler */
           sigemptyset(&sa.sa_mask);
           if (sigaction(SIGSEGV, &sa, NULL) == -1) {
               perror("sigaction");
               exit(EXIT_FAILURE);
           }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容