问题
In sigaction
manpage it's written :
sa_sigaction
also specifies the action to be associated with signum
.
This function receives the signal number as its first argument, a
pointer to a siginfo_t
as its second argument and a pointer to a ucon-
text_t (cast to void*
) as its third argument.
So we can pass arguments to the signal handler (throught void*
), but I
can't find the way.
Is there no way to put it anywhere?
Example :
struct ping_val
{
int data1;
int data2;
};
void ping(int sig, siginfo_t *siginf, void *ptr)
{
// ....
}
int main()
{
struct sigaction sa_ping;
ping_val foo;
foo.data1 = 3;
foo.data2 = 4;
sa_ping.sa_sigaction = ping;
sigemptyset(&sa_ping.sa_mask);
sa_ping.sa_flags = 0;
sigaction(SIGALRM, &sa_ping, NULL);
// ....
}
Where I can pass foo
structure value in argument in ping (with a cast in struct *
)???
回答1:
You cannot pass any arguments to a signal handler because you never call it yourselves. A signal handler is called by the OS that doesn't know anything about your arguments.
The standard way to have a signal handler communicate with the main program is through global (or file-scoped) variables.
回答2:
The siginfo_t structure that a signal handler receives contains a union sigval si_value
member:
union sigval {
int sival_int; // Integer signal value
void *sival_ptr; // Pointer signal value
}
So if you're sending signals within a single process (or among forks, in some cases, I suppose), you can send a pointer to some data.
I know of two ways to send a sigval
value to a signal handler:
If you use timer_create to create a timer, you pass it a sigevent
struct, which contains a union sigval sigev_value
member. By convention, user code will set sigev_value.sival_ptr
to be the timer ID, so that the signal handler can distinguish among several timers if necessary, but you can set it to any void *
value.
If you use sigqueue (as opposed to kill
, raise
, faults, etc.) to send the signals, you give it a union sigval
as an argument.
回答3:
You write:
So we can pass arguments to the signal handler [through the void* ucontext_t argument], but I can't find the way.
There is no such way to be found — the ucontext_t
argument is set by the system itself and refers to "the receiving thread's context that was interrupted when the signal was delivered."
(Specifically, by spec it contains at least a reference to that interrupted context, and to a machine-specific representation of that context, and also the current context's stack and its set of blocked signals.)
You probably don't need any of this. If you want your program to take some action and/or modify its state on receipt of a signal, you've a limited number of tactics that can be safely used in a signal handler (volatile sigatomic_t flags, self-pipes, platform-specific interfaces), but then your main loop can of course do whatever you want with the knowledge that SIGFOO was just received.
来源:https://stackoverflow.com/questions/44879718/sigaction-using-void-sa-sigactionint-siginfo-t-void