Всем привет. Помогите пожалуйста получить сигнал от сокета с дополнительной информацией.
Информация из man fcntl:
F_SETSIG (int)
Set the signal sent when input or output becomes possible to the value given in arg. A value of zero means to send the default SIGIO
signal. Any other value (including SIGIO) is the signal to send instead, and in this case additional info is available to the signal
handler if installed with SA_SIGINFO.
By using F_SETSIG with a nonzero value, and setting SA_SIGINFO for the signal handler (see sigaction(2)), extra information about I/O
events is passed to the handler in a siginfo_t structure. If the si_code field indicates the source is SI_SIGIO, the si_fd field gives
the file descriptor associated with the event. Otherwise, there is no indication which file descriptors are pending, and you should use
the usual mechanisms (select(2), poll(2), read(2) with O_NONBLOCK set etc.) to determine which file descriptors are available for I/O.
By selecting a real time signal (value >= SIGRTMIN), multiple I/O events may be queued using the same signal numbers. (Queuing is depen‐
dent on available memory). Extra information is available if SA_SIGINFO is set for the signal handler, as above.
Note that Linux imposes a limit on the number of real-time signals that may be queued to a process (see getrlimit(2) and signal(7)) and
if this limit is reached, then the kernel reverts to delivering SIGIO, and this signal is delivered to the entire process rather than to
a specific thread.
На русском
F_SETSIG
Установить сигнал, который будет послан, когда станет возможен ввод или вывол. Значение 0 означает сигнал SIGIO. Любое другое значение (включая SIGIO) является другим сигналам, посылаемым вместо SIGIO и в это случае, для обработчика сигнала доступна дополнительная информация, если он был установлен с SA_SIGINFO.
В случае использования F_SETSIG с ненулевым значением и установкой SA_SIGINFO для обработчика сигнала (см. sigaction(2)), обработчику передаётся дополнительная информация о событиях ввода/вывода в структуре siginfo_t. Если поле si_code показывает, что сигналом является SI_SIGIO, то поле si_fd содержит файловый дескриптор, ассоциированный с собрытием вывода/вывода. В противном случае, не существует никакого механизма, чтобы сообщить с каким файловым дескриптором связан полученный сигнал и вы должны использовать (select(2), poll(2), read(2) с установленным флагом O_NONBLOCK и т.д.) чтобы определить какой файловый дескриптор доступен для ввода/вывода.
При выборе сигнала реального времени (value >= SIGRTMIN) как описано в POSIX.1b, в очередь будут добавляться несколько событий ввода вывода, с теми же номерами сигналов. (Размер очереди зависит от доступной памяти). Дополнительная информация будет доступна как описано выше, если для обработчика сигнала будет установлено SA_SIGINFO.
Мои попытки
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
void hello (int signum, siginfo_t *info, void *f)
{
if (info->si_signo == SIGIO)
fprintf (stderr, "Сигнал получен от %i \n", info->si_fd);
}
int main ()
{
struct sigaction act;
memset (&act, 0, sizeof(act));
act.sa_sigaction = hello;
act.sa_flags = SA_SIGINFO;
sigaction (SIGIO, &act, NULL);
int client = 0;
struct sockaddr_in saddr;
int sd = socket (AF_INET, SOCK_STREAM, 0);
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons(4000);
if (bind(sd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) < 0 ) {
perror ("bind");
close (sd);
return 1;
}
if ( listen(sd, 20) != 0) {
perror ("Listen");
close (sd);
return 1;
}
while (1) {
int size = sizeof (saddr);
memset (&saddr, 0, size);
client = accept (sd, (struct sockaddr *)&saddr, &size);
if (client > 0) {
int s_f;
fcntl(client, F_SETOWN, getpid());
fcntl(client, F_SETFL, FASYNC);
}
else {
perror ("Ошибка обработки входящего сокета");
continue;
}
}
} После коннекта отправляю порцию данных. Сигнал успешно принимается распознается, но вот номер сокета выводится некорректно 205760316 или -588753092.
Так же не получается установить посылаемый сигнал с помощью fcntl, F_SETSIG. Выдает ошибку (F_SETSIG undeclared (first use in this function)).
uname -a
Linux vmovs-admin 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
