C语言如何只等待一定时间的信号?
How to wait for a signal for a certain time only, in C language?
我正在尝试使用 C 编程语言中的信号在 2 个进程(linux 中的父进程和子进程)之间进行通信。
第一个进程进行一些计算并提供数据。然后,它向处于 挂起状态 的第二个发送信号,等待信号唤醒并使用共享内存收集第一个进程共享的数据。
如何让第二个进程等待一定时间或者说一段时间?
在那段时间内,如果第一个进程提供数据并向第二个进程发送信号,则一切正常。否则,如果它在这段时间内没有收到第一个信号,它会做另一件事。
我怎样才能使第二个进程响应该需求?
我应该使用哪些算法和信号来实现这个?
您可以将代码的第一个进程包含在无限 while 循环中(例如-; while(1){}),一旦第一个进程计算出的数据使用函数将数据发送到第二个进程。在第二个进程中使用 sleep() 函数。例如;
main()
{
printf("Sleep for 10 milisecond to exit.\n");
sleep(0.10);
return ;
}
you may change the time.
呼叫休眠直到 10 秒或信号将是:
struct timeval t = {10, 0};
int rc = select(0, NULL, NULL, NULL, &t);
if (rc == 0) {
// timeout
} else if (errno == EINTR) {
// signal
} else {
// some error
POSIX 定义了一个完全符合您的目的的函数:sigtimedwait()
。它将挂起调用进程的执行,直到 指定集中的信号之一变为挂起, 或 指定的超时到期。它的 return 值表示发生了哪些。
Within that period, if the first process provides data and sends a signal to the second, everything is OK. Otherwise, if it doesn't receive any signal from the first within that period, it will do another thing.
How can I make the second process respond to that need ?
第二个进程设置 sigtimedwait
的参数。然后它会阻止预期的信号(通过 sigprocmask
),以便在收到该信号时不会发生默认配置,然后调用 sigtimedwait
。后者的 return 值指示是否接收到指定信号之一(如果接收到,接收到哪个信号),或者函数 return 是否出于其他原因——通常是因为超时已过期。在后一种情况下,可以检查 errno
变量以确定它是否确实超时。上面链接的手册页提供了一些额外的使用说明。
具体来说,您需要两个主要参数:
a sigset_t
定义要阻塞和等待的信号。手册页末尾的 "See also" 部分为您提供相关和类似功能的文档,包括 sigsetops(3)
,它告诉您如何操作此类对象。例如,
#include <signal.h>
// ...
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGUSER2);
a struct timespec
,其定义在手册页中内联提供。这个定义应该足以让你想出像
这样的东西
struct timespec timeout = { .tv_sec = 10 };
根据文档,您可以将 sigtimedwait
的第二个参数指定为 NULL
如果您不需要可以通过这种方式传回给您的信息,而您不需要t.
您可以使用上面已经准备好的信号集来设置信号屏蔽,例如:
sigprocmask(SIG_BLOCK, &sigs, NULL);
这似乎有点违反直觉,因为您确实想接收信号,但效果是阻止已为信号建立的任何配置发生,这与通过 [=17 处理信号的路径不同=].
此时,您可以调用 sigtimedwait()
:
int sig_num = sigtimedwait(&sigs, NULL, &timeout);
如果在指定时间内接收到指定信号之一(在此示例中仅 SIGUSER2
),则结果将是一个信号编号,否则为 -1。因此,
if (sig_num == SIGUSER2) {
// I received the signal
// do something ...
} else {
// assert(sig_num == -1);
// I did not receive the signal within the alotted time
// do something else ...
}
您可能会选择假设在未收到信号的情况下发生超时,但最可靠的代码会检查 errno
以验证:
if (errno == EAGAIN) {
// it was a timeout
} else if (errno = EINTR) {
// a signal outside the set was received
// ... might want to calculate how much wait time is left and try again
// (left as an exercise)
} else {
// some other error occurred
// ... aborting with an error might be best:
perror("signal wait failed unexpectedly");
exit(1);
}
我正在尝试使用 C 编程语言中的信号在 2 个进程(linux 中的父进程和子进程)之间进行通信。
第一个进程进行一些计算并提供数据。然后,它向处于 挂起状态 的第二个发送信号,等待信号唤醒并使用共享内存收集第一个进程共享的数据。
如何让第二个进程等待一定时间或者说一段时间?
在那段时间内,如果第一个进程提供数据并向第二个进程发送信号,则一切正常。否则,如果它在这段时间内没有收到第一个信号,它会做另一件事。
我怎样才能使第二个进程响应该需求?
我应该使用哪些算法和信号来实现这个?
您可以将代码的第一个进程包含在无限 while 循环中(例如-; while(1){}),一旦第一个进程计算出的数据使用函数将数据发送到第二个进程。在第二个进程中使用 sleep() 函数。例如;
main()
{
printf("Sleep for 10 milisecond to exit.\n");
sleep(0.10);
return ;
}
you may change the time.
呼叫休眠直到 10 秒或信号将是:
struct timeval t = {10, 0};
int rc = select(0, NULL, NULL, NULL, &t);
if (rc == 0) {
// timeout
} else if (errno == EINTR) {
// signal
} else {
// some error
POSIX 定义了一个完全符合您的目的的函数:sigtimedwait()
。它将挂起调用进程的执行,直到 指定集中的信号之一变为挂起, 或 指定的超时到期。它的 return 值表示发生了哪些。
Within that period, if the first process provides data and sends a signal to the second, everything is OK. Otherwise, if it doesn't receive any signal from the first within that period, it will do another thing.
How can I make the second process respond to that need ?
第二个进程设置 sigtimedwait
的参数。然后它会阻止预期的信号(通过 sigprocmask
),以便在收到该信号时不会发生默认配置,然后调用 sigtimedwait
。后者的 return 值指示是否接收到指定信号之一(如果接收到,接收到哪个信号),或者函数 return 是否出于其他原因——通常是因为超时已过期。在后一种情况下,可以检查 errno
变量以确定它是否确实超时。上面链接的手册页提供了一些额外的使用说明。
具体来说,您需要两个主要参数:
a
sigset_t
定义要阻塞和等待的信号。手册页末尾的 "See also" 部分为您提供相关和类似功能的文档,包括sigsetops(3)
,它告诉您如何操作此类对象。例如,#include <signal.h> // ... sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, SIGUSER2);
a
这样的东西struct timespec
,其定义在手册页中内联提供。这个定义应该足以让你想出像struct timespec timeout = { .tv_sec = 10 };
根据文档,您可以将 sigtimedwait
的第二个参数指定为 NULL
如果您不需要可以通过这种方式传回给您的信息,而您不需要t.
您可以使用上面已经准备好的信号集来设置信号屏蔽,例如:
sigprocmask(SIG_BLOCK, &sigs, NULL);
这似乎有点违反直觉,因为您确实想接收信号,但效果是阻止已为信号建立的任何配置发生,这与通过 [=17 处理信号的路径不同=].
此时,您可以调用 sigtimedwait()
:
int sig_num = sigtimedwait(&sigs, NULL, &timeout);
如果在指定时间内接收到指定信号之一(在此示例中仅 SIGUSER2
),则结果将是一个信号编号,否则为 -1。因此,
if (sig_num == SIGUSER2) {
// I received the signal
// do something ...
} else {
// assert(sig_num == -1);
// I did not receive the signal within the alotted time
// do something else ...
}
您可能会选择假设在未收到信号的情况下发生超时,但最可靠的代码会检查 errno
以验证:
if (errno == EAGAIN) {
// it was a timeout
} else if (errno = EINTR) {
// a signal outside the set was received
// ... might want to calculate how much wait time is left and try again
// (left as an exercise)
} else {
// some other error occurred
// ... aborting with an error might be best:
perror("signal wait failed unexpectedly");
exit(1);
}