[修改] 调整整体代码结构目录
This commit is contained in:
parent
6eb7f6d723
commit
27e63d5aaf
|
@ -0,0 +1,29 @@
|
|||
cmake_minimum_required(VERSION 3.1.3)
|
||||
|
||||
project(kysdk-system)
|
||||
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
add_definitions(-Drelease)
|
||||
set(CMAKE_C_FLAGS "$ENV{CFLAGS} -O2 -Wall")
|
||||
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -O2 -Wall")
|
||||
else (CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
message("CMake Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
set(CMAKE_C_FLAGS "$ENV{CFLAGS} -g -O0 -Wall")
|
||||
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -g -O0 -Wall")
|
||||
endif()
|
||||
|
||||
message("Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
set (LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
add_subdirectory(src)
|
|
@ -1,73 +0,0 @@
|
|||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
include_directories(/usr/include/kysdk/kysdk-base/)
|
||||
|
||||
# add_subdirectory(disk)
|
||||
# add_subdirectory(systeminfo)
|
||||
add_subdirectory(systemtime)
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef KYSDK_SYSTEM_SYSINFO_H__
|
||||
#define KYSDK_SYSTEM_SYSINFO_H__
|
||||
|
||||
#include <string>
|
||||
#include <stdbool.h>
|
||||
|
||||
namespace KYSDK_SYSTEM {
|
||||
|
||||
/**
|
||||
* @brief 获取架构类型
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
extern std::string getSystemArchitecture();
|
||||
|
||||
/**
|
||||
* @brief 获取操作系统名称
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
extern std::string getSystemName();
|
||||
|
||||
/**
|
||||
* @brief 获取操作系统版本号
|
||||
*
|
||||
* @param verbose
|
||||
* @return std::string
|
||||
*/
|
||||
extern std::string getSystemVersion(bool verbose = false);
|
||||
|
||||
/**
|
||||
* @brief 获取操作系统激活状态
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
extern bool getSystemActivationStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取操作系统服务序列号
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
extern std::string getSystemSerialNumber();
|
||||
|
||||
/**
|
||||
* @brief 获取内核版本号
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
extern std::string getKernelVersion();
|
||||
}
|
||||
|
||||
#endif // KYSDK_SYSTEM_SYSINFO_H__
|
|
@ -1,19 +1,19 @@
|
|||
FILE(GLOB SRC_LIST_C ${PROJECT_SOURCE_DIR}/src/*.c)
|
||||
FILE(GLOB TIMER_LIST_C ${PROJECT_SOURCE_DIR}/src/timer/*.c)
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(PKGS REQUIRED
|
||||
dbus-1
|
||||
glib-2.0
|
||||
dbus-glib-1
|
||||
)
|
||||
message("pkg cflags: ${PKGS_CFLAGS}")
|
||||
message ("pkg include dirs: ${PKGS_INCLUDE_DIRS}")
|
||||
# message("pkg cflags: ${PKGS_CFLAGS}")
|
||||
# message ("pkg include dirs: ${PKGS_INCLUDE_DIRS}")
|
||||
find_library(GLIBC_LIB glib-2.0)
|
||||
message("library :${GLIBC_LIB}")
|
||||
# message("library :${GLIBC_LIB}")
|
||||
find_library(DBUS_LIB dbus-1)
|
||||
find_library(DBUS_GLIB_LIB dbus-glib-1)
|
||||
find_library(THREAD_LIB pthread)
|
||||
link_directories(/usr/lib/kysdk/kysdk-base/)
|
||||
include_directories(${PKGS_INCLUDE_DIRS})
|
||||
SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
||||
# SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
||||
ADD_EXECUTABLE(systime m_systime.c)
|
||||
target_link_libraries(systime ${GLIBC_LIB} ${DBUS_LIB} ${DBUS_GLIB_LIB} ${THREAD_LIB} ${TIMER_LIST_C})
|
||||
target_link_libraries(systime ${GLIBC_LIB} ${DBUS_LIB} ${DBUS_GLIB_LIB} ${THREAD_LIB} ${TIMER_LIST_C} kytimer kylog kyconf)
|
|
@ -4,7 +4,7 @@
|
|||
#include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
|
||||
|
||||
#include "m_systime.h"
|
||||
#include "./timer/libkytimer.h"
|
||||
#include <libkytimer.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -125,17 +125,17 @@ void *startBroadcastSystemTimePerMin(void *tmp)
|
|||
if (g_TimeChanged || g_TimeSync)
|
||||
{
|
||||
printf("Get Time Changed signal or mis-synced. stop timerID %zd\n", timerID);
|
||||
kyStopTimer(timerID);
|
||||
kdk_timer_stop(timerID);
|
||||
g_TimeChanged = 0;
|
||||
g_TimeSync = 0;
|
||||
timerID = -1;
|
||||
}
|
||||
|
||||
if (!g_Flag)
|
||||
kyStartTimer(200, printClock, KTIMER_SINGLESHOT, KTIMER_RELATIVE, conn, 0);
|
||||
kdk_timer_start(200, printClock, KTIMER_SINGLESHOT, KTIMER_RELATIVE, conn, 0);
|
||||
else
|
||||
{
|
||||
timerID = kyStartTimer(1000 * 60, printClock, KTIMER_PERIODIC, KTIMER_RELATIVE, conn, 0);
|
||||
timerID = kdk_timer_start(1000 * 60, printClock, KTIMER_PERIODIC, KTIMER_RELATIVE, conn, 0);
|
||||
printf("start periodic timer with ID %zd\n", timerID);
|
||||
}
|
||||
}
|
|
@ -125,17 +125,17 @@ void *startBroadcastSystemTimePerMin(void *tmp)
|
|||
if (g_TimeChanged || g_TimeSync)
|
||||
{
|
||||
printf("Get Time Changed signal or mis-synced. stop timerID %zd\n", timerID);
|
||||
kyStopTimer(timerID);
|
||||
kdk_timer_stop(timerID);
|
||||
g_TimeChanged = 0;
|
||||
g_TimeSync = 0;
|
||||
timerID = -1;
|
||||
}
|
||||
|
||||
if (!g_Flag)
|
||||
kyStartTimer(200, printClock, KTIMER_SINGLESHOT, KTIMER_RELATIVE, conn, 0);
|
||||
kdk_timer_start(200, printClock, KTIMER_SINGLESHOT, KTIMER_RELATIVE, conn, 0);
|
||||
else
|
||||
{
|
||||
timerID = kyStartTimer(1000 * 60, printClock, KTIMER_PERIODIC, KTIMER_RELATIVE, conn, 0);
|
||||
timerID = kdk_timer_start(1000 * 60, printClock, KTIMER_PERIODIC, KTIMER_RELATIVE, conn, 0);
|
||||
printf("start periodic timer with ID %zd\n", timerID);
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,22 +0,0 @@
|
|||
CLIBS=-lpthread -lrt
|
||||
CFLAGS=-g -O0 -Wall -fPIC -shared
|
||||
CC=gcc
|
||||
TARGET=libkytimer.so
|
||||
LIBINSTALLNAME=libkytimer.so.1.0.0
|
||||
LIBINSTALLDIR=/usr/lib/
|
||||
HEADERINSTALLDIR=/usr/include/
|
||||
HEADERS=kytimer.h
|
||||
|
||||
.PHONY:all
|
||||
.PHONY:clean
|
||||
.PHONY:lib
|
||||
|
||||
all:lib
|
||||
|
||||
lib:
|
||||
$(CC) $(CFLAGS) $(CLIBS) -o $(TARGET) libkytimer.c
|
||||
mkdir -p ../lib/
|
||||
mv $(TARGET) ../lib/$(LIBINSTALLNAME)
|
||||
|
||||
clean:
|
||||
-rm ../lib/$(LIBINSTALLNAME)
|
|
@ -1,340 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include "libkytimer.h"
|
||||
|
||||
static void* timerCoreThread(void* data); //定时器循环核心
|
||||
static KTimerNode* findNodeByFD(unsigned int fd); //根据fd查找节点
|
||||
static int testNodeInList(KTimerNode* node);
|
||||
static void insertIntoList(KTimerNode* node); //插入节点,按照间隔时间的顺序从小到大排序
|
||||
static void deleteFromList(KTimerNode* node , int locked); //从链表中删除节点
|
||||
static pthread_t g_coreThreadID; //核心循环线程
|
||||
static KTimerNode* g_list = NULL;
|
||||
static int epollfd; //事件池句柄
|
||||
static int curTimerCounts; //当前已注册定时器数量
|
||||
|
||||
int kyTimerInitialize(); //初始化定时器核心
|
||||
size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete); //注册并开始一个定时器,返回定时器句柄号
|
||||
void kyStopTimer(size_t timerfd); //停止一个定时器
|
||||
void kyResetTickCount(size_t timerfd , unsigned int intervalms);
|
||||
void kyTimerDestroy(); //销毁定时器核心
|
||||
|
||||
#ifndef TFD_TIMER_CANCEL_ON_SET
|
||||
#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
|
||||
#endif
|
||||
|
||||
int kyTimerInitialize()
|
||||
{
|
||||
if (g_coreThreadID > 0)
|
||||
return 0;
|
||||
|
||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollfd <= 0)
|
||||
{
|
||||
printf("Epoll事件池创建失败!%s\n" , strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (pthread_create(&g_coreThreadID , NULL , timerCoreThread , NULL))
|
||||
{
|
||||
printf("kyTimer 定时器核心初始化失败:%s\n" , strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete)
|
||||
{
|
||||
if (g_coreThreadID <= 0 && kyTimerInitialize())
|
||||
{
|
||||
printf("定时器注册失败:定时器全局句柄初始化失败!\n");
|
||||
return 0;
|
||||
}
|
||||
if (curTimerCounts >= KTIMER_MAXTIMERFD)
|
||||
{
|
||||
printf("定时器注册失败:定时器注册数量已超限!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KTimerNode* node = (KTimerNode*)calloc(1 , sizeof(KTimerNode));
|
||||
if (!node)
|
||||
{
|
||||
printf("定时器注册失败:无法分配内存,%s\n" , strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_init(&node->lock , NULL);
|
||||
node->callback = callback;
|
||||
node->userdata = userdata;
|
||||
node->intervalms = intervalms;
|
||||
node->attr = attr;
|
||||
node->type = type;
|
||||
node->freeOnDelete = freeOnDelete;
|
||||
|
||||
if (type == KTIMER_ABSOLUTE)
|
||||
node->fd = timerfd_create(CLOCK_MONOTONIC , TFD_CLOEXEC|TFD_NONBLOCK);
|
||||
else
|
||||
node->fd = timerfd_create(CLOCK_REALTIME , TFD_CLOEXEC|TFD_NONBLOCK);
|
||||
|
||||
if ((int)node->fd <= 0)
|
||||
{
|
||||
printf("定时器注册失败:timerfd_create失败,%s\n" , strerror(errno));
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
struct itimerspec tval;
|
||||
tval.it_value.tv_sec = intervalms / 1000;
|
||||
tval.it_value.tv_nsec = (intervalms % 1000) * 1000000;
|
||||
|
||||
if (attr == KTIMER_PERIODIC) //多次触发时设置interval项
|
||||
{
|
||||
tval.it_interval.tv_sec = tval.it_value.tv_sec;
|
||||
tval.it_interval.tv_nsec = tval.it_value.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
tval.it_interval.tv_sec = 0;
|
||||
tval.it_interval.tv_nsec = 0;
|
||||
}
|
||||
|
||||
timerfd_settime(node->fd, 0, &tval, NULL);
|
||||
|
||||
//注册到Epoll池中
|
||||
struct epoll_event ev;
|
||||
memset(&ev , 0 , sizeof(struct epoll_event));
|
||||
if (attr == KTIMER_SINGLESHOT)
|
||||
ev.events = EPOLLIN | EPOLLONESHOT;
|
||||
else
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = node;
|
||||
if (epoll_ctl(epollfd , EPOLL_CTL_ADD , node->fd , &ev))
|
||||
{
|
||||
printf("定时器注册失败:epoll_ctl错误,%s\n" , strerror(errno));
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
insertIntoList(node);
|
||||
|
||||
return node->fd;
|
||||
}
|
||||
|
||||
//停止一个定时器,并从列表中移除
|
||||
void kyStopTimer(size_t timerfd)
|
||||
{
|
||||
if (timerfd <= 0)
|
||||
return;
|
||||
KTimerNode* node = findNodeByFD(timerfd);
|
||||
if (node)
|
||||
{
|
||||
if (epoll_ctl(epollfd , EPOLL_CTL_DEL , timerfd , NULL))
|
||||
{
|
||||
printf("无法注销文件句柄%zd : %s\n" , timerfd , strerror(errno));
|
||||
return;
|
||||
}
|
||||
deleteFromList(node , 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//定时器核心线程,负责循环处理已到期的定时器
|
||||
static void* timerCoreThread(void* data)
|
||||
{
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
KTimerNode* knode = NULL;
|
||||
int read_fds = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE , NULL);
|
||||
pthread_testcancel();
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE , NULL);
|
||||
|
||||
struct epoll_event activeEvs[KTIMER_MAXTIMERFD];
|
||||
read_fds = epoll_wait(epollfd , activeEvs , KTIMER_MAXTIMERFD , -1);
|
||||
if (read_fds < 0)
|
||||
{
|
||||
printf("epoll wait error , %s\n" , strerror(errno));
|
||||
continue;
|
||||
}
|
||||
for (int i = 0 ; i < read_fds ; i ++)
|
||||
{
|
||||
knode = activeEvs[i].data.ptr;
|
||||
pthread_mutex_lock(&knode->lock);
|
||||
if (!testNodeInList(knode))
|
||||
continue;
|
||||
uint64_t dep;
|
||||
read(knode->fd , &dep , sizeof(uint64_t));
|
||||
|
||||
if (knode && knode->attr != KTIMER_NEVER && knode->callback)
|
||||
{
|
||||
#if 1
|
||||
pthread_attr_t attr;
|
||||
pthread_t tid;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr , PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&tid , &attr , knode->callback , knode->userdata);
|
||||
|
||||
knode->freeOnDelete = 0;
|
||||
#else
|
||||
knode->callback(knode->userdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (knode->attr == KTIMER_SINGLESHOT) //单次触发的在触发后就从链表中移除
|
||||
{
|
||||
// FixMe: 如果设置了freeOnDelete,并且采用上面的线程执行模式,
|
||||
// 则会发生段错误。因此只能在启用线程执行模式的时候强制禁止
|
||||
// freeOnDelete。
|
||||
deleteFromList(knode , 1);
|
||||
}
|
||||
if (testNodeInList(knode))
|
||||
pthread_mutex_unlock(&knode->lock);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static KTimerNode* findNodeByFD(unsigned int fd)
|
||||
{
|
||||
KTimerNode* tmp = g_list;
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp->fd == fd)
|
||||
return tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int testNodeInList(KTimerNode* node)
|
||||
{
|
||||
KTimerNode* pos = g_list;
|
||||
while (pos)
|
||||
{
|
||||
if (pos == node)
|
||||
return 1;
|
||||
pos = pos->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void insertIntoList(KTimerNode* node)
|
||||
{
|
||||
curTimerCounts ++;
|
||||
if (!g_list)
|
||||
{
|
||||
g_list = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_list->intervalms > node->intervalms)
|
||||
{
|
||||
node->next = g_list;
|
||||
g_list = node;
|
||||
return;
|
||||
}
|
||||
|
||||
KTimerNode* cur = g_list->next;
|
||||
KTimerNode* prev = g_list;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
if (cur->intervalms > node->intervalms)
|
||||
{
|
||||
node->next = cur;
|
||||
prev->next = node;
|
||||
return;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
prev->next = node;
|
||||
node->next = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void deleteFromList(KTimerNode* node , int locked)
|
||||
{
|
||||
if (!g_list)
|
||||
return;
|
||||
curTimerCounts --;
|
||||
if (!locked)
|
||||
pthread_mutex_lock(&node->lock);
|
||||
if (node == g_list)
|
||||
{
|
||||
g_list = g_list->next;
|
||||
if (node->userdata && node->freeOnDelete)
|
||||
free(node->userdata);
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
|
||||
KTimerNode* pos = g_list;
|
||||
while (pos)
|
||||
{
|
||||
if (pos->next && pos->next == node)
|
||||
{
|
||||
pos->next = pos->next->next;
|
||||
if (node->userdata && node->freeOnDelete)
|
||||
free(node->userdata);
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
pos = pos->next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void kyResetTickCount(size_t timerfd , unsigned int intervalms)
|
||||
{
|
||||
KTimerNode* node = findNodeByFD(timerfd);
|
||||
if (!node)
|
||||
return;
|
||||
node->intervalms = intervalms;
|
||||
struct itimerspec tval;
|
||||
tval.it_value.tv_sec = intervalms / 1000;
|
||||
tval.it_value.tv_nsec = (intervalms % 1000) * 1000000;
|
||||
|
||||
if (node->attr == KTIMER_PERIODIC) //多次触发时设置interval项
|
||||
{
|
||||
tval.it_interval.tv_sec = tval.it_value.tv_sec;
|
||||
tval.it_interval.tv_nsec = tval.it_value.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
tval.it_interval.tv_sec = 0;
|
||||
tval.it_interval.tv_nsec = 0;
|
||||
}
|
||||
timerfd_settime(timerfd , 0 , &tval , NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void kyTimerDestroy() //停止所有定时器,并销毁定时器核心
|
||||
{
|
||||
//终止线程运行
|
||||
if (g_coreThreadID > 0)
|
||||
pthread_cancel(g_coreThreadID);
|
||||
|
||||
//销毁链表
|
||||
KTimerNode* node = g_list;
|
||||
while (node)
|
||||
{
|
||||
deleteFromList(node , 0);
|
||||
node = g_list;
|
||||
}
|
||||
|
||||
//关闭epoll池
|
||||
close(epollfd);
|
||||
return;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef __KY_TIMER_H__
|
||||
#define __KY_TIMER_H__
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KTIMER_SINGLESHOT = 0,
|
||||
KTIMER_PERIODIC = 1,
|
||||
KTIMER_NEVER = 2
|
||||
}KTimerAttribute;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KTIMER_ABSOLUTE = 0,
|
||||
KTIMER_RELATIVE
|
||||
}KTimerType;
|
||||
|
||||
#define KTIMER_MAXTIMERFD 1000 //最多支持注册1000个定时器
|
||||
|
||||
typedef void* (*time_handler)(void* user_data); //回调函数规则
|
||||
|
||||
typedef struct _KTimerNode{
|
||||
pthread_mutex_t lock;
|
||||
size_t fd; //序列号
|
||||
time_handler callback; //到期后执行的函数
|
||||
int freeOnDelete; //删除定时器时自动释放userdata
|
||||
void* userdata; //callback使用的参数,外部使用alloc分配内存,在delete定时器的时候会根据配置自动释放
|
||||
unsigned int intervalms; //定时器间隔时间,单位毫秒
|
||||
KTimerAttribute attr; //触发类型,单次触发或多次触发
|
||||
KTimerType type; //时钟类型,绝对时间还是相对时间
|
||||
struct _KTimerNode* next;
|
||||
}KTimerNode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
extern int kyTimerInitialize(); //初始化定时器核心
|
||||
extern size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete); //注册并开始一个定时器,返回定时器句柄号
|
||||
extern void kyStopTimer(size_t timerfd); //停止一个定时器
|
||||
extern void kyResetTickCount(size_t timerfd , unsigned int intervalms); //重置一个定时器的时间
|
||||
extern void kyTimerDestroy(); //销毁定时器核心
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
all:
|
||||
gcc -g -O0 -o demo main.c -lkytimer -lpthread
|
||||
|
||||
clean:
|
||||
rm demo
|
|
@ -1,62 +0,0 @@
|
|||
#include <libkytimer.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
void func(char* comment)
|
||||
{
|
||||
char date[32] = {0};
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (ctime_r(&now , date))
|
||||
date[strlen(date) - 1] = '\0';
|
||||
printf("[%s]这是%s\n" , date , comment);
|
||||
}
|
||||
|
||||
void stop(size_t* fdpoll)
|
||||
{
|
||||
printf("开始停止定时器\n");
|
||||
for (int i = 0 ; i < 10 ; i ++)
|
||||
{
|
||||
kyStopTimer(fdpoll[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
assert(kyTimerInitialize() == 0);
|
||||
|
||||
//测试1 -- 基本功能
|
||||
size_t fdpoll[10] = {0};
|
||||
for (int i = 1 ; i <= 10 ; i ++)
|
||||
{
|
||||
char* data = (char*)malloc(10);
|
||||
assert(data);
|
||||
sprintf(data , "%d号" , i);
|
||||
fdpoll[i - 1] = kyStartTimer(i * 1000 , (time_handler)func , KTIMER_PERIODIC , (void*)data , 1);
|
||||
assert(fdpoll[i - 1]);
|
||||
}
|
||||
kyStartTimer(10000 , (time_handler)stop , KTIMER_SINGLESHOT , (void*)fdpoll , 0);
|
||||
sleep(11);
|
||||
|
||||
//测试3 -- 单次触发
|
||||
printf("单次触发测试:\n");
|
||||
kyStartTimer(2000 , (time_handler)func , KTIMER_SINGLESHOT , "2号" , 0);
|
||||
sleep(5);
|
||||
|
||||
//测试2 -- 重置定时器时间
|
||||
printf("修改时间测试:\n");
|
||||
int persec = kyStartTimer(1000 , (time_handler)func , KTIMER_PERIODIC , "1号" , 0);
|
||||
int sec3 = kyStartTimer(3000 , (time_handler)func , KTIMER_SINGLESHOT , "3号" , 0);
|
||||
sleep(2);
|
||||
kyResetTickCount(sec3 , 4000);
|
||||
printf("sec3 时钟已被重置为4000ms\n");
|
||||
sleep(10);
|
||||
|
||||
printf("正在销毁定时器核心...\n");
|
||||
kyTimerDestroy();
|
||||
return 0;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
FILE=$(file)
|
||||
CFLAGS=$(cflags)
|
||||
CFLAGS += -g -O0 -std=gnu11 -Wall
|
||||
CLIBS=-lpthread -pthread -lrt
|
||||
CLIBS += $(clibs)
|
||||
|
||||
.PHONY:main test
|
||||
all:systemtime.c
|
||||
gcc -o demo systemtime.c ../timer/libkytimer.c $(CFLAGS) $(CLIBS)
|
||||
|
||||
.PHONY:clean
|
||||
clean:
|
||||
-rm main
|
||||
-rm *.o
|
Binary file not shown.
|
@ -1,141 +0,0 @@
|
|||
#include "systemtime.h"
|
||||
#include "../timer/libkytimer.h"
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <semaphore.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <errno.h>
|
||||
|
||||
pthread_mutex_t lock; //互斥锁
|
||||
u_int8_t g_Flag; //任何平台都是8位无符号数
|
||||
|
||||
u_int8_t g_Quit;
|
||||
sem_t g_Wait;
|
||||
|
||||
u_int8_t g_TimeChanged;
|
||||
|
||||
void sig_Handler(int sig)
|
||||
{
|
||||
g_Quit = 1;
|
||||
printf("%s----%d",__func__,sig);
|
||||
}
|
||||
|
||||
static void* printClock(void* ptr)
|
||||
{
|
||||
struct tm *now;
|
||||
time_t current;
|
||||
time(¤t);
|
||||
now = localtime(¤t);
|
||||
printf("%s,%d",__func__,__LINE__);
|
||||
printf("%d/%d/%d %d:%d:%d\n", now->tm_year, now->tm_mon, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
|
||||
|
||||
if (!g_Flag)
|
||||
{
|
||||
pthread_mutex_lock(&lock);
|
||||
if(now->tm_sec == 0)
|
||||
{
|
||||
g_Flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Flag = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
sem_post(&g_Wait);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void startBroadcastSystemTimePerMin()
|
||||
{
|
||||
size_t timerID = -1;
|
||||
while (!g_Quit)
|
||||
{
|
||||
sem_wait(&g_Wait);
|
||||
|
||||
if (g_TimeChanged)
|
||||
{
|
||||
printf("Get Time Changed signal. stop timerID %zd\n", timerID);
|
||||
kyStopTimer(timerID);
|
||||
g_TimeChanged = 0;
|
||||
timerID = -1;
|
||||
}
|
||||
|
||||
if (! g_Flag)
|
||||
kyStartTimer(500, printClock, KTIMER_SINGLESHOT, KTIMER_RELATIVE, NULL, 0);
|
||||
else
|
||||
{
|
||||
timerID = kyStartTimer(1000 * 60, printClock, KTIMER_PERIODIC, KTIMER_RELATIVE, NULL, 0);
|
||||
printf("start periodic timer with ID %zd\n", timerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int monitorSystemTimeChange()
|
||||
{
|
||||
#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
|
||||
|
||||
struct itimerspec its = {.it_value.tv_sec = TIME_T_MAX};
|
||||
int fd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0)
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u_int64_t dep;
|
||||
ssize_t ret = read(fd, &dep, sizeof(u_int64_t));
|
||||
if (ret == -1 && errno == ECANCELED)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* actionTimeChanged(void* ptr)
|
||||
{
|
||||
while (!g_Quit)
|
||||
{
|
||||
if (monitorSystemTimeChange() == 1)
|
||||
{
|
||||
printf("System Time Changed.\n");
|
||||
g_TimeChanged = 1;
|
||||
g_Flag = 0;
|
||||
printClock(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
signal(SIGTERM, sig_Handler);
|
||||
signal(SIGQUIT, sig_Handler);
|
||||
signal(SIGKILL, sig_Handler);
|
||||
signal(SIGINT, sig_Handler);
|
||||
|
||||
sem_init(&g_Wait, 0, 1);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_t tid;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&tid, &attr, actionTimeChanged, NULL);
|
||||
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
startBroadcastSystemTimePerMin();
|
||||
pthread_mutex_destroy(&lock);
|
||||
|
||||
sem_destroy(&g_Wait);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef KYSDK_SYSTIME_H__
|
||||
#define KYSDK_SYSTIME_H__
|
||||
|
||||
extern void startBroadcastSystemTimePerMin();
|
||||
|
||||
/**
|
||||
* @brief 当系统时间被修改时,该函数会返回 1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
extern int monitorSystemTimeChange();
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
CLIBS=-lpthread -lrt
|
||||
CFLAGS=-g -O0 -Wall -fPIC -shared
|
||||
CC=gcc
|
||||
TARGET=libkytimer.so
|
||||
LIBINSTALLNAME=libkytimer.so.1.0.0
|
||||
LIBINSTALLDIR=/usr/lib/
|
||||
HEADERINSTALLDIR=/usr/include/
|
||||
HEADERS=kytimer.h
|
||||
|
||||
.PHONY:all
|
||||
.PHONY:clean
|
||||
.PHONY:lib
|
||||
|
||||
all:lib
|
||||
|
||||
lib:
|
||||
$(CC) $(CFLAGS) $(CLIBS) -o $(TARGET) libkytimer.c
|
||||
mkdir -p ../lib/
|
||||
mv $(TARGET) ../lib/$(LIBINSTALLNAME)
|
||||
|
||||
clean:
|
||||
-rm ../lib/$(LIBINSTALLNAME)
|
|
@ -1,340 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include "libkytimer.h"
|
||||
|
||||
static void* timerCoreThread(void* data); //定时器循环核心
|
||||
static KTimerNode* findNodeByFD(unsigned int fd); //根据fd查找节点
|
||||
static int testNodeInList(KTimerNode* node);
|
||||
static void insertIntoList(KTimerNode* node); //插入节点,按照间隔时间的顺序从小到大排序
|
||||
static void deleteFromList(KTimerNode* node , int locked); //从链表中删除节点
|
||||
static pthread_t g_coreThreadID; //核心循环线程
|
||||
static KTimerNode* g_list = NULL;
|
||||
static int epollfd; //事件池句柄
|
||||
static int curTimerCounts; //当前已注册定时器数量
|
||||
|
||||
int kyTimerInitialize(); //初始化定时器核心
|
||||
size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete); //注册并开始一个定时器,返回定时器句柄号
|
||||
void kyStopTimer(size_t timerfd); //停止一个定时器
|
||||
void kyResetTickCount(size_t timerfd , unsigned int intervalms);
|
||||
void kyTimerDestroy(); //销毁定时器核心
|
||||
|
||||
#ifndef TFD_TIMER_CANCEL_ON_SET
|
||||
#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
|
||||
#endif
|
||||
|
||||
int kyTimerInitialize()
|
||||
{
|
||||
if (g_coreThreadID > 0)
|
||||
return 0;
|
||||
|
||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollfd <= 0)
|
||||
{
|
||||
printf("Epoll事件池创建失败!%s\n" , strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (pthread_create(&g_coreThreadID , NULL , timerCoreThread , NULL))
|
||||
{
|
||||
printf("kyTimer 定时器核心初始化失败:%s\n" , strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete)
|
||||
{
|
||||
if (g_coreThreadID <= 0 && kyTimerInitialize())
|
||||
{
|
||||
printf("定时器注册失败:定时器全局句柄初始化失败!\n");
|
||||
return 0;
|
||||
}
|
||||
if (curTimerCounts >= KTIMER_MAXTIMERFD)
|
||||
{
|
||||
printf("定时器注册失败:定时器注册数量已超限!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KTimerNode* node = (KTimerNode*)calloc(1 , sizeof(KTimerNode));
|
||||
if (!node)
|
||||
{
|
||||
printf("定时器注册失败:无法分配内存,%s\n" , strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_init(&node->lock , NULL);
|
||||
node->callback = callback;
|
||||
node->userdata = userdata;
|
||||
node->intervalms = intervalms;
|
||||
node->attr = attr;
|
||||
node->type = type;
|
||||
node->freeOnDelete = freeOnDelete;
|
||||
|
||||
if (type == KTIMER_ABSOLUTE)
|
||||
node->fd = timerfd_create(CLOCK_MONOTONIC , TFD_CLOEXEC|TFD_NONBLOCK);
|
||||
else
|
||||
node->fd = timerfd_create(CLOCK_REALTIME , TFD_CLOEXEC|TFD_NONBLOCK);
|
||||
|
||||
if ((int)node->fd <= 0)
|
||||
{
|
||||
printf("定时器注册失败:timerfd_create失败,%s\n" , strerror(errno));
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
struct itimerspec tval;
|
||||
tval.it_value.tv_sec = intervalms / 1000;
|
||||
tval.it_value.tv_nsec = (intervalms % 1000) * 1000000;
|
||||
|
||||
if (attr == KTIMER_PERIODIC) //多次触发时设置interval项
|
||||
{
|
||||
tval.it_interval.tv_sec = tval.it_value.tv_sec;
|
||||
tval.it_interval.tv_nsec = tval.it_value.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
tval.it_interval.tv_sec = 0;
|
||||
tval.it_interval.tv_nsec = 0;
|
||||
}
|
||||
|
||||
timerfd_settime(node->fd, 0, &tval, NULL);
|
||||
|
||||
//注册到Epoll池中
|
||||
struct epoll_event ev;
|
||||
memset(&ev , 0 , sizeof(struct epoll_event));
|
||||
if (attr == KTIMER_SINGLESHOT)
|
||||
ev.events = EPOLLIN | EPOLLONESHOT;
|
||||
else
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = node;
|
||||
if (epoll_ctl(epollfd , EPOLL_CTL_ADD , node->fd , &ev))
|
||||
{
|
||||
printf("定时器注册失败:epoll_ctl错误,%s\n" , strerror(errno));
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
insertIntoList(node);
|
||||
|
||||
return node->fd;
|
||||
}
|
||||
|
||||
//停止一个定时器,并从列表中移除
|
||||
void kyStopTimer(size_t timerfd)
|
||||
{
|
||||
if (timerfd <= 0)
|
||||
return;
|
||||
KTimerNode* node = findNodeByFD(timerfd);
|
||||
if (node)
|
||||
{
|
||||
if (epoll_ctl(epollfd , EPOLL_CTL_DEL , timerfd , NULL))
|
||||
{
|
||||
printf("无法注销文件句柄%zd : %s\n" , timerfd , strerror(errno));
|
||||
return;
|
||||
}
|
||||
deleteFromList(node , 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//定时器核心线程,负责循环处理已到期的定时器
|
||||
static void* timerCoreThread(void* data)
|
||||
{
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
KTimerNode* knode = NULL;
|
||||
int read_fds = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE , NULL);
|
||||
pthread_testcancel();
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE , NULL);
|
||||
|
||||
struct epoll_event activeEvs[KTIMER_MAXTIMERFD];
|
||||
read_fds = epoll_wait(epollfd , activeEvs , KTIMER_MAXTIMERFD , -1);
|
||||
if (read_fds < 0)
|
||||
{
|
||||
printf("epoll wait error , %s\n" , strerror(errno));
|
||||
continue;
|
||||
}
|
||||
for (int i = 0 ; i < read_fds ; i ++)
|
||||
{
|
||||
knode = activeEvs[i].data.ptr;
|
||||
pthread_mutex_lock(&knode->lock);
|
||||
if (!testNodeInList(knode))
|
||||
continue;
|
||||
uint64_t dep;
|
||||
read(knode->fd , &dep , sizeof(uint64_t));
|
||||
|
||||
if (knode && knode->attr != KTIMER_NEVER && knode->callback)
|
||||
{
|
||||
#if 1
|
||||
pthread_attr_t attr;
|
||||
pthread_t tid;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr , PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&tid , &attr , knode->callback , knode->userdata);
|
||||
|
||||
knode->freeOnDelete = 0;
|
||||
#else
|
||||
knode->callback(knode->userdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (knode->attr == KTIMER_SINGLESHOT) //单次触发的在触发后就从链表中移除
|
||||
{
|
||||
// FixMe: 如果设置了freeOnDelete,并且采用上面的线程执行模式,
|
||||
// 则会发生段错误。因此只能在启用线程执行模式的时候强制禁止
|
||||
// freeOnDelete。
|
||||
deleteFromList(knode , 1);
|
||||
}
|
||||
if (testNodeInList(knode))
|
||||
pthread_mutex_unlock(&knode->lock);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static KTimerNode* findNodeByFD(unsigned int fd)
|
||||
{
|
||||
KTimerNode* tmp = g_list;
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp->fd == fd)
|
||||
return tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int testNodeInList(KTimerNode* node)
|
||||
{
|
||||
KTimerNode* pos = g_list;
|
||||
while (pos)
|
||||
{
|
||||
if (pos == node)
|
||||
return 1;
|
||||
pos = pos->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void insertIntoList(KTimerNode* node)
|
||||
{
|
||||
curTimerCounts ++;
|
||||
if (!g_list)
|
||||
{
|
||||
g_list = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_list->intervalms > node->intervalms)
|
||||
{
|
||||
node->next = g_list;
|
||||
g_list = node;
|
||||
return;
|
||||
}
|
||||
|
||||
KTimerNode* cur = g_list->next;
|
||||
KTimerNode* prev = g_list;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
if (cur->intervalms > node->intervalms)
|
||||
{
|
||||
node->next = cur;
|
||||
prev->next = node;
|
||||
return;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
prev->next = node;
|
||||
node->next = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void deleteFromList(KTimerNode* node , int locked)
|
||||
{
|
||||
if (!g_list)
|
||||
return;
|
||||
curTimerCounts --;
|
||||
if (!locked)
|
||||
pthread_mutex_lock(&node->lock);
|
||||
if (node == g_list)
|
||||
{
|
||||
g_list = g_list->next;
|
||||
if (node->userdata && node->freeOnDelete)
|
||||
free(node->userdata);
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
|
||||
KTimerNode* pos = g_list;
|
||||
while (pos)
|
||||
{
|
||||
if (pos->next && pos->next == node)
|
||||
{
|
||||
pos->next = pos->next->next;
|
||||
if (node->userdata && node->freeOnDelete)
|
||||
free(node->userdata);
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
pos = pos->next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void kyResetTickCount(size_t timerfd , unsigned int intervalms)
|
||||
{
|
||||
KTimerNode* node = findNodeByFD(timerfd);
|
||||
if (!node)
|
||||
return;
|
||||
node->intervalms = intervalms;
|
||||
struct itimerspec tval;
|
||||
tval.it_value.tv_sec = intervalms / 1000;
|
||||
tval.it_value.tv_nsec = (intervalms % 1000) * 1000000;
|
||||
|
||||
if (node->attr == KTIMER_PERIODIC) //多次触发时设置interval项
|
||||
{
|
||||
tval.it_interval.tv_sec = tval.it_value.tv_sec;
|
||||
tval.it_interval.tv_nsec = tval.it_value.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
tval.it_interval.tv_sec = 0;
|
||||
tval.it_interval.tv_nsec = 0;
|
||||
}
|
||||
timerfd_settime(timerfd , 0 , &tval , NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void kyTimerDestroy() //停止所有定时器,并销毁定时器核心
|
||||
{
|
||||
//终止线程运行
|
||||
if (g_coreThreadID > 0)
|
||||
pthread_cancel(g_coreThreadID);
|
||||
|
||||
//销毁链表
|
||||
KTimerNode* node = g_list;
|
||||
while (node)
|
||||
{
|
||||
deleteFromList(node , 0);
|
||||
node = g_list;
|
||||
}
|
||||
|
||||
//关闭epoll池
|
||||
close(epollfd);
|
||||
return;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef __KY_TIMER_H__
|
||||
#define __KY_TIMER_H__
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KTIMER_SINGLESHOT = 0,
|
||||
KTIMER_PERIODIC = 1,
|
||||
KTIMER_NEVER = 2
|
||||
}KTimerAttribute;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KTIMER_ABSOLUTE = 0,
|
||||
KTIMER_RELATIVE
|
||||
}KTimerType;
|
||||
|
||||
#define KTIMER_MAXTIMERFD 1000 //最多支持注册1000个定时器
|
||||
|
||||
typedef void* (*time_handler)(void* user_data); //回调函数规则
|
||||
|
||||
typedef struct _KTimerNode{
|
||||
pthread_mutex_t lock;
|
||||
size_t fd; //序列号
|
||||
time_handler callback; //到期后执行的函数
|
||||
int freeOnDelete; //删除定时器时自动释放userdata
|
||||
void* userdata; //callback使用的参数,外部使用alloc分配内存,在delete定时器的时候会根据配置自动释放
|
||||
unsigned int intervalms; //定时器间隔时间,单位毫秒
|
||||
KTimerAttribute attr; //触发类型,单次触发或多次触发
|
||||
KTimerType type; //时钟类型,绝对时间还是相对时间
|
||||
struct _KTimerNode* next;
|
||||
}KTimerNode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
extern int kyTimerInitialize(); //初始化定时器核心
|
||||
extern size_t kyStartTimer(unsigned int intervalms, time_handler callback, KTimerAttribute attr, KTimerType type, void* userdata, int freeOnDelete); //注册并开始一个定时器,返回定时器句柄号
|
||||
extern void kyStopTimer(size_t timerfd); //停止一个定时器
|
||||
extern void kyResetTickCount(size_t timerfd , unsigned int intervalms); //重置一个定时器的时间
|
||||
extern void kyTimerDestroy(); //销毁定时器核心
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
all:
|
||||
gcc -g -O0 -o demo main.c -lkytimer -lpthread
|
||||
|
||||
clean:
|
||||
rm demo
|
|
@ -1,62 +0,0 @@
|
|||
#include <libkytimer.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
void func(char* comment)
|
||||
{
|
||||
char date[32] = {0};
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (ctime_r(&now , date))
|
||||
date[strlen(date) - 1] = '\0';
|
||||
printf("[%s]这是%s\n" , date , comment);
|
||||
}
|
||||
|
||||
void stop(size_t* fdpoll)
|
||||
{
|
||||
printf("开始停止定时器\n");
|
||||
for (int i = 0 ; i < 10 ; i ++)
|
||||
{
|
||||
kyStopTimer(fdpoll[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
assert(kyTimerInitialize() == 0);
|
||||
|
||||
//测试1 -- 基本功能
|
||||
size_t fdpoll[10] = {0};
|
||||
for (int i = 1 ; i <= 10 ; i ++)
|
||||
{
|
||||
char* data = (char*)malloc(10);
|
||||
assert(data);
|
||||
sprintf(data , "%d号" , i);
|
||||
fdpoll[i - 1] = kyStartTimer(i * 1000 , (time_handler)func , KTIMER_PERIODIC , (void*)data , 1);
|
||||
assert(fdpoll[i - 1]);
|
||||
}
|
||||
kyStartTimer(10000 , (time_handler)stop , KTIMER_SINGLESHOT , (void*)fdpoll , 0);
|
||||
sleep(11);
|
||||
|
||||
//测试3 -- 单次触发
|
||||
printf("单次触发测试:\n");
|
||||
kyStartTimer(2000 , (time_handler)func , KTIMER_SINGLESHOT , "2号" , 0);
|
||||
sleep(5);
|
||||
|
||||
//测试2 -- 重置定时器时间
|
||||
printf("修改时间测试:\n");
|
||||
int persec = kyStartTimer(1000 , (time_handler)func , KTIMER_PERIODIC , "1号" , 0);
|
||||
int sec3 = kyStartTimer(3000 , (time_handler)func , KTIMER_SINGLESHOT , "3号" , 0);
|
||||
sleep(2);
|
||||
kyResetTickCount(sec3 , 4000);
|
||||
printf("sec3 时钟已被重置为4000ms\n");
|
||||
sleep(10);
|
||||
|
||||
printf("正在销毁定时器核心...\n");
|
||||
kyTimerDestroy();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue