sclog 是一個輕量級、跨平台的 C 語言日誌庫,支援:
sc.log(全量)、sc.log.wf(僅 WARNING/FATAL)_DEBUG 宏決定 TRACE/DEBUG 是否編入發布版// 線程私有信息體
struct slinfo {
unsigned logid; // 全局唯一請求 ID
char reqip[_INT_LITTLE]; // 客戶端 IP
char times[_INT_LITTLE]; // 處理耗時(微秒)
struct timeval timev; // 開始時間戳
char mod[_INT_LITTLE]; // 模組名
};
// 全局單例
static struct {
pthread_key_t key; // 線程私有鍵
pthread_once_t once; // 單次初始化
unsigned logid; // 原子自增 ID
FILE *log; // 普通日誌句柄
FILE *wf; // 告警日誌句柄
} _slmain = {0, PTHREAD_ONCE_INIT, 0, NULL, NULL};
使用 pthread_key_create + pthread_setspecific/getspecific 實現每線程獨立的 slinfo,避免鎖競爭。鍵創建僅執行一次(pthread_once),銷毀回調 _slinfo_destroy 防止內存洩漏。
// 統一 gettimeofday (Windows 移植)
#if defined(_MSC_VER)
int gettimeofday(struct timeval *tv, void *tz) {
SYSTEMTIME wtm; GetLocalTime(&wtm);
struct tm tm = {wtm.wYear-1900, wtm.wMonth-1, wtm.wDay,
wtm.wHour, wtm.wMinute, wtm.wSecond, 0, 0, -1};
time_t clock = mktime(&tm);
tv->tv_sec = (long)clock;
tv->tv_usec = wtm.wMilliseconds * 1000;
return 0;
}
#define localtime_r(t, tm) localtime_s(tm, t)
#else
#include
#endif
// 原子操作封裝
#if defined(_MSC_VER)
#define ATOM_ADD_FETCH(v, a) InterlockedAdd((LONG*)&(v), (LONG)(a))
#elif defined(__GNUC__)
#define ATOM_ADD_FETCH(v, a) __sync_add_and_fetch(&(v), (a))
#endif
格式:[LEVEL][YYYY-MM-DD HH:MM:SS.usec][file:line:func][logid:XXX][reqip:IP][mod:NAME] msg
#define SCLOG_PUTS(fstr) "[" fstr "][%s:%d:%s][logid:%u][reqip:%s][mod:%s]"
#define SCLOG_PRINTF(fstr, fmt, ...) \
sl_printf(SCLOG_PUTS(fstr) fmt "\n", __FILE__, __LINE__, __func__, \
sl_getlogid(), sl_getreqip(), sl_getmod(), ##__VA_ARGS__)
#define SL_FATAL(fmt, ...) SCLOG_PRINTF(_STR_SCLOG_FATAL, fmt, ##__VA_ARGS__)
#define SL_INFO(fmt, ...) SCLOG_PRINTF(_STR_SCLOG_INFO, fmt, ##__VA_ARGS__)
// ... 其他級別宏
// 發布版移除 DEBUG/TRACE
#if defined(_DEBUG)
#define SL_DEBUG(fmt, ...) SCLOG_PRINTF(_STR_SCLOG_DEBUG, fmt, ##__VA_ARGS__)
#else
#define SL_DEBUG(fmt, ...) /* nothing */
#endif
char logs[_INT_LOG] (8KB) 避免堆分配開銷。fputs 在 POSIX 下線程安全,省去鎖開銷。.wf 文件。// main.c #include "sclog.h" #includevoid *worker(void *arg) { sl_init("worker", "192.168.1.1", 0); for (int i = 0; i < 100; ++i) { SL_INFO("處理任務 %d", i); SL_WARNING("任務 %d 耗時較長", i); } return NULL; } int main() { sl_start(); // 初始化日誌系統 pthread_t t1, t2; pthread_create(&t1, NULL, worker, NULL); pthread_create(&t2, NULL, worker, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); return 0; // atexit 自動調用 _sl_end 清理 }
# Linux gcc -Wall -ggdb -o main.out main.c sclog.c schead.c scatom.c -lpthread # Windows (需 pthreads-w32) cl main.c sclog.c schead.c scatom.c /I. /D_MSC_VER /link pthreadVC2.lib
sclog 展示了工業級 C 庫的核心要素:跨平台抽象層、線程本地存儲、原子操作、編譯期特性裁剪、資源 RAII 風格管理。適合作為學習 C 系統編程、或項目中直接集成的輕量日誌組件。