存档

‘源码阅读’ 分类的存档

Lua源码剖析(五)

2013年12月3日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: Lua源码剖析(五)

这次主要来分析lua的gc。

首先lua中的数据类型包括下面9种,ni, Boolean, number, string, table,user data, thread , functions 以及 lightusedata.其中 string, table,thread , function 是会被垃圾回收管理的,其他的都是值存在。

因此我们来看对应的GC数据结构.

#define CommonHeader     GCObject *next; lu_byte tt; lu_byte marked
 
typedef struct GCheader {
  CommonHeader;
} GCheader;

union GCObject {
  GCheader gch;
  union TString ts;
  union Udata u;
  union Closure cl;
  struct Table h;
  struct Proto p;
  struct UpVal uv;
  struct lua_State th;  /* thread */
};

我们可以看到在lua中字符串,userdata, thread, table ,string, thread(以及Upval, proto) 都会被垃圾回收管理。这里比较关键的就是GCheader这个结构体,我们可以看到这个结构体其实就是一个链表,也就是说所有的gc对象都会被链到一个链表中,其中tt表示当前对象的类型,在lua中包括下面这些类型:

#define LUA_TNIL          0
#define LUA_TBOOLEAN          1
#define LUA_TLIGHTUSERDATA     2
#define LUA_TNUMBER          3
#define LUA_TSTRING          4
#define LUA_TTABLE          5
#define LUA_TFUNCTION          6
#define LUA_TUSERDATA          7
#define LUA_TTHREAD          8

而marked表示当前对象的状态(涉及到gc算法,后续会详细分析),状态位包括下面这些:

#define WHITE0BIT     0
#define WHITE1BIT     1
#define BLACKBIT     2
#define FINALIZEDBIT     3
#define KEYWEAKBIT     3
#define VALUEWEAKBIT     4
#define FIXEDBIT     5
#define SFIXEDBIT     6
#define WHITEBITS     bit2mask(WHITE0BIT, WHITE1BIT)

阅读全文…

Share
分类: lua, 源码阅读 标签: ,

Lua源码剖析(四)

2013年9月8日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: Lua源码剖析(四)

前面三篇请看我前面的 blog

这篇主要来分析lua的虚拟机的实现,我看的代码依旧是5.1

因此首先从luaL_loadfile开始,这个函数我们知道是在当前的lua state加载一个lua文件,其中第二个参数就是filename。

其中LoadF结构很简单,它用来表示一个load file:

typedef struct LoadF {
  int extraline;
  FILE *f;
  char buff[LUAL_BUFFERSIZE];
} LoadF;

其中会使用fopen来打开对应的文件名,然后根据第一个字符来判断是否是注释(#),如果是则跳过

    lua_pushfstring(L, "@%s", filename);
    lf.f = fopen(filename, "r");
    if (lf.f == NULL) return errfile(L, "open", fnameindex);
  }
  c = getc(lf.f);
  if (c == '#') {  /* Unix exec. file? */
    lf.extraline = 1;
    while ((c = getc(lf.f)) != EOF && c != '\n') ;  /* skip first line */
    if (c == '\n') c = getc(lf.f);
  }

阅读全文…

Share
分类: lua, 源码阅读 标签:

nginx least_conn 模块源码剖析

2012年7月11日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx least_conn 模块源码剖析

nginx在1.3.1添加了一个新模块 least_conn,也就是我们常说的最少连接负载均衡算法,简单来说就是每次选择的都是当前最少连接的一个server(这个最少连接不是全局的,是每个进程都有自己的一个统计列表)。

在看最少连接模块之前需要对round robin模块有一定的了解,这里我就不对round robin模块进行分析了,想要看这块代码,可以去我们组 卫岳的blog的这篇文章
http://blog.sina.com.cn/s/blog_7303a1dc01014i0j.html

ok,接下来就来看这个模块,首先来看如何打开least_conn模块:

static ngx_command_t  ngx_http_upstream_least_conn_commands[] = {

    { ngx_string("least_conn"),
      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
      ngx_http_upstream_least_conn,
      0,
      0,
      NULL },

      ngx_null_command
};

阅读全文…

Share

一个out of socket memory的问题

2012年7月3日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: 一个out of socket memory的问题

今天同事遇到一个问题,就是server(read hat 5, kernel 2.6.18)的dmesg打出了下面两个信息

TCP: too many of orphaned sockets
Out of socket memory

一般我们看到这个信息,第一反应肯定是需要调节tcp_mem(/proc/sys/net/ipv4)了,可是根据当时的内存使用情况,使用的内存并没有超过 tcp_mem。然后我先去看了最新的内核代码,3.4.4,其中涉及到socket 内存报警在这里

bool tcp_check_oom(struct sock *sk, int shift)
{
	bool too_many_orphans, out_of_socket_memory;

	too_many_orphans = tcp_too_many_orphans(sk, shift);
	out_of_socket_memory = tcp_out_of_memory(sk);

	if (too_many_orphans && net_ratelimit())
		pr_info("too many orphaned sockets\n");
	if (out_of_socket_memory && net_ratelimit())
		pr_info("out of memory -- consider tuning tcp_mem\n");
	return too_many_orphans || out_of_socket_memory;
}

上面的代码很简单,就是如果孤儿socket太多,则打印警告,然后如果socket memory超过限制,也打印出警告。
阅读全文…

Share
分类: kernel, 源码阅读 标签: , ,

mochiweb源码分析(二)

2012年5月30日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: mochiweb源码分析(二)

这次主要来看mochiweb如何处理http协议以及如何将外部模块加载到mochiweb框架中。

首先在上一篇的分析最后,我们知道当accept句柄之后,mochiweb最终会调用call_loop方法,那么我们就从call_loop开始

call_loop({M, F}, Socket) ->
    M:F(Socket);
call_loop({M, F, [A1]}, Socket) ->
    M:F(Socket, A1);
call_loop({M, F, A}, Socket) ->
    erlang:apply(M, F, [Socket | A]);
call_loop(Loop, Socket) ->
    Loop(Socket).

阅读全文…

Share

mochiweb源码分析(一)

2012年5月19日 4 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: mochiweb源码分析(一)

这篇主要分析下mochiweb的整体结构。

我这里看的代码是github上的最新代码( https://github.com/mochi/mochiweb )。

由于mochiweb是一个框架,因此我们就从他自带的简单例子入手,来看他是如何工作的。我们就从keepalive.erl开始。

首先来看这个模块的start函数,也就是它的启动函数:

-define(LOOP, {?MODULE, loop}).

start(Options = [{port, _Port}]) ->
    mochiweb_http:start([{name, ?MODULE}, {loop, ?LOOP} | Options]).

可以看到启动函数非常简单,那就是直接调用mochiweb_http模块的start函数。那么我们整个分析流程,就从这个模块的start函数开始。这里要注意,我们可以看到是将当前回调模块的loop函数传递给了mochiweb_http,这就给后续调用回调,提供了接口。

%% @spec start(Options) -> ServerRet
%%     Options = [option()]
%%     Option = {name, atom()} | {ip, string() | tuple()} | {backlog, integer()}
%%              | {nodelay, boolean()} | {acceptor_pool_size, integer()}
%%              | {ssl, boolean()} | {profile_fun, undefined | (Props) -> ok}
%%              | {link, false}
%% @doc Start a mochiweb server.
%%      profile_fun is used to profile accept timing.
%%      After each accept, if defined, profile_fun is called with a proplist of a subset of the mochiweb_socket_server state and timing information.
%%      The proplist is as follows: [{name, Name}, {port, Port}, {active_sockets, ActiveSockets}, {timing, Timing}].
%% @end
start(Options) ->
    mochiweb_socket_server:start(parse_options(Options)).

阅读全文…

Share

Nginx配置文件解析详解

2012年4月28日 1 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: Nginx配置文件解析详解

Nginx的配置解析相关的部分比较绕,比如为何要有4重指针,比如NGX_MAIN_CONF , loc_conf,NGX_DIRECT_CONF有什么区别呢?这些我前面的blog都有些涉及,这次主要是把配置这块完全拿出来然后来分析下。

首先来看配置解析时的数据结构,这里主要是ngx_conf_t,这个结构保存了解析配置文件所需要的一些域,这个是非常重要的一个数据结构,我们详细来看这个结构:

struct ngx_conf_s {
//当前解析到的命令名
    char                 *name;
//当前命令的所有参数
    ngx_array_t          *args;

//使用的cycle
    ngx_cycle_t          *cycle;
//所使用的内存池
    ngx_pool_t           *pool;
//这个pool将会在配置解析完毕后释放。
    ngx_pool_t           *temp_pool;
//这个表示将要解析的配置文件
    ngx_conf_file_t      *conf_file;
//配置log
    ngx_log_t            *log;

//主要为了提供模块的层次化(后续会详细介绍)
    void                 *ctx;
//模块类型
    ngx_uint_t            module_type;
//命令类型
    ngx_uint_t            cmd_type;

//模块自定义的handler
    ngx_conf_handler_pt   handler;
//自定义handler的conf
    char                 *handler_conf;
};

阅读全文…

Share

hotwheels源码剖析

2012年4月8日 1 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: hotwheels源码剖析

在霸爷的推荐下,看了hotwheels的代码,接下来我就来分析下hotwheels的代码(主要是server端代码),hotwheels是干吗的呢,介绍在这里:
https://github.com/tolbrino/hotwheels

Janus is a messaging server optimized to unicast over TCP to thousands of clients subscribed to topics of interest.

The ultimate goal is to maintain a latency of less than 2 seconds for 20 thousand clients on Amazon EC2 (small instance).

首先来看janus.app:

{application, janus,
 [{description, "Janus"},
  {vsn, "0.0.1"},
  {id, "janus"},
  {modules, [barrier,
             bin,
             bot,
             client_proxy,
             common,
             flashbot,
             histo,
             janus,
             janus_acceptor,
             janus_admin,
             janus_app,
             janus_flash,
             launcher,
             mapper,
             pubsub,
             topman,
             t,
             transport,
             util
            ]},
  {registered, [janus_sup, 
                janus_topman_sup,
                janus_proxy_mapper_sup,
                janus_transport_sup,
                janus_listener]},
  {applications, [kernel, 
                  stdlib, 
                  mnesia,
                  inets
                 ]},
  {mod, {janus_app, []}},
  {env, []}
 ]
}.

阅读全文…

Share
分类: erlang, 源码阅读 标签: ,

nginx中upstream的设计和实现(一)

2011年4月8日 8 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(一)

在nginx的模块中,分为3种类型,分别是handler,filter和upstream,其中upstream可以看做一种特殊的handler,它主要用来实现和后端另外的服务器(php/jboss等)进行通信,由于在nginx中全部都是使用非阻塞,并且是一个流式的处理,所以upstream的实现很复杂,接下来我会通过几篇blog来详细的分析下nginx中upstream的设计和实现。

upstream顾名思义,真正产生内容的地方在”上游”而不是nginx,也就是说nginx是位于client和后端的upstream之间的桥梁,在这种情况下,一个upstream需要做的事情主要有2个,第一个是当client发送http请求过来之后,需要创建一个到后端upstream的请求。第二个是当后端发送数据过来之后,需要将后端upstream的数据再次发送给client.接下来会看到,我们编写一个upstream模块,最主要也是这两个hook方法。

首先来看如果我们要写一个upstream模块的话,大体的步骤是什么,我们以memcached模块为例子,我们会看到如果我们自己编写upstream模块的话,只需要编写upstream需要的一些hook函数,然后挂载到upstream上就可以了。
阅读全文…

Share
分类: nginx, server, 源码阅读 标签:

nginx的启动流程分析(二)

2011年1月21日 1 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx的启动流程分析(二)

接上篇,这篇主要来看nginx的网络部分的初始化

首先是ngx_http_optimize_servers函数,这个函数是在ngx_http_block中被调用的,它的主要功能就是创建listening结构,然后初始化。这里ngx_listening_t表示一个正在监听的句柄以及它的上下文。

static ngx_int_t
ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
    ngx_array_t *ports)
{
    ngx_uint_t             p, a;
    ngx_http_conf_port_t  *port;
    ngx_http_conf_addr_t  *addr;

    if (ports == NULL) {
        return NGX_OK;
    }

    port = ports->elts;
    for (p = 0; p < ports->nelts; p++) {
..................................................
//初始化listen结构
        if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}

阅读全文…

Share