对‘timer_create’未定义的引用 linux中timer的使用解析

本文详细介绍了Linux中使用timer_create创建定时器的步骤和注意事项,包括头文件、链接选项-lrt以及_POSIX_C_SOURCE的设置。还给出了创建、启动、销毁定时器的示例代码,涉及到SIGEV_SIGNAL和SIGEV_THREAD两种通知方式。此外,文章还提及了间隔定时器itimer的相关信息。

第一篇 对‘timer_create’未定义的引用

在编译过程中大家可能会报错,大概率的错误提示就是对‘timer_create’未定义的引用

编译的时候注意以下三点:(网友互助回复中高频提到的三点)

1.头文件

#include <signal.h>
#include <time.h>

2. 链接 使用 -lrt

大概 是如下的使用格式

g++ -o xxx xxx.cpp -lrt

如果你跑 这个timer_creater的demo,可参考如下进行编译:

g++ -o timer_creater -lpthread timer_creater.cpp -lrt

特别需要注意的: -lrt需要放到最后面,如果你放到中间,依然会报错!

本篇 第一章节 结束!,下面的3 4 5 是我自己的笔记!


3._POSIX_C_SOURCE 值设置

其实这个担心,可能是被手册给误导了,手册只是提示你这个值必须大于多少;并不是说你的一定不满足,大概率下,你是不用担心的

_POSIX_C_SOURCE >= 199309L

其中:网上讨论最多的是第三条,但是大部分的问题,大概率是第二条 -lrt位置的问题;

4.为何这三条频率会如此之高?

直到我看到了linux API 的帮助后才明白;

man timer_create

原来,这手册中明确提到了 这三点;
在这里插入图片描述

_POSIX_C_SOURCE 值怎么判断是否满足199309L:

手册参考文章:
https://www.onitroad.com/jc/linux/man-pages/linux/man7/feature_test_macros.7.html
这个文章有详细介绍; 文章有点长,直接运行里面的demo,就可返回_POSIX_C_SOURCE的大小;

_POSIX_C_SOURCE 这个值和glibc有关系
可以用getconf GNU_LIBC_VERSION查看glibc的版本;

hann@hann-virtual-machine:$ getconf GNU_LIBC_VERSION
glibc 2.27

我的版本是2.27 ,好像有这么句话,当然也是有前提的;
700 <= _XOPEN_SOURCE(since glibc 2.10)
_POSIX_C_SOURCE定义为值200809L。

你也可以用上述链接的demo跑一下:
直接运行里面的demo,就可返回_POSIX_C_SOURCE的大小;

如果你不放心:
可以自定义下:
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif

第二篇 使用Linux实现一个高精度定时器

由timer_create()创建的计时器通常称为" POSIX(间隔)计时器"。 POSIX计时器API由以下接口组成:

timer_create():创建一个计时器。(创建定时器)、
timer_settime(2):布防(启动)或撤防(停止)计时器。(初始化定时器)、
timer_gettime(2):获取计时器的下一次到期之前剩余的时间以及计时器的间隔设置。
timer_getoverrun(2):返回上一次计时器到期的溢出计数。 timer_delete(2):撤防并删除计时器。(销毁它)。

创建一个定时器:

介绍参见:https://www.onitroad.com/jc/linux/man-pages/linux/man2/timer_create.2.html

int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)

进程可以通过调用timer_create()创建特定的定时器,定时器是每个进程自己的,不是在fork时继承的。
timer_create()创建一个新的每个进程间隔计时器。新计时器的ID在timerid指向的缓冲区中返回,该缓冲区必须是非空指针。该ID在该过程中是唯一的,直到删除计时器为止。新计时器最初被撤防;
clockid参数指定新计时器用来测量时间的时钟。可以将其指定为以下值之一:

CLOCK_REALTIME 可设置的系统范围的实时时钟。

sevp.sigev_notify字段可以具有以下值:

SIGEV_NONE
什么都不做,只提供通过timer_gettime和timer_getoverrun查询超时信息。
SIGEV_SIGNAL:
当定时器到期,内核会将sigev_signo所指定的信号传送给进程。在信号处理程序中,si_value会被设定会sigev_value。
SIGEV_THREAD:
当定时器到期,内核会(在此进程内)以sigev_notification_attributes为线程属性创建一个线程,并且让它执行sigev_notify_function,传入sigev_value作为为一个参数。

*timerid装载的是被创建的定时器的ID
该函数创建了定时器,并将他的ID 放入timerid指向的位置中。参数evp指定了定时器到期要产生的异步通知。如果evp为NULL,那么定时器到期会产生默认的信号,对 CLOCK_REALTIMER来说,默认信号就是SIGALRM。如果要产生除默认信号之外的其它信号,程序必须将 evp->sigev_signo设置为期望的信号码。struct sigevent 结构中的成员evp->sigev_notify说明了定时器到期时应该采取的行动。通常,这个成员的值为SIGEV_SIGNAL,这个值说明在定时器到期时,会产生一个信号。程序可以将成员evp->sigev_notify设为SIGEV_NONE来防止定时器到期时产生信号。
如果几个定时器产生了同一个信号,处理程序可以用 evp->sigev_value来区分是哪个定时器产生了信号。要实现这种功能,程序必须在为信号安装处理程序时,使用struct sigaction的成员sa_flags中的标志符SA_SIGINFO。

struct sigevent
{
   
   
    int sigev_notify; //notification type 具体实现类型
    int sigev_signo; //signal number  信号
    union sigval   sigev_value; //signal valu区分是哪个定时器产生了信号
    void (*sigev_notify_function)(union sigval)
    pthread_attr_t *<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值