首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >linux允许从信号处理程序进行任何系统调用吗?

linux允许从信号处理程序进行任何系统调用吗?
EN

Stack Overflow用户
提问于 2012-07-27 01:48:16
回答 2查看 9.9K关注 0票数 21

我的理解是,通常情况下,如果从信号处理程序调用非异步信号安全函数,行为是未定义的,但我听说linux允许您安全地调用任何系统调用。这是真的吗?此外,SIGSEGV处理程序的唯一可移植行为是中止或退出,但我知道如果您返回,linux实际上将恢复执行,对吗?

EN

回答 2

Stack Overflow用户

发布于 2012-07-27 01:57:08

根据section 2 signal manual的说法

有关可从信号处理程序内部安全调用的异步信号安全函数的列表,请参见signal(7)。

section 7 signals manual列出了以下函数和/或系统调用,并提供了非常清晰的描述:

异步信号安全函数

代码语言:javascript
复制
   A signal handler function must be very careful, since processing elsewhere may
   be interrupted at some arbitrary point in the execution of the program.  POSIX
   has the concept of "safe function".  If a signal interrupts the execution of
   an unsafe function, and handler calls an unsafe function, then the behavior of
   the program is undefined.

   POSIX.1-2004 (also known as POSIX.1-2001 Technical Corrigendum 2) requires an
   implementation to guarantee that the following functions can be safely called
   inside a signal handler:

       _Exit()
       _exit()
       abort()
       accept()
       access()
       aio_error()
       aio_return()
       aio_suspend()
       alarm()
       bind()
       cfgetispeed()
       cfgetospeed()
       cfsetispeed()
       cfsetospeed()
       chdir()
       chmod()
       chown()
       clock_gettime()
       close()
       connect()
       creat()
       dup()
       dup2()
       execle()
       execve()
       fchmod()
       fchown()
       fcntl()
       fdatasync()
       fork()
       fpathconf()
       fstat()
       fsync()
       ftruncate()
       getegid()
       geteuid()
       getgid()
       getgroups()
       getpeername()
       getpgrp()
       getpid()
       getppid()
       getsockname()
       getsockopt()
       getuid()
       kill()
       link()
       listen()
       lseek()
       lstat()
       mkdir()
       mkfifo()
       open()
       pathconf()
       pause()
       pipe()
       poll()
       posix_trace_event()
       pselect()
       raise()
       read()
       readlink()
       recv()
       recvfrom()
       recvmsg()
       rename()
       rmdir()
       select()
       sem_post()
       send()
       sendmsg()
       sendto()
       setgid()
       setpgid()
       setsid()
       setsockopt()
       setuid()
       shutdown()
       sigaction()
       sigaddset()
       sigdelset()
       sigemptyset()
       sigfillset()
       sigismember()
       signal()
       sigpause()
       sigpending()
       sigprocmask()
       sigqueue()
       sigset()
       sigsuspend()
       sleep()
       sockatmark()
       socket()
       socketpair()
       stat()
       symlink()
       sysconf()
       tcdrain()
       tcflow()
       tcflush()
       tcgetattr()
       tcgetpgrp()
       tcsendbreak()
       tcsetattr()
       tcsetpgrp()
       time()
       timer_getoverrun()
       timer_gettime()
       timer_settime()
       times()
       umask()
       uname()
       unlink()
       utime()
       wait()
       waitpid()
       write()

   POSIX.1-2008 removes fpathconf(), pathconf(), and sysconf() from the above
   list, and adds the following functions:

       execl()
       execv()
       faccessat()
       fchmodat()
       fchownat()
       fexecve()
       fstatat()
       futimens()
       linkat()
       mkdirat()
       mkfifoat()
       mknod()
       mknodat()
       openat()
       readlinkat()
       renameat()
       symlinkat()
       unlinkat()
       utimensat()
       utimes()

我相信这个信息比我们有时在某些地方听到的东西更可靠。所以Linux只允许某些系统调用,但不允许所有系统调用。所以你的问题的答案很简单--不。

票数 21
EN

Stack Overflow用户

发布于 2012-07-27 16:19:09

是也不是

是:

您可以在信号处理程序中调用任何真实/原始的syscall。内核有责任确保它是安全的(从内核的角度来看)。

1)内核不知道用户空间的上下文,或者说内核在发送信号时将状态保存到用户空间后故意忘记了它。(注意:执行恢复是由用户在保存状态的帮助下通过syscall完成的,而不是真正由内核完成的,内核已经忘记了)

2)一些线程库是通过单线程实现的,所以线程已经在“信号处理器”中,但这些线程可以调用任何syscall。

否:

但是用户空间函数有它们自己的目的和副作用。有些不是re-entrance safe,这些函数不能从信号处理程序中调用。man 7 signal会帮你找出哪些是安全的。

例如,您可以在任何地方调用sys_futex() anywhere (包括信号处理程序),但如果使用sys_futex()实现互斥处理程序,则当信号中断互斥处理程序的临界区时,sys_futex()内部信号处理程序可能会永远被阻塞。

此外,SIGSEGV处理程序的唯一可移植行为是中止或退出,但我知道如果你返回,

实际上会恢复执行,对吗?

是的,如果你找不到原因的话。一些用户可能会将SIGSEGV用于他们自己的按需映射目的(例如,在JIT中,您可以翻译SIGSEGV信号处理程序中的代码,并将翻译后的代码mmap到内存,然后返回),他们可以调用mmap()或mprotect() ...etc。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11675040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档