3 回答

TA貢獻1848條經(jīng)驗 獲得超10個贊
printf()
調(diào)用所有函數(shù)并不安全,例如 printf
,在信號處理程序中。一種有用的技術(shù)是使用信號處理程序來設(shè)置 flag
然后檢查一下 flag
從主程序中打印一條消息,如果需要的話。
alarm_fired
alarm_fired
static int alarm_fired = 0;void ding(int sig) // can be called asynchronously{ alarm_fired = 1; // set flag}int main(){ pid_t pid; printf("alarm application starting\n"); pid = fork(); switch(pid) { case -1: /* Failure */ perror("fork failed"); exit(1); case 0: /* child */ sleep(5); kill(getppid(), SIGALRM); exit(0); } /* if we get here we are the parent process */ printf("waiting for alarm to go off\n"); (void) signal(SIGALRM, ding); pause(); if (alarm_fired) // check flag to call printf printf("Ding!\n"); printf("done\n"); exit(0);}
volatile sigatomic_t
signal()
sigaction()

TA貢獻1803條經(jīng)驗 獲得超3個贊
malloc()
malloc()
ISO/IEC 9899:2011§7.14.1.1 signal
功能
5如果信號發(fā)生時不是由于調(diào)用 abort
或 raise
函數(shù)時,如果信號處理程序引用任何具有靜態(tài)或線程存儲持續(xù)時間的對象,而該對象不是無鎖原子對象,則行為是未定義的,除非將值賦值給聲明為 volatile sig_atomic_t
,或者信號處理程序調(diào)用標(biāo)準(zhǔn)庫中的除 abort
函數(shù) _Exit
函數(shù) quick_exit
函數(shù),或 signal
函數(shù)的第一個參數(shù)等于與導(dǎo)致調(diào)用處理程序的信號對應(yīng)的信號。此外,如果對 signal
函數(shù)的結(jié)果是 SIG_ERR
返回值 errno
是不確定的。 252)252)
如果任何信號是由異步信號處理程序生成的,則該行為是未定義的。
如果進程是多線程的,或者進程是單線程的,并且執(zhí)行信號處理程序的結(jié)果是:
進程調(diào)用 abort()
,raise()
,kill()
,pthread_kill()
,或 sigqueue()
若要生成未被阻塞的信號,請執(zhí)行以下操作
正在解除阻塞并在解除阻塞的調(diào)用返回之前傳遞的掛起信號
如果信號處理程序引用除 errno
使用靜態(tài)存儲持續(xù)時間,而不是將值賦值給聲明為 volatile sig_atomic_t
,或者如果信號處理程序調(diào)用在此標(biāo)準(zhǔn)中定義的除下表所列函數(shù)之外的任何函數(shù)。
下表定義了一組應(yīng)該是異步信號安全的函數(shù).因此,應(yīng)用程序可以不受限制地從信號捕獲函數(shù)調(diào)用它們: _Exit() fexecve() posix_trace_event() sigprocmask()_exit() fork() pselect() sigqueue()…fcntl() pipe() sigpause() write()fdatasync() poll() sigpending()
上表中沒有的所有功能都被認(rèn)為在信號方面是不安全的。在信號存在的情況下,本卷POSIX.1-2008所定義的所有函數(shù)在從信號捕捉函數(shù)調(diào)用或被信號捕獲函數(shù)中斷時都應(yīng)表現(xiàn)為定義的功能,但有一個例外:當(dāng)信號中斷不安全的函數(shù),而信號捕捉函數(shù)調(diào)用不安全的函數(shù)時,則行為未定義。
獲得以下值的操作: errno
和將值賦值給 errno
應(yīng)該是異步信號安全的。
當(dāng)信號被傳遞到線程時,如果該信號的動作指定終止、停止或繼續(xù),則整個進程將分別終止、停止或繼續(xù)。
printf()
<string.h>
_Exit() getppid() sendmsg() tcgetpgrp()
_exit() getsockname() sendto() tcsendbreak()
abort() getsockopt() setgid() tcsetattr()
accept() getuid() setpgid() tcsetpgrp()
access() htonl() setsid() time()
aio_error() htons() setsockopt() timer_getoverrun()
aio_return() kill() setuid() timer_gettime()
aio_suspend() link() shutdown() timer_settime()
alarm() linkat() sigaction() times()
bind() listen() sigaddset() umask()
cfgetispeed() longjmp() sigdelset() uname()
cfgetospeed() lseek() sigemptyset() unlink()
cfsetispeed() lstat() sigfillset() unlinkat()
cfsetospeed() memccpy() sigismember() utime()
chdir() memchr() siglongjmp() utimensat()
chmod() memcmp() signal() utimes()
chown() memcpy() sigpause() wait()
clock_gettime() memmove() sigpending() waitpid()
close() memset() sigprocmask() wcpcpy()
connect() mkdir() sigqueue() wcpncpy()
creat() mkdirat() sigset() wcscat()
dup() mkfifo() sigsuspend() wcschr()
dup2() mkfifoat() sleep() wcscmp()
execl() mknod() sockatmark() wcscpy()
execle() mknodat() socket() wcscspn()
execv() ntohl() socketpair() wcslen()
execve() ntohs() stat() wcsncat()
faccessat() open() stpcpy() wcsncmp()
fchdir() openat() stpncpy() wcsncpy()
fchmod() pause() strcat() wcsnlen()
fchmodat() pipe() strchr() wcspbrk()
fchown() poll() strcmp() wcsrchr()
fchownat() posix_trace_event() strcpy() wcsspn()
fcntl() pselect() strcspn() wcsstr()
fdatasync() pthread_kill() strlen() wcstok()
fexecve() pthread_self() strncat() wmemchr()
ffs() pthread_sigmask() strncmp() wmemcmp()
fork() raise() strncpy() wmemcpy()
fstat() read() strnlen() wmemmove()
fstatat() readlink() strpbrk() wmemset()
fsync() readlinkat() strrchr() write()
ftruncate() recv() strspn()
futimens() recvfrom() strstr()
getegid() recvmsg() strtok_r()
geteuid() rename() symlink()
getgid() renameat() symlinkat()
getgroups() rmdir() tcdrain()
getpeername() select() tcflow()
getpgrp() sem_post() tcflush()
getpid() send() tcgetattr()
write()
printf()
標(biāo)準(zhǔn)C功能和信號安全
為什么大多數(shù)字符串函數(shù)都是從 <string.h>
的字符類函數(shù)。 <ctype.h>
還有更多的C標(biāo)準(zhǔn)庫函數(shù)不在上面的列表中嗎?實現(xiàn)需要有目的邪惡才能實現(xiàn)。 strlen()
從信號處理程序調(diào)用不安全。
<string.h>
strlen()
strchr()
, strstr()
strtok()
, strcoll()
strxfrm()
strtok()
strtok()
strcoll()
strxfrm()
<ctype.h>
strcoll()
strxfrm()
.
<math.h>
<complex.h>
, <fenv.h>
<tgmath.h>
.
<stdlib.h>
abs()
malloc()
<assert.h>
— 可能不安全<complex.h>
— 可能安全<ctype.h>
-不安全 <errno.h>
-安全 <fenv.h>
— 可能不安全<float.h>
-沒有職能 <inttypes.h>
-區(qū)域敏感功能(不安全) <iso646.h>
-沒有職能 <limits.h>
-沒有職能 <locale.h>
-區(qū)域敏感功能(不安全) <math.h>
— 可能安全<setjmp.h>
-不安全 <signal.h>
-允許 <stdalign.h>
-沒有職能 <stdarg.h>
-沒有職能 <stdatomic.h>
— 可能安全,可能不安全<stdbool.h>
-沒有職能 <stddef.h>
-沒有職能 <stdint.h>
-沒有職能 <stdio.h>
-不安全 <stdlib.h>
-并非所有的安全(有些是允許的;另一些是不允許的) <stdnoreturn.h>
-沒有職能 <string.h>
-并非所有的安全 <tgmath.h>
— 可能安全<threads.h>
— 可能不安全<time.h>
-地點依賴性(但 time()
顯式允許) <uchar.h>
-地點依賴性 <wchar.h>
-地點依賴性 <wctype.h>
-地點依賴性
<pthread.h>

TA貢獻1828條經(jīng)驗 獲得超3個贊
如何避免使用 printf
在信號處理器里?
總是避開它,會說:只是不要用 printf()
在信號處理程序中。 至少在POSIX一致性系統(tǒng)上,您可以使用 write(STDOUT_FILENO, ...)
而不是 printf()
..然而,格式化可能并不容易: 使用寫或異步安全函數(shù)從信號處理程序打印int
添加回答
舉報