日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux_unix编程手册--信号处理函数

發布時間:2025/3/15 linux 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux_unix编程手册--信号处理函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

全部的代碼都已上傳github 地址:https://github.com/zzu-andrew/linux_unix

一般而言信號處理函數設計的越簡單越好,其中最主要的原因就是降低引發競爭條件的風險。
更新全局變量或靜態數據結構的函數可能是不可重入的。(只用到本地變量的函數肯定是可重入的),
將靜態數據結構用于內部記賬的函數也是不可重入的,其中最明顯的例子就是stdio.h函數哭成員(printf()、scanf()等),他們會為緩沖區I/O更新內部數據結構。所以如果在信號處理函數中調用printf()函數又在主程序中又調用printf或者其他的stdio函數,就有可能出現奇怪的輸出。

![在這里插入圖片描述](https://img-blog.csdnimg.cn/2018120

/*************************************************************************\ * Copyright (C) Michael Kerrisk, 2018. * * * * This program is free software. You may use, modify, and redistribute it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation, either version 3 or (at your option) any * * later version. This program is distributed without any warranty. See * * the file COPYING.gpl-v3 for details. * \*************************************************************************//* Listing 21-1 *//* nonreentrant.cDemonstrate the nonreentrant nature of some library functions, in thisexample, crypt(3). */ #if ! defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600 #define _XOPEN_SOURCE 600 #endif #include <unistd.h> #include <signal.h> #include <string.h> #include "tlpi_hdr.h"static char *str2; /* Set from argv[2] */ static int handled = 0; /* Counts number of calls to handler */static void handler(int sig) {crypt(str2, "xx");handled++; }int main(int argc, char *argv[]) {char *cr1;int callNum, mismatch;struct sigaction sa;if (argc != 3)usageErr("%s str1 str2\n", argv[0]);str2 = argv[2]; /* Make argv[2] available to handler */cr1 = strdup(crypt(argv[1], "xx")); /* Copy statically allocated stringto another buffer */if (cr1 == NULL)errExit("strdup");sigemptyset(&sa.sa_mask);sa.sa_flags = 0;sa.sa_handler = handler;if (sigaction(SIGINT, &sa, NULL) == -1)errExit("sigaction");/* Repeatedly call crypt() using argv[1]. If interrupted by asignal handler, then the static storage returned by crypt()will be overwritten by the results of encrypting argv[2], andstrcmp() will detect a mismatch with the value in 'cr1'. *//*** @brief 正常情況下,處理同一個字符得出的結果肯定是相同的,但是當捕捉到Crt+C之后就會出現不一樣的結果,因為信號處理函數中斷了加密函數的執行* @note 因此一旦捕捉到信號就會,進入到if判斷條件,出現打印的結果* @param 1: * @param callNum++: * @retval */for (callNum = 1, mismatch = 0; ; callNum++) {if (strcmp(crypt(argv[1], "xx"), cr1) != 0) {mismatch++;printf("Mismatch on call %d (mismatch=%d handled=%d)\n",callNum, mismatch, handled);}} }


然而使用標準的longjmp()函數從處理器函數中退出存在一個問題,在進入信號處理函數時,內核會自動的將引發調用的信號以及由act.sa_mask所指定的任意信號添加到進程的信號掩碼中,并在處理器函數正常返回時將它們從掩碼中清除,如果使用longjmp()退出信號處理函數將會引發?   由UNIX實現的血統決定Linux準許你System-V當信號處理函數從longjmp退出之后,不會將信號掩碼回復,亦即在離開處理器函數時不會對阻塞的信號接觸阻塞

/*************************************************************************\ * Copyright (C) Michael Kerrisk, 2018. * * * * This program is free software. You may use, modify, and redistribute it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation, either version 3 or (at your option) any * * later version. This program is distributed without any warranty. See * * the file COPYING.gpl-v3 for details. * \*************************************************************************//* Listing 21-2 *//* sigmask_longjmp.cDemonstrate the different effects of longjmp() and siglongjmp()on the process signal mask.By default, this program uses setjmp() + longjmp(). Compile with-DUSE_SIGSETJMP to use sigsetjmp() + siglongjmp(). */#define _GNU_SOURCE /* Get strsignal() declaration from <string.h> */ #include <string.h> #include <setjmp.h> #include <signal.h> #include "signal_functions.h" /* Declaration of printSigMask() */ #include "tlpi_hdr.h"static volatile sig_atomic_t canJump = 0;/* Set to 1 once "env" buffer has beeninitialized by [sig]setjmp() */ #ifdef USE_SIGSETJMP static sigjmp_buf senv; #else static jmp_buf env; #endifstatic void handler(int sig) {/* UNSAFE: This handler uses non-async-signal-safe functions(printf(), strsignal(), printSigMask(); see Section 21.1.2) */printf("Received signal %d (%s), signal mask is:\n", sig,strsignal(sig));printSigMask(stdout, NULL);if (!canJump) {printf("'env' buffer not yet set, doing a simple return\n");return;}#ifdef USE_SIGSETJMPsiglongjmp(senv, 1); #elselongjmp(env, 1); #endif }int main(int argc, char *argv[]) {struct sigaction sa;printSigMask(stdout, "Signal mask at startup:\n");sigemptyset(&sa.sa_mask);sa.sa_flags = 0;sa.sa_handler = handler;if (sigaction(SIGINT, &sa, NULL) == -1)errExit("sigaction");#ifdef USE_SIGSETJMPprintf("Calling sigsetjmp()\n");if (sigsetjmp(senv, 1) == 0) #elseprintf("Calling setjmp()\n");if (setjmp(env) == 0) #endifcanJump = 1; /* Executed after [sig]setjmp() */else /* Executed after [sig]longjmp() */printSigMask(stdout, "After jump from handler, signal mask is:\n" );for (;;) /* Wait for signals until killed */pause(); }

若是定義了USE_SIGSETJMP 宏

異常終止進程:abort()

函數與abort()終止其調用進程,并生成核心轉儲
void abort(void);

int sigaltstack(const stack_t *ss, stack_t *oss);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

在備選棧中處理信號sigaltstack

sigaltstack函數的作用就是即使函數的棧溢出也能夠調用信號處理函數

/*************************************************************************\ * Copyright (C) Michael Kerrisk, 2018. * * * * This program is free software. You may use, modify, and redistribute it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation, either version 3 or (at your option) any * * later version. This program is distributed without any warranty. See * * the file COPYING.gpl-v3 for details. * \*************************************************************************//* Listing 21-3 *//* t_sigaltstack.cDemonstrate the use of sigaltstack() to handle a signal on an alternatesignal stack. */ #define _GNU_SOURCE /* Get strsignal() declaration from <string.h> */ #include <string.h> #include <signal.h> #include "tlpi_hdr.h"static void sigsegvHandler(int sig) {int x;/* UNSAFE: This handler uses non-async-signal-safe functions(printf(), strsignal(), fflush(); see Section 21.1.2) */printf("Caught signal %d (%s)\n", sig, strsignal(sig));printf("Top of handler stack near %10p\n", (void *) &x);fflush(NULL);_exit(EXIT_FAILURE); /* Can't return after SIGSEGV */ }/* The following stops 'gcc -Wall' complaining that "control reachesend of non-void function" because we don't follow the call tooverflowStack() stack in main() with a call to exit(). */#ifdef __GNUC__ static void overflowStack(int callNum) __attribute__ ((__noreturn__)); #endifstatic void /* A recursive function that overflows the stack */ overflowStack(int callNum) //連續調用知道程序的棧溢出 {char a[100000]; /* Make this stack frame large */printf("Call %4d - top of stack near %10p\n", callNum, &a[0]);overflowStack(callNum+1); }int main(int argc, char *argv[]) {stack_t sigstack;struct sigaction sa;int j;printf("Top of standard stack is near %10p\n", (void *) &j);/* Allocate alternate stack and inform kernel of its existence */sigstack.ss_sp = malloc(SIGSTKSZ);if (sigstack.ss_sp == NULL)errExit("malloc");sigstack.ss_size = SIGSTKSZ;sigstack.ss_flags = 0;if (sigaltstack(&sigstack, NULL) == -1)errExit("sigaltstack");printf("Alternate stack is at %10p-%p\n",sigstack.ss_sp, (char *) sbrk(0) - 1);sa.sa_handler = sigsegvHandler; /* Establish handler for SIGSEGV */sigemptyset(&sa.sa_mask);sa.sa_flags = SA_ONSTACK; /* Handler uses alternate stack */if (sigaction(SIGSEGV, &sa, NULL) == -1)errExit("sigaction");overflowStack(1); }

可見上述函數就算棧溢出,信號處理器也能夠正常的執行

$ ./t_sigaltstack Top of standard stack is near 0x7ffd2c51877c Alternate stack is at 0x1f83420-0x1fa3fff Call 1 - top of stack near 0x7ffd2c5000a0 Call 2 - top of stack near 0x7ffd2c4e79d0 Call 3 - top of stack near 0x7ffd2c4cf300 Call 4 - top of stack near 0x7ffd2c4b6c30 Call 5 - top of stack near 0x7ffd2c49e560 . . . Call 77 - top of stack near 0x7ffd2bdbfae0 Call 78 - top of stack near 0x7ffd2bda7410 Call 79 - top of stack near 0x7ffd2bd8ed40 Call 80 - top of stack near 0x7ffd2bd76670 Call 81 - top of stack near 0x7ffd2bd5dfa0 Call 82 - top of stack near 0x7ffd2bd458d0 Call 83 - top of stack near 0x7ffd2bd2d200 Caught signal 11 (Segmentation fault) Top of handler stack near 0x1f84ee4 andrew@andrew-Thurley:/work/svn_linux/linux_unix/sys

總結

以上是生活随笔為你收集整理的linux_unix编程手册--信号处理函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。