skynet源码浏览系列从main函数开始 net源码使用教程

skynet 是C语言编辑的框架 。人类选用学习过程中最基本的方法去浏览skynet 。从C语言的main函数开始 。
首先人类找到框架的入口main函数 。在 skynet/skynet-src/skynet_main.c 文件内 。
main函数的代码如下:
intmain(int argc, char *argv[]) {const char * config_file = NULL ;if (argc 1) {config_file = argv[1];} else {fprintf(stderr, "Need a config file. Please read skynet wiki : ;}人类一段一段查就这样看
intmain(int argc, char *argv[]) {const char * config_file = NULL ;if (argc 1) {config_file = argv[1];} else {fprintf(stderr, "Need a config file. Please read skynet wiki : 赋值为启动时的第二个参数 。也就是配置文件的路径 。
skynet_globalinit();
// skynet/skynet-src/skynet_server.cstruct skynet_node {ATOM_INT total;int init;uint32_t monitor_exit;pthread_key_t handle_key;bool profile;// default is off};static struct skynet_node G_NODE;void skynet_globalinit(void) {ATOM_INIT(&G_NODE.total , 0);G_NODE.monitor_exit = 0;G_NODE.init = 1;if (pthread_key_create(&G_NODE.handle_key, NULL)) {fprintf(stderr, "pthread_key_create failed");exit(1);}// skynet/skynet-src/skynet_imp.h/*#define THREAD_WORKER 0#define THREAD_MAIN 1#define THREAD_SOCKET 2#define THREAD_TIMER 3#define THREAD_MONITOR 4*/skynet_initthread(THREAD_MAIN);}skynet_initthread(int m) {// skynet/skynet-src/atomic.h// #define ATOM_POINTER volatile uintptr_tuintptr_t v = (uint32_t)(-m);pthread_setspecific(G_NODE.handle_key, (void *)v);}初始化全局节点信息。total 为0 。monitor_exit 为0 。init 1 。
pthread_key_create(&G_NODE.handle_key, NULL) 创建了一个多线程私有资料handle_key:
skynet_initthread(THREAD_MAIN); 将目前线程情况由 THREAD_MAIN 更换为 THREAD_WORKER 情况并记录在handle_key 。
skynet_env_init();
// skynet/skynet-src/skynet_env.cstruct skynet_env {struct spinlock lock;lua_State *L;};static struct skynet_env *E = NULL;voidskynet_env_init() {E = skynet_malloc(sizeof(*E));SPIN_INIT(E)E-L = luaL_newstate();}E 一个skynet_env结构体 。结构体内包含一个 spinlock 自旋锁 。一个lua虚拟机指针 。
skynet_malloc 为结构体E分配内存 。skynet_malloc内部暂时不细究 。
SPIN_INIT(E)
通过查找代码得知, 这是在 skynet/skynet-src/spinlick.h 中定义的一个宏 。#define SPIN_INIT(q) spinlock_init(&(q)-lock);对E中的lock 进行初始化 。
E-L = luaL_newstate(); L绑定了一个lua虚拟机 。
sigign();
#include signal.hint sigign() {struct sigaction sa;sa.sa_handler = SIG_IGN;sa.sa_flags = 0;sigemptyset(&sa.sa_mask);sigaction(SIGPIPE, &sa, 0);return 0;}main 函数同文件下的 sigign() 函数 。
定义了一个 sigaction 结构体 。将 sa_handler 设置为 SIG_IGN 。表示要忽略信号的发生的动作 。
sigaction(SIGPIPE, &sa, 0); 将 SIGPIPE的行为代替为 sa 结构体定义的形式 。表示目前进程忽略 SIGPIPE 信号 。
这里简单记录了一下 sigaction 的资料 。
01ext_sigaction
struct skynet_config config;
定义了结构体 config
struct skynet_config {int thread;int harbor;int profile;const char * daemon;const char * module_path;const char * bootstrap;const char * logger;const char * logservice;};luaL_initcodecache();
// skynet/skynet-src/skynet_main.c#ifdef LUA_CACHELIBluaL_initcodecache();#endif// skynet/3rd/lauxlib.cstatic struct codecache CC;struct codecache {struct spinlock lock;lua_State *L;};LUALIB_API voidluaL_initcodecache(void) {SPIN_INIT(&CC);}static const char * load_config = "\local result = {}\n\local function getenv(name) return assert(os.getenv(name), [[os.getenv() failed: ]] .. name) end\n\local sep = package.config:sub(1,1)\n\local current_path = [[.]]..sep\n\local function include(filename)\n\local last_path = current_path\n\local path, name = filename:match([[(.*]]..sep..[[)(.*)$]])\n\if path then\n\if path:sub(1,1) == sep then-- root\n\current_path = path\n\else\n\current_path = current_path .. path\n\end\n\else\n\name = filename\n\end\n\local f = assert(io.open(current_path .. name))\n\local code = assert(f:read [[*a]])\n\code = string.gsub(code, [[%$([%w_%d]+)]], getenv)\n\f:close()\n\assert(load(code,[[@]]..filename,[[t]],result))()\n\current_path = last_path\n\end\n\setmetatable(result, { __index = { include = include } })\n\local config_name = ...\n\include(config_name)\n\setmetatable(result, nil)\n\return result\n\&#34struct lua_State *L = luaL_newstate();luaL_openlibs(L);// link lua libint err = luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");assert(err == LUA_OK);lua_pushstring(L, config_file);err = lua_pcall(L, 1, 1, 0);if (err) {fprintf(stderr,"%s\n",lua_tostring(L,-1));lua_close(L);return 1;}luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");
加载了一段lua代码到内存里 。并压入lua栈内 。
load_config 这段代码实现的功能: 将配置文件内的 $var 代替成了环境变量的内容, 并返回了一个result表 。

推荐阅读