sc_console/
├── Makefile # 構建腳本
├── main/
│ └── main.c # 業務入口與測試
└── module/
└── schead/ # 核心基礎模塊
├── include/ # 對外頭文件
│ ├── scatom.h # 原子操作
│ ├── schead.h # 跨平台宏/工具
│ └── sclog.h # 多級日誌接口
├── schead.c # 平台相關實現
└── sclog.c # 日誌核心實現
CC=gcc
DEBUG=-g -Wall -D_DEBUG
PTHREAD=-lpthread
DIR=-I./module/schead/include
RUN=$(CC) $(DEBUG) -o $@ $^ $(PTHREAD) $(DIR)
RUNO=$(CC) $(DEBUG) -c -o $@ $^ $(DIR)
sc_console.out: main.o schead.o sclog.o
$(RUN)
main.o: ./main/main.c
$(RUNO)
schead.o: ./module/schead/schead.c
$(RUNO)
sclog.o: ./module/schead/sclog.c
$(RUNO)
clean:
rm -rf *.i *.s *.o *.out __* log; ls -hl
屏蔽 GCC `__sync_*` 與 MSVC `Interlocked*` 差異:
/* scatom.h 關鍵宏 */
#if defined(_MSC_VER)
#define ATOM_FETCH_ADD(v,a) InterlockedExchangeAdd((LONG*)&(v), (LONG)(a))
#define ATOM_LOCK(v) while(ATOM_SET(v,1)) Sleep(0)
#elif defined(__GNUC__)
#define ATOM_FETCH_ADD(v,a) __sync_fetch_and_add(&(v), (a))
#define ATOM_LOCK(v) while(ATOM_SET(v,1)) usleep(2)
#endif
提供:原子增減、設置、比較交換、自旋鎖。注意:MSVC 強轉 `LONG*` 因 API 要求 32 位操作數。
/* sclog.c 關鍵點 */
static pthread_key_t __lkey;
static pthread_once_t __lonce = PTHREAD_ONCE_INIT;
static unsigned __logid = 0;
int sl_pecific_init(const char* mod, const char* reqip) {
pthread_once(&__lonce, __gkey); // 單次創建 key
struct slinfo* pl = pthread_getspecific(__lkey);
if (!pl) pl = malloc(sizeof(*pl)); // 首次分配
gettimeofday(&pl->timev, NULL);
pl->logid = ATOM_ADD_FETCH(__logid, 1); // 原子遞增唯一ID
strcpy(pl->mod, mod);
strcpy(pl->reqip, reqip);
pthread_setspecific(__lkey, pl);
return _RT_OK;
}
int sl_printf(const char* format, ...) {
char tstr[64], logs[8192];
sh_times(tstr, 63); // 當前時間戳
int len = snprintf(logs, sizeof(logs), "[%s ", tstr);
va_list ap; va_start(ap, format);
vsnprintf(logs+len, sizeof(logs)-len, format, ap);
va_end(ap);
fputs(logs, __slmain.log); // fputs 線程安全
if (format[4]=='F' || format[4]=='W') // FATAL/WARNING
fputs(logs, __slmain.wf);
return _RT_OK;
}
Linux/Windows 雙平台編譯運行,生成結構化日誌:
[2017-01-21 10:17:33][FATAL][main.c:45:main][logid:1][reqip:0.0.0.0][mod:main thread] pthread test one fatal is at 0, It's OK.
[2017-01-21 10:17:33][WARNING][main.c:46:main][logid:1][reqip:0.0.0.0][mod:main thread] pthread test one warning is at 0, It's OK.
完美實現跨平台、多線程、分級、帶上下文的生產級日誌系統。