Tengo entendido que, en general, el comportamiento no está definido si llamas a una función de señal segura no asíncrona desde un manejador de señal, pero he escuchado que linux te permite llamar a cualquier sistema de manera segura. ¿Es esto cierto? Además, el único comportamiento portátil para un manejador SIGSEGV es abortar o salir, pero entiendo que Linux realmente reanudará la ejecución si regresa, ¿cierto?¿Linux permite que cualquier llamada al sistema se realice desde manejadores de señal?
Respuesta
Creo que se puede llamar a cualquier llamada al sistema desde un controlador de señal. Un verdadero syscall tiene un número en <asm/unistd.h>
(o <asm/unistd_64.h>
).
algunas funciones POSIX de la sección 2 de las páginas de manual se implementan a través de una llamada al sistema "multiplexado", por lo que no son "verdaderos llamadas al sistema" en mi sentido
Una llamada al sistema es una operación atómica desde el punto de vista de la aplicación; es casi como una instrucción de una sola máquina (desde el interior de la aplicación). Ver this answer.
Si su pregunta es: ¿puede un controlador SIGSEGV
cambiar la asignación de direcciones defectuosas a través de mprotect
o mmap
? entonces creo que la respuesta es sí (al menos en x86-64 & x86-32 arquitecturas), como said here en una pregunta que usted citó, pero no lo intenté. He leído que hacerlo es bastante ineficiente (SIGSEGV
el manejo no es muy rápido, y mprotect
o mmap
también es un poco lento). En particular, imitar de esta manera Hurd/Mach external pagers podría ser ineficiente.
Las llamadas al sistema son algo atómicas, pero pueden devolver el control al código de usuario, ya sea desde el que se llamaron desde ellas o desde un manejador de señal. El comportamiento normal es que el manejador de señal haga algo, luego regrese, luego la llamada al sistema interrumpido devuelve EINTR. (y el glibc puede volver a llamarlo, creo que es lo que sucede.) Si hace una llamada al sistema desde dentro de un manejador de señal, supongo que el sistema operativo pone en cola otras señales hasta que termine. O, opcionalmente, hace algo extraño si llama a una llamada al sistema que no está en la lista de seguridad garantizada. –
¡Solo lo creeré cuando vea un documento en el árbol escrito por el mismo Linus! :-) –
Según section 2 signal
manual:
Ver señal (7) para obtener una lista de las funciones asíncrono de señal de seguridad que pueden ser llamados con seguridad desde el interior de un manejador de señales.
Y section 7 signals
manual enumera las siguientes funciones y/o llamadas al sistema junto con una descripción bastante claro: funciones
asíncrono de señal seguras
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()
creo que esta información sea más fiable que algo que escuchamos a veces en alguna parte. Entonces, Linux solo permite algunas llamadas al sistema, pero no todas. Entonces la respuesta a tu pregunta es simplemente - no.
Sin embargo, parece ser posix en lugar de linux. Sé que Linux (se supone que es) compatible con posix, así que entendí que, como mínimo, esas funciones son seguras, me gustaría entender si hay alguna más allá (en particular, mprotect) que también lo es. –
@gct: Esta es la página de manual específica de Linux. Es lo más preciso que puede obtener después de buscar el código fuente. Si le apetece revisar el código fuente y hacer un mejor análisis ... vaya por él :) –
@gct: Por cierto, hay una mejor manera de manejar las señales sin esta restricción - tiene que usar 'epoll' con 'signalfd'. Luego puede hacer lo que quiera en el controlador, consulte http://www.kernel.org/doc/man-pages/online/pages/man2/signalfd.2.html –
sí y no
Sí:
Puede llamar a cualquier llamada al sistema de bienes/prima dentro de un manejador de señales. El kernel tiene la responsabilidad de garantizar que sea seguro (desde el punto de vista del kernel).
1) El núcleo no conoce el contexto del espacio de usuario, o dice que el kernel lo olvida intencionalmente después de guardar el estado en el espacio de usuario cuando se entrega la señal. (NOTA: la reanudación de la ejecución es realizada por el usuario a través de un syscall con la ayuda de los estados guardados, no realmente por el kernel, el kernel ya lo ha olvidado)
2) algunos hilos lib se implementan a través de singles, por lo que los hilos son ya está en "manejador de señal", pero estos hilos pueden llamar a cualquier syscall.
Nº:
Pero las funciones de espacio de usuario tienen su propio propósito y efecto secundario. Algunos no son re-entrance safe, esas funciones no se pueden llamar desde el manejador de señal. man 7 signal
le ayudará a saber cuáles son seguros para la reentrada.
Tome ejemplo, puede llamar en cualquier lugar incluyendo sys_futex()
manejador de la señal, pero si se utiliza sys_futex()
para implementar un mutex, el sys_futex()
dentro del manejador de señal puede bloqueado para siempre cuando se interrumpe la señal de la sección crítica de la exclusión mutua.
Además, el único comportamiento portátil para un controlador SIGSEGV es abortar o salida, pero entiendo Linux en realidad se reanudará la ejecución si retorno, verdad?
Sí, si no puede encontrar el motivo. Algunos usuarios pueden usar SIGSEGV para su propio propósito de mapa cuando es necesario (por ejemplo, en JIT, puede traducir el código en el manejador de señal SIGSEGV y mmap el código traducido a la memoria y luego regresar), pueden llamar a mmap() o mprotect() ... etc.
"Puede llamar a cualquier syscall real/sin procesar dentro de un manejador de señal" ¿Tiene algún recurso (por ejemplo, documentos del kernel, comentarios) para respaldar ese reclamo? –
- 1. ¿Cómo se implementa la llamada al sistema en Linux?
- 2. Xcode: GDB y manejadores de señal
- 3. Seleccionar() llamada al sistema en hilos?
- 4. Llamada al sistema Linux para crear proceso e hilo
- 5. ¿Cómo hacer que Subversion (o cualquier programa) realice commits periódicos?
- 6. DataGridViewComboBox - ¿Cómo se permite cualquier valor?
- 7. ¿Cómo se permite cualquier carácter en RegEx?
- 8. ¿Llamada al sistema sin cambio de contexto?
- 9. Ignorando una llamada al sistema
- 10. interrumpido llamada al sistema con cola de procesamiento
- 11. Llamada al sistema e interruptor de contexto
- 12. Encienda el altavoz cuando se realice una llamada saliente
- 13. Llamada al sistema Unix fork() ¿qué se ejecuta cuando?
- 14. señal de llamada después de la horquilla
- 15. Dónde agrego una llamada al sistema en Linux fuente del kernel
- 16. Agregando una nueva llamada al sistema en el kernel de Linux 3.3
- 17. ¿Cómo especifico el shell que se usará para una llamada al sistema ruby?
- 18. Usando la llamada al sistema open()
- 19. Dirección incorrecta al agregar una llamada al sistema
- 20. Linux Bluetooth l2ping con intensidad de señal
- 21. ¿Se puede invocar startServce() desde cualquier conversación?
- 22. Cómo prohibir las llamadas al sistema, GNU/Linux
- 23. ¿Por qué esta llamada explícita de un método de Scala permite que se resuelva implícitamente?
- 24. Cómo untaint llamada al sistema en CGI.pm
- 25. kernel de Linux: agregue la llamada al sistema de forma dinámica a través del módulo
- 26. x86 Montaje: antes de realizar una llamada al sistema en Linux ¿Debería guardar todos los registros?
- 27. Llamada al sistema vs Llamada a la función
- 28. ¿hay algo así como flujos de datos alternativos en cualquier sistema de archivos de Linux?
- 29. SELECCIONAR cualquier sistema FROM
- 30. ¿Algún sistema de caché distribuida que permite etiquetar contenido?
¿Dónde has oído hablar de eso? – moooeeeep
específicamente la respuesta a esta pregunta: http://stackoverflow.com/questions/2663456/write-a-signal-handler-to-catch-sigsegv –
Me hubiera gustado haber agregado el término "llamada sin procesar del sistema" al título: -) –