constructor / destructor
意思是: 构造器和析构器;constructor修饰的函数会在main函数之前执行,destructor修饰的函数会在程序exit前调用.
示例如下:
int main(int argc, char * argv[]) {
@autoreleasepool {
NSLog(@"main");
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
__attribute__((constructor))
void before(){
NSLog(@"before main");
}
__attribute__((destructor))
void after(){
NSLog(@"after main");
}
//在viewController中调用exit
- (void)viewDidLoad {
[super viewDidLoad];
exit(0);
}
输出如下:
2016-07-21 21:49:17.446 Study[14162:5415982] before main
2016-07-21 21:49:17.447 Study[14162:5415982] main
2016-07-21 21:49:17.534 Study[14162:5415982] after main
因此可以根据每一个模块封装成对应的加载接口和卸载接口。
太懒了,直接贴代码。。
版本一,初步封装
#include <stdio.h>
typedef struct ks_module_info
{
const char* name;
unsigned char priority;
int (*load)(void);
int (*unload)(void);
}ks_module_info;
void ks_module_register(const struct ks_module_info *info);
void ks_module_unregister(const struct ks_module_info *info);
void ks_module_register(const struct ks_module_info* info)
{
printf("##### before main, ks_module_register ######\n");
info->load();
}
void ks_module_unregister(const struct ks_module_info* info)
{
printf("##### after main, ks_module_unregister ######\n");
info->unload();
}
#define KS_MODULE_INFO(name, load_pri, load_func, unload_func) \
static struct ks_module_info __mod_info = { \
name, \
load_pri, \
load_func, \
unload_func, \
}; \
static void __attribute__((constructor)) __reg_module(void) \
{ \
ks_module_register(&__mod_info); \
} \
static void __attribute__((destructor)) __unreg_module(void) \
{ \
ks_module_unregister(&__mod_info); \
}
#define MD_FAILOVER_NAME "mod_failover"
enum MD_PRIORITY
{
MD_DAEMON_PRIORITY = 1,
MD_FAILOVER_PRIORITY,
};
static int unload_module(void)
{
printf("########### unload module ########\n");
return 0;
}
static int load_module(void)
{
printf("########### load module ########\n");
return 0;
}
int main(int argc,char **argv)
{
printf("hello world!\n");
return 0;
}
KS_MODULE_INFO(MD_FAILOVER_NAME, MD_FAILOVER_PRIORITY, load_module, unload_module);
版本二,实际项目中可能运用的方法
工程文件
kscore.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "kscore.h"
#include "ksstd.h"
#include "ksmodule.h"
#define MAX_STR_LEN 64
static void load_modules()
{
int i = 0;
int modulecount = 0;
struct ks_module_info *modules = NULL;
ks_get_modules(&modules, &modulecount);
if (!modules || !modulecount)
{
ksdebug(DEBUG_ERR, "get modules fail.");
return;
}
for (i = 0; i < modulecount; i++)
{
if (!modules[i].name)
continue;
modules[i].load();
}
}
static void unload_modules()
{
int i;
int modulecount = 0;
struct ks_module_info *modules = NULL;
ks_get_modules(&modules, &modulecount);
if (!modules || !modulecount)
return;
i = modulecount-1;
for ( ; i >= 0; i--)
{
if (!modules[i].name)
continue;
modules[i].unload();
}
}
//
//
int ks_core_start(int verify)
{
load_modules();
return 0;
}
int ks_core_stop()
{
unload_modules();
return 0;
}
int ks_core_unload_module(int priority)
{
int i, modulecount = 0;
struct ks_module_info *modules = NULL;
ksprintf("==================ks_core_unload_module:%d====================", priority);
ks_get_modules(&modules, &modulecount);
if (!modules || !modulecount)
return -1;
i = modulecount-1;
for ( ; i >= 0; i--)
{
if (!modules[i].name)
continue;
if(priority == modules[i].priority)
modules[i].unload();
}
return 0;
}
kscore.h
#ifndef _KS_CORE_H_
#define _KS_CORE_H_
#ifdef __cplusplus
extern "C"
{
#endif
int ks_core_start();
int ks_core_stop();
int ks_core_unload_module(int priority);
#ifdef __cplusplus
}
#endif
#endif
ksdefs.h
#ifndef _KS_CORE_H_
#define _KS_CORE_H_
#ifdef __cplusplus
extern "C"
{
#endif
int ks_core_start();
int ks_core_stop();
int ks_core_unload_module(int priority);
#ifdef __cplusplus
}
#endif
#endif
ksmodule.c
#include "ksmodule.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ksstd.h"
static int ks_module_debug = 0;
static int global_md_cnt = 0;
static struct ks_module_info global_modules[MAX_KS_MODULE] = {{0}};
static struct ks_module_info* find_module(const char* name)
{
int i = 0;
for ( ; i < MAX_KS_MODULE; i++)
{
if (global_modules[i].name && strcasecmp(global_modules[i].name, name)==0)
return &global_modules[i];
}
return NULL;
}
static void insert_module_info(struct ks_module_info modules[MAX_KS_MODULE], struct ks_module_info* info)
{
int idx = 0;
for ( ; idx < global_md_cnt; idx++)
{
if (info->priority > modules[idx].priority)
break;
}
int move = global_md_cnt;
for ( ; move > idx; move--)
{
memcpy(modules+move, modules+move-1, sizeof(struct ks_module_info));
}
memcpy(modules+idx, info, sizeof(struct ks_module_info));
global_md_cnt++;
if (ks_module_debug)
{
int i = 0;
for ( ; i < global_md_cnt; i++)
{
ksprintf("module-%d name:%s", i+1, modules[i].name);
}
}
}
void ks_module_register(const struct ks_module_info* info)
{
if (!info || !info->name)
return;
if (find_module(info->name))
return;
if (global_md_cnt >= MAX_KS_MODULE)
return;
int i = 0;
for ( ; i < MAX_KS_MODULE; i++)
{
if (global_modules[i].name)
continue;
insert_module_info(global_modules, (struct ks_module_info*)(info));
break;
}
}
void ks_module_unregister(const struct ks_module_info* info)
{
if (!info || !info->name)
return;
struct ks_module_info* mod = find_module(info->name);
if (!mod)
return;
memset(mod, 0, sizeof(struct ks_module_info));
global_md_cnt--;
}
int ks_get_modules(struct ks_module_info **modules, int *capability)
{
if (!modules || !capability)
return -1;
*modules = global_modules;
*capability = global_md_cnt;
return 0;
}
ksmodule.h
/*
* Filename: ksmodule
* Created at: 2019.02.26
* Description: module controller.
* Author: ks
* Copyright (C) xxl
* ****************************************************************/
#ifndef _KS_MODULE_H_
#define _KS_MODULE_H_
#ifdef __cplusplus
extern "C"
{
#endif
#define KS_MODULE_CONF "/mnt/nand/etc/modules.conf"
#define MAX_KS_MODULE 4
enum MD_PRIORITY
{
MD_PRIORITY_LOG = 1,
MD_PRIORITY_SEARCH = 2,
MD_PRIORITY_SYSCONF = 3,
MD_PRIORITY_FAILOVER = 4,
};
#define MD_NAME_LOG "log"
#define MD_NAME_SEARCH "search"
#define MD_NAME_SYSCONF "sysconf"
#define MD_NAME_FAILOVER "failover"
typedef struct ks_module_info
{
const char* name;
unsigned char priority;
int (*load)(void);
int (*unload)(void);
}ks_module_info;
void ks_module_register(const struct ks_module_info *info);
void ks_module_unregister(const struct ks_module_info *info);
#define KS_MODULE_INFO(name, load_pri, load_func, unload_func) \
static struct ks_module_info __mod_info = { \
name, \
load_pri, \
load_func, \
unload_func, \
}; \
static void __attribute__((constructor)) __reg_module(void) \
{ \
ks_module_register(&__mod_info); \
} \
static void __attribute__((destructor)) __unreg_module(void) \
{ \
ks_module_unregister(&__mod_info); \
}
int ks_get_modules(struct ks_module_info **modules, int *capability);
#ifdef __cplusplus
}
#endif
#endif
ksstd.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ksstd.h"
void time_to_string(int ntime, char stime[32])
{
struct tm temp;
localtime_r((long*)&ntime, &temp);
snprintf(stime, 32, "%4d-%02d-%02d %02d:%02d:%02d",
temp.tm_year + 1900, temp.tm_mon + 1, temp.tm_mday, temp.tm_hour, temp.tm_min, temp.tm_sec);
}
void time_to_string_ks(char stime[32])
{
struct tm temp;
struct timeval tv;
gettimeofday(&tv, NULL);
localtime_r(&tv.tv_sec, &temp);
snprintf(stime, 32, "%4d-%02d-%02d %02d:%02d:%02d.%03d",
temp.tm_year + 1900, temp.tm_mon + 1, temp.tm_mday, temp.tm_hour, temp.tm_min, temp.tm_sec,(int)(tv.tv_usec/1000));
}
ksstd.h
#ifndef _KS_STD_H_
#define _KS_STD_H_
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
{
#endif
void time_to_string(int ntime, char stime[32]);
void time_to_string_ks(char stime[32]);
/* Word color define */
#define YELLOW "\033[0;33m" // yellow
#define GRAY "\033[2;37m"
#define DGREEN "\033[1;32m"
#define GREEN "\033[0;32m"
#define DARKGRAY "\033[0;30m"
//#define BLACK "\033[0;39m"
#define BLACK "\033[2;30m" // not faint black
#define NOCOLOR "\033[0;39m \n"
#define CLRCOLOR "\033[0;39m "
//#define NOCOLOR "\033[0m \n"
#define BLUE "\033[1;34m"
#define DBLUE "\033[2;34m"
#define RED "\033[0;31m"
#define BOLD "\033[1m"
#define UNDERLINE "\033[4m"
#define CLS "\014"
#define NEWLINE "\r\n"
#define DEBUG_LEVEL_DEFAULT 0xffffffff
extern unsigned int global_debug_mask;
typedef void (*hook_print)(char* format, ...);
extern hook_print global_debug_hook;
#define ERR_LOG_PATH "./err_log.txt"
enum DEBUG_LEVEL
{
DEBUG_ERR = 0x01,
DEBUG_WRN = 0x02,
DEBUG_INF = 0x04,
DEBUG_GUI = 0x08,
DEBUG_POE = 0X10,
};
#define _log_err(level, prefix, format, ...) \
do{\
if(global_debug_mask & level){\
char stime[32] = {0};\
char log[1024] = {0};\
char cmd[128] = {0};\
int filesize = -1;\
FILE * hfile = NULL;\
hfile = fopen(ERR_LOG_PATH, "a");\
if(hfile){\
fseek(hfile, 0L, SEEK_END);\
filesize = ftell(hfile);\
time_to_string(time(0), stime);\
snprintf(log, sizeof(log), "[%s%s %d==func:%s file:%s line:%d]==" format "\n", \
prefix, stime, getpid(), __func__, __FILE__, __LINE__, ##__VA_ARGS__); \
fwrite(log, 1, strlen(log), hfile);\
fflush(hfile);\
fclose(hfile);\
snprintf(cmd, sizeof(cmd), "rm -rf %s", ERR_LOG_PATH);\
if(filesize > 1024*1024)\
system(cmd);\
}\
}\
}while(0);
#define mslogerr(level, format, ...) \
if(level == DEBUG_ERR){\
_debug(level, "ERR:",RED format CLRCOLOR, ##__VA_ARGS__)\
_log_err(level, "ERR:", format, ##__VA_ARGS__)\
}else if(level == DEBUG_WRN)\
_log_err(level, "WRN:", format, ##__VA_ARGS__)\
else\
_log_err(level, "INF:", format, ##__VA_ARGS__)
#define _debug(level, prefix, format, ...) \
do{\
if(global_debug_mask & level){\
char stime[32] = {0};\
time_to_string_ks(stime);\
printf("[%s%s %d==func:%12s file:%12s line:%6d]==" format "\n", \
prefix, stime, getpid(), __func__, __FILE__, __LINE__, ##__VA_ARGS__); \
if(global_debug_hook)\
global_debug_hook("[%s%s %d==func:%12s file:%12s line:%6d]==" format "\n",\
prefix, stime, getpid(), __func__, __FILE__, __LINE__, ##__VA_ARGS__);\
}\
}while(0);
#define ksdebug(level, format, ...) \
do { \
switch(level) \
{ \
case DEBUG_ERR: \
_debug(level, "ERR:",RED format CLRCOLOR, ##__VA_ARGS__); \
_log_err(level, "ERR:", format, ##__VA_ARGS__); \
break; \
case DEBUG_WRN: \
_debug(level, "WRN:",YELLOW format CLRCOLOR, ##__VA_ARGS__); \
break; \
case DEBUG_GUI: \
_debug(level, "GUI:",GREEN format CLRCOLOR, ##__VA_ARGS__); \
break; \
default: \
_debug(level, "INF:", format, ##__VA_ARGS__); \
break; \
} \
}while(0)
#define ksprintf(format, ...) \
do{\
char stime[32] = {0};\
time_to_string(time(0), stime);\
printf("[%s %d==func:%s file:%s line:%d]==" format "\n", \
stime, getpid(), __func__, __FILE__, __LINE__, ##__VA_ARGS__); \
}while(0)
#ifdef __cplusplus
}
#endif
#endif
main.c
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include "ksstd.h"
//#include "kscore.h"
int g_exitcore = 0;
unsigned int global_debug_mask = DEBUG_LEVEL_DEFAULT;
hook_print global_debug_hook = 0;
extern int global_record_run;
static int global_module_debug = 0;
static void signal_handler(int signal)
{
if(signal != SIGPIPE)
printf("mscore recv signal %d\n", signal);
switch(signal)
{
case SIGINT:
case SIGTERM:
case SIGKILL:
g_exitcore = 1;
break;
case SIGUSR2:
g_exitcore = 2;
break;
case SIGPIPE:
break;
default:
break;
}
}
static void signal_backtrace(int signo)
{
time_t t = time(NULL);
if(signo == 11)
{
printf("kscore received signal: %d, backtrace stack at time: %s...\n",signo, ctime(&t));
ksdebug(DEBUG_ERR, "kscore received signal: %d, backtrace stack at time: %s...\n",signo, ctime(&t));
}
exit(0);
}
static void set_core_signal()
{
signal(SIGINT, signal_handler); //2//
signal(SIGTERM, signal_handler); //15
signal(SIGKILL, signal_handler); //9
signal(SIGPIPE, signal_handler); //13
signal(SIGUSR2, signal_handler); //12
signal(SIGSEGV, signal_backtrace); //11
signal(SIGBUS, signal_backtrace); // 7
signal(SIGILL, signal_backtrace); // 4
signal(SIGSTKFLT, signal_backtrace);// 16
signal(SIGFPE, signal_backtrace); // 8
signal(SIGABRT, signal_backtrace); //6
}
int main(int argc,char **argv)
{
ksprintf("hello world!");
ks_core_start(1);
set_core_signal();
//maybe run a thread
while (1)
{
if (g_exitcore)
{
break;
}
usleep(100*1000);//100ms
}
ks_core_stop();
return 0;
}
mod_failover.c
/*
* Filename: mod_failover
* Created at: 2019.02.26
* Description: failover module
* Author: ks
* Copyright (C) xxl
* *******************************************************/
#include <string.h>
#include "ksmodule.h"
#include "ksstd.h"
struct md_failover_conf
{
int loaded;
int debug;
};
static struct md_failover_conf g_failover_conf = {0};
static int init_module()
{
return 0;
}
static int uninit_module()
{
return 0;
}
static int load_module(void)
{
if(g_failover_conf.loaded)
return 1;
ksprintf("====load module:%s====", MD_NAME_FAILOVER);
g_failover_conf.loaded = 1;
g_failover_conf.debug = 0;
if(init_module() != 0)
{
ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_FAILOVER);
g_failover_conf.loaded = 0;
return -1;
}
return 0;
}
static int unload_module(void)
{
if (g_failover_conf.loaded == 0)
return 1;
g_failover_conf.loaded = 0;
uninit_module();
ksprintf("====unload %s success.====", MD_NAME_FAILOVER);
return 0;
}
KS_MODULE_INFO(MD_NAME_FAILOVER, MD_PRIORITY_FAILOVER, load_module, unload_module);
mod_log.c
/*
* Filename: mod_log
* Created at: 2019.02.26
* Description: log module
* Author: ks
* Copyright (C) xxl
* *******************************************************/
#include <string.h>
#include "ksmodule.h"
#include "ksstd.h"
struct md_log_conf
{
int loaded;
int debug;
};
static struct md_log_conf g_log_conf = {0};
static int init_module()
{
return 0;
}
static int uninit_module()
{
return 0;
}
static int load_module(void)
{
if(g_log_conf.loaded)
return 1;
ksprintf("====load module:%s====", MD_NAME_LOG);
g_log_conf.loaded = 1;
g_log_conf.debug = 0;
if(init_module() != 0)
{
ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_LOG);
g_log_conf.loaded = 0;
return -1;
}
return 0;
}
static int unload_module(void)
{
if (g_log_conf.loaded == 0)
return 1;
g_log_conf.loaded = 0;
uninit_module();
ksprintf("====unload %s success.====", MD_NAME_LOG);
return 0;
}
KS_MODULE_INFO(MD_NAME_LOG, MD_PRIORITY_LOG, load_module, unload_module);
mod_search.c
/*
* Filename: mod_search
* Created at: 2019.02.26
* Description: search module
* Author: ks
* Copyright (C) xxl
* *******************************************************/
#include <string.h>
#include "ksmodule.h"
#include "ksstd.h"
struct md_search_conf
{
int loaded;
int debug;
};
static struct md_search_conf g_search_conf = {0};
static int init_module()
{
return 0;
}
static int uninit_module()
{
return 0;
}
static int load_module(void)
{
if(g_search_conf.loaded)
return 1;
ksprintf("====load module:%s====", MD_NAME_SEARCH);
//int *x = NULL;
//*x = 1;
g_search_conf.loaded = 1;
g_search_conf.debug = 0;
if(init_module() != 0)
{
ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_SEARCH);
g_search_conf.loaded = 0;
return -1;
}
return 0;
}
static int unload_module(void)
{
if (g_search_conf.loaded == 0)
return 1;
g_search_conf.loaded = 0;
uninit_module();
ksprintf("====unload %s success.====", MD_NAME_SEARCH);
return 0;
}
KS_MODULE_INFO(MD_NAME_SEARCH, MD_PRIORITY_SEARCH, load_module, unload_module);
mod_sysconf.c
/*
* Filename: mod_sysconf
* Created at: 2019.02.26
* Description: sysconf module
* Author: ks
* Copyright (C) xxl
* *******************************************************/
#include <string.h>
#include "ksmodule.h"
#include "ksstd.h"
struct md_sysconf_conf
{
int loaded;
int debug;
};
static struct md_sysconf_conf g_sysconf_conf = {0};
static int init_module()
{
return 0;
}
static int uninit_module()
{
return 0;
}
static int load_module(void)
{
if(g_sysconf_conf.loaded)
return 1;
ksprintf("====load module:%s====", MD_NAME_SYSCONF);
g_sysconf_conf.loaded = 1;
g_sysconf_conf.debug = 0;
if(init_module() != 0)
{
ksdebug(DEBUG_WRN, "load module:%s failed.", MD_NAME_SYSCONF);
g_sysconf_conf.loaded = 0;
return -1;
}
return 0;
}
static int unload_module(void)
{
if (g_sysconf_conf.loaded == 0)
return 1;
g_sysconf_conf.loaded = 0;
uninit_module();
ksprintf("====unload %s success.====", MD_NAME_SYSCONF);
return 0;
}
KS_MODULE_INFO(MD_NAME_SYSCONF, MD_PRIORITY_SYSCONF, load_module, unload_module);
运行结果