我一直在阅读有关过去三天的计时器的信息,但找不到任何有用的信息,我试图通过实际示例进行了解,有人可以帮助我弄清楚如何为以下程序设置警报。
我如何设置一个计时器,以便它将发送2个args,一个是数组名称,第二个是要删除的数字,我知道下面无论如何都不安全,我只是想了解如何使用用args报警以调用函数。
请注意,该环境是Linux,并且我也非常感谢与有效的C示例的任何链接。
#include<stdio.h>
int delete_from_array(int arg) ;
int main()
{
int a[10000], i, y ;
//how to set timer here for to delete any number in array after half a second
for (y=0; y < 100; y++) {
for (i=0; i<sizeof(a) / sizeof(int); i++)
a[i] = i;
sleep(1);
printf("wake\n");
}
}
int delete_from_array(int arg)
{
int i, a[1000], number_to_delete=0;
//number_to_delete = arg->number;
for (i=0; i<sizeof(a); i++)
if (a[i] == number_to_delete)
a[i] = 0;
printf("deleted\n");
}
我要做的是,我有一个哈希值,该哈希值的值将在1秒后过期,因此,将值插入哈希值后,我需要创建一个计时器,以便在我们说完之后删除该值1秒,如果我在该间隔(1秒)之前收到服务器的响应,则从哈希中删除值并删除计时器,就像在tcp中重新传输一样
您要使用信号还是线程?
首先,设置信号处理程序或准备合适的线程函数;有关详细信息,请参见man 7
sigevent
。
接下来,使用创建一个合适的计时器timer_create()
。有关详细信息,请参见man 2
timer_create
。
根据计时器触发时的操作,您可能希望将计时器设置为一次触发,或稍后再重复一次。您timer_settime()
可以同时使用计时器和撤防计时器。有关详细信息,请参见man
2 timer_settime
。
在实际应用中,通常需要复用计时器。即使一个进程可以创建多个计时器,它们也是有限的资源。特别是超时计时器-这很简单-设置标志和/或向特定线程发送信号-
应该使用单个计时器,该计时器在下一次超时时触发,设置相关的超时标志,并可选地发送信号(使用空体处理程序)到所需线程以确保其被中断。(对于单线程进程,原始信号传递将中断阻止I
/ O调用。)考虑服务器,它对某些请求做出响应:在处理请求时,请求本身可能会有一分钟左右的超时时间可能需要连接超时,I / O超时等等。
现在,最初的问题很有趣,因为计时器在有效使用时功能强大。但是,示例程序基本上是胡说八道。您为什么不创建一个程序,该程序设置一个或多个计时器,每个计时器例如将一些内容输出到标准输出?请记住使用write()
from等,unistd.h
因为它们是异步信号安全的,而printf()
from等stdio.h
则不是。(如果信号处理程序使用非异步信号安全函数,则结果是不确定的。它通常可以工作,但完全不能保证;它和工作一样崩溃。测试是
不明确的 ,因为它是 不确定的 。)
编辑添加:这是复用超时的准系统示例。
(在法律允许的范围内,我将以下所示代码段的所有版权,相关权和邻接权专用于全球公共领域;请参阅CC0公共领域专用。换句话说,请随时以任何方式使用以下代码希望,只是不要怪我有任何问题。)
我使用了旧式的GCC原子内置函数,因此它应该是线程安全的。除了一些补充,它也应该适用于多线程代码。(您不能使用例如互斥锁,因为pthread_mutex_lock()
这不是异步信号安全的方法。以原子方式操作超时状态应该可以工作,尽管如果在触发时禁用超时可能会留下一些竞争。)
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#define TIMEOUTS 16
#define TIMEOUT_SIGNAL (SIGRTMIN+0)
#define TIMEOUT_USED 1
#define TIMEOUT_ARMED 2
#define TIMEOUT_PASSED 4
static timer_t timeout_timer;
static volatile sig_atomic_t timeout_state[TIMEOUTS] = { 0 };
static struct timespec timeout_time[TIMEOUTS];
/* Return the number of seconds between before and after, (after - before).
* This must be async-signal safe, so it cannot use difftime().
*/
static inline double timespec_diff(const struct timespec after, const struct timespec before)
{
return (double)(after.tv_sec - before.tv_sec)
+ (double)(after.tv_nsec - before.tv_nsec) / 1000000000.0;
}
/* Add positive seconds to a timespec, nothing if seconds is negative.
* This must be async-signal safe.
*/
static inline void timespec_add(struct timespec *const to, const double seconds)
{
if (to && seconds > 0.0) {
long s = (long)seconds;
long ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));
/* Adjust for rounding errors. */
if (ns < 0L)
ns = 0L;
else
if (ns > 999999999L)
ns = 999999999L;
to->tv_sec += (time_t)s;
to->tv_nsec += ns;
if (to->tv_nsec >= 1000000000L) {
to->tv_nsec -= 1000000000L;
to->tv_sec++;
}
}
}
/* Set the timespec to the specified number of seconds, or zero if negative seconds.
*/
static inline void timespec_set(struct timespec *const to, const double seconds)
{
if (to) {
if (seconds > 0.0) {
const long s = (long)seconds;
long ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));
if (ns < 0L)
ns = 0L;
else
if (ns > 999999999L)
ns = 999999999L;
to->tv_sec = (time_t)s;
to->tv_nsec = ns;
} else {
to->tv_sec = (time_t)0;
to->tv_nsec = 0L;
}
}
}
/* Return nonzero if the timeout has occurred.
*/
static inline int timeout_passed(const int timeout)
{
if (timeout >= 0 && timeout < TIMEOUTS) {
const int state = __sync_or_and_fetch(&timeout_state[timeout], 0);
/* Refers to an unused timeout? */
if (!(state & TIMEOUT_USED))
return -1;
/* Not armed? */
if (!(state & TIMEOUT_ARMED))
return -1;
/* Return 1 if timeout passed, 0 otherwise. */
return (state & TIMEOUT_PASSED) ? 1 : 0;
} else {
/* Invalid timeout number. */
return -1;
}
}
/* Release the timeout.
* Returns 0 if the timeout had not fired yet, 1 if it had.
*/
static inline int timeout_unset(const int timeout)
{
if (timeout >= 0 && timeout < TIMEOUTS) {
/* Obtain the current timeout state to 'state',
* then clear all but the TIMEOUT_PASSED flag
* for the specified timeout.
* Thanks to Bylos for catching this bug. */
const int state = __sync_fetch_and_and(&timeout_state[timeout], TIMEOUT_PASSED);
/* Invalid timeout? */
if (!(state & TIMEOUT_USED))
return -1;
/* Not armed? */
if (!(state & TIMEOUT_ARMED))
return -1;
/* Return 1 if passed, 0 otherwise. */
return (state & TIMEOUT_PASSED) ? 1 : 0;
} else {
/* Invalid timeout number. */
return -1;
}
}
int timeout_set(const double seconds)
{
struct timespec now, then;
struct itimerspec when;
double next;
int timeout, i;
/* Timeout must be in the future. */
if (seconds <= 0.0)
return -1;
/* Get current time, */
if (clock_gettime(CLOCK_REALTIME, &now))
return -1;
/* and calculate when the timeout should fire. */
then = now;
timespec_add(&then, seconds);
/* Find an unused timeout. */
for (timeout = 0; timeout < TIMEOUTS; timeout++)
if (!(__sync_fetch_and_or(&timeout_state[timeout], TIMEOUT_USED) & TIMEOUT_USED))
break;
/* No unused timeouts? */
if (timeout >= TIMEOUTS)
return -1;
/* Clear all but TIMEOUT_USED from the state, */
__sync_and_and_fetch(&timeout_state[timeout], TIMEOUT_USED);
/* update the timeout details, */
timeout_time[timeout] = then;
/* and mark the timeout armable. */
__sync_or_and_fetch(&timeout_state[timeout], TIMEOUT_ARMED);
/* How long till the next timeout? */
next = seconds;
for (i = 0; i < TIMEOUTS; i++)
if ((__sync_fetch_and_or(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
const double secs = timespec_diff(timeout_time[i], now);
if (secs >= 0.0 && secs < next)
next = secs;
}
/* Calculate duration when to fire the timeout next, */
timespec_set(&when.it_value, next);
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = 0L;
/* and arm the timer. */
if (timer_settime(timeout_timer, 0, &when, NULL)) {
/* Failed. */
__sync_and_and_fetch(&timeout_state[timeout], 0);
return -1;
}
/* Return the timeout number. */
return timeout;
}
static void timeout_signal_handler(int signum __attribute__((unused)), siginfo_t *info, void *context __attribute__((unused)))
{
struct timespec now;
struct itimerspec when;
int saved_errno, i;
double next;
/* Not a timer signal? */
if (!info || info->si_code != SI_TIMER)
return;
/* Save errno; some of the functions used may modify errno. */
saved_errno = errno;
if (clock_gettime(CLOCK_REALTIME, &now)) {
errno = saved_errno;
return;
}
/* Assume no next timeout. */
next = -1.0;
/* Check all timeouts that are used and armed, but not passed yet. */
for (i = 0; i < TIMEOUTS; i++)
if ((__sync_or_and_fetch(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
const double seconds = timespec_diff(timeout_time[i], now);
if (seconds <= 0.0) {
/* timeout [i] fires! */
__sync_or_and_fetch(&timeout_state[i], TIMEOUT_PASSED);
} else
if (next <= 0.0 || seconds < next) {
/* This is the soonest timeout in the future. */
next = seconds;
}
}
/* Note: timespec_set() will set the time to zero if next <= 0.0,
* which in turn will disarm the timer.
* The timer is one-shot; it_interval == 0.
*/
timespec_set(&when.it_value, next);
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = 0L;
timer_settime(timeout_timer, 0, &when, NULL);
/* Restore errno. */
errno = saved_errno;
}
int timeout_init(void)
{
struct sigaction act;
struct sigevent evt;
struct itimerspec arm;
/* Install timeout_signal_handler. */
sigemptyset(&act.sa_mask);
act.sa_sigaction = timeout_signal_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
return errno;
/* Create a timer that will signal to timeout_signal_handler. */
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = TIMEOUT_SIGNAL;
evt.sigev_value.sival_ptr = NULL;
if (timer_create(CLOCK_REALTIME, &evt, &timeout_timer))
return errno;
/* Disarm the timeout timer (for now). */
arm.it_value.tv_sec = 0;
arm.it_value.tv_nsec = 0L;
arm.it_interval.tv_sec = 0;
arm.it_interval.tv_nsec = 0L;
if (timer_settime(timeout_timer, 0, &arm, NULL))
return errno;
return 0;
}
int timeout_done(void)
{
struct sigaction act;
struct itimerspec arm;
int errors = 0;
/* Ignore the timeout signals. */
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_IGN;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
if (!errors) errors = errno;
/* Disarm any current timeouts. */
arm.it_value.tv_sec = 0;
arm.it_value.tv_nsec = 0L;
arm.it_interval.tv_sec = 0;
arm.it_interval.tv_nsec = 0;
if (timer_settime(timeout_timer, 0, &arm, NULL))
if (!errors) errors = errno;
/* Destroy the timer itself. */
if (timer_delete(timeout_timer))
if (!errors) errors = errno;
/* If any errors occurred, set errno. */
if (errors)
errno = errors;
/* Return 0 if success, errno otherwise. */
return errors;
}
记住rt
在编译时包括库,即用于gcc -W -Wall *source*.c -lrt -o *binary*
编译。
这个想法是,主程序首先调用timeout_init()
以安装所有必需的处理程序等,然后可以timeout_done()
在退出之前(或在进入之后的子进程中fork()
)调用deistall
。
要设置超时,请致电timeout_set(seconds)
。返回值是超时描述符。当前,您可以使用来检查一个标志timeout_passed()
,但是超时信号的传递也会中断任何阻塞的I
/ O调用。因此,您可以期望超时会中断任何阻塞的I / O调用。
如果您想要做的只是设置超时标志,则不能在信号处理程序中进行;请记住,在信号处理程序中,您仅限于异步信号安全功能。最简单的方法是使用一个单独的线程,该线程具有无限循环sigwaitinfo()
,TIMEOUT_SIGNAL
信号在所有其他线程中均被阻塞。这样,可以确保专用线程捕获信号,但同时,不限于异步信号安全功能。例如,它可以做更多的工作,甚至可以使用将信号发送到特定线程pthread_kill()
。(只要该信号具有一个处理程序,即使是一个带有空主体的处理程序,它的传递都会中断该线程中任何阻塞的I
/ O调用。)
这是一个main()
使用超时的简单示例。它很愚蠢,并且依赖于fgets()
不重试(被信号中断时),但是它似乎可以工作。
#include <string.h>
#include <stdio.h>
int main(void)
{
char buffer[1024], *line;
int t1, t2, warned1;
if (timeout_init()) {
fprintf(stderr, "timeout_init(): %s.\n", strerror(errno));
return 1;
}
printf("You have five seconds to type something.\n");
t1 = timeout_set(2.5); warned1 = 0;
t2 = timeout_set(5.0);
line = NULL;
while (1) {
if (timeout_passed(t1)) {
/* Print only the first time we notice. */
if (!warned1++)
printf("\nTwo and a half seconds left, buddy.\n");
}
if (timeout_passed(t2)) {
printf("\nAw, just forget it, then.\n");
break;
}
line = fgets(buffer, sizeof buffer, stdin);
if (line) {
printf("\nOk, you typed: %s\n", line);
break;
}
}
/* The two timeouts are no longer needed. */
timeout_unset(t1);
timeout_unset(t2);
/* Note: 'line' is non-NULL if the user did type a line. */
if (timeout_done()) {
fprintf(stderr, "timeout_done(): %s.\n", strerror(errno));
return 1;
}
return 0;
}
问题内容: 我正在尝试使用C为Linux创建一个基本的shell。在我尝试进行输出重定向之前,它已经可以工作了,并且它破坏了一切。当我运行此代码时,它直接进入fork()的默认情况。我不知道为什么。如果我在子进程中摆脱了for循环,那么它就可以工作,但是即使有了for循环,我也不明白为什么子进程甚至从未输入。如果将打印语句放在子进程的顶部,则不会打印出来。 当我在命令行中运行此命令时,我得到提示并
我想使用ProcessBuilder运行此命令: 我尝试了以下方法: 我使用的是如下:
问题内容: 我想使用系统蜂鸣器(并且只有在没有蜂鸣器/无法访问蜂鸣器时才使用扬声器)生成具有特定频率和长度(针对不同的声音信号)的蜂鸣声。我知道可以通过使用ioctl来做到这一点,但这需要root访问权限,而这是我所不希望的。 我知道我可以只使用“ beep”命令,但这将是一个依赖关系,如果可能的话,不应使用它(根本没有外部依赖关系,只有基本的linux库和C)。 我目前拥有的是以下代码(但这需要
问题内容: 我需要在C / C ++ linux中每’n’毫秒激活一次的函数(例如,信号处理程序)。如何设置信号等,以便以毫秒分辨率注册计时器事件。 精度并非至关重要,但需要在数百毫秒左右的时间内。 我是Linux新手,我真的不知道从哪里开始。 问题答案: 是一个好的开始,但是您真的要与信号异步吗?否则,您可能会有一个带有或以及适当超时的主循环。
本文向大家介绍C#中timer定时器用法实例,包括了C#中timer定时器用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#中timer定时器用法。分享给大家供大家参考。具体如下: 下面的代码通过Timer定时器每隔1000毫秒(1秒)触发一次事件 希望本文所述对大家的C#程序设计有所帮助。
问题内容: 我正在编写一个跨平台程序。我希望这个程序可以在Windows和Linux上运行,所以对于两个平台,我有两个不同的代码段。如果操作系统是Windows,则我希望第一个代码段可以运行;如果是Linux,那么我要运行第二个代码段。 所以我写了下面的代码,但是在Windows和Linux上构建时都会出错。我该怎么解决? 问题答案: 通常是这样完成的(或多或少): 这样,只有在Linux平台上才