簡體   English   中英

linux是否允許從信號處理程序進行任何系統調用?

[英]Does linux allow any system call to be made from signal handlers?

我的理解是,一般來說,如果從信號處理程序調用非異步信號安全函數,行為是不確定的,但我聽說linux允許你安全地調用任何系統調用。 這是真的? 此外,SIGSEGV處理程序的唯一可移植行為是中止或退出,但我知道如果你返回,linux實際上會恢復執行,是嗎?

根據第2節signal手冊

請參閱signal(7)以獲取可從信號處理程序內部安全調用的異步信號安全函數列表。

第7節signals手冊列出了以下功能和/或系統調用以及非常清晰的描述:

異步信號安全功能

   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確實只允許一些系統調用,但不是全部。 所以你的問題的答案很簡單 - 不。

是的,沒有

是:

您可以在信號處理程序中調用任何實際/原始系統調用。 內核有責任確保它是安全的(在內核的視圖中)。

1)內核不知道用戶空間的上下文,或者說內核在傳遞信號后將狀態保存到用戶空間后故意忘記它。 (注意:執行恢復是由用戶通過系統調用在保存狀態的幫助下完成的,而不是由內核完成,內核已經忘記了)

2)一些線程lib是通過單一實現的,因此線程已經在“信號處理程序”中,但這些線程可以調用任何系統調用。

沒有:

但用戶空間功能有其自身的目的和副作用。 有些不能重新進入安全 ,這些功能無法從信號處理程序調用。 man 7 signal將幫助您找出哪些是重新入口安全。

舉個例子,您可以在包括信號處理程序在內的任何地方調用sys_futex() ,但是如果使用sys_futex()來實現互斥鎖,則當信號中斷互斥鎖的關鍵部分時, sys_futex()內部信號處理程序可能會被阻塞。

此外,SIGSEGV處理程序的唯一可移植行為是中止或退出,但我知道如果你返回,linux實際上會恢復執行,是嗎?

是的,如果你找不到原因。 有些用戶可能會將SIGSEGV用於他們自己的地圖 - 當需要時(例如,在JIT中,您可以將SIGSEGV信號處理程序中的代碼翻譯並將已翻譯的代碼mmap到內存然后返回),他們可以調用mmap()或mprotect ()......等。

我相信任何真正的系統調用都可以從信號處理程序調用。 真正的系統調用在<asm/unistd.h> (或<asm/unistd_64.h> )中有一個數字。

手冊頁第2節中的一些posix函數是通過“多路復用”系統調用來實現的,因此它們不是我所說的“真正的系統調用”

從應用程序的角度來看,系統調用是一種原子操作; 它幾乎就像一台機器指令(來自應用程序內部)。 看到這個答案

如果您的問題是: SIGSEGV處理程序是否可以通過mprotectmmap更改錯誤的地址映射? 那么我相信答案是肯定的(至少在X86-64和X86-32架構),因為在這里說你引用了一個問題,但我沒有嘗試。 我已經讀過這樣做非常低效( SIGSEGV處理速度不是很快,而且mprotectmmap也有點慢)。 特別是,這樣模仿Hurd / Mach外部尋呼機可能效率低下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM