[修改] 调整整体代码结构目录

This commit is contained in:
Debaucher 2021-10-26 19:27:34 +08:00
parent 6eb7f6d723
commit 27e63d5aaf
36 changed files with 101 additions and 1281 deletions

29
CMakeLists.txt Normal file
View File

@ -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)

View File

@ -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

View File

@ -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

5
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
include_directories(/usr/include/kysdk/kysdk-base/)
# add_subdirectory(disk)
# add_subdirectory(systeminfo)
add_subdirectory(systemtime)

View File

@ -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__

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -1,5 +0,0 @@
all:
gcc -g -O0 -o demo main.c -lkytimer -lpthread
clean:
rm demo

View File

@ -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;
}

View File

@ -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.

View File

@ -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(&current);
now = localtime(&current);
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;
}

View File

@ -1,13 +0,0 @@
#ifndef KYSDK_SYSTIME_H__
#define KYSDK_SYSTIME_H__
extern void startBroadcastSystemTimePerMin();
/**
* @brief 1
*
* @return int
*/
extern int monitorSystemTimeChange();
#endif

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -1,5 +0,0 @@
all:
gcc -g -O0 -o demo main.c -lkytimer -lpthread
clean:
rm demo

View File

@ -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;
}