2019-04-05 Nginx

在 Github 上找了个现成的 VS 项目,直接就编起来了。运行时,因为 conf 的缺失,解决了一下。
打断点的时候,遇到了些问题,比如一开始断点是有效的,但访问一个页面的时候,比如访问一个不存在的页面(404)时,应该是要执行一个代码的,但断点一直没打上。后来猜想是 Process 的问题,并且似乎停止调试的时候,并没有真正停止运行。
利用在 Linux 上的经验,找了个 command 来找 bind 了一个端口的程序:
Get-Process -Id (Get-NetTCPConnection -LocalPort 8080).OwningProcess
然后找了个 kill process 的命令:
taskkill /PID 13488 /F

然后再解决调试的问题,在 visual studio 里 attach 一下就好了。

入口

调试环境 OK 后,找了一个 use case 作为切入点,来看基本运行的堆栈。
use case 就是在代码里搜 404,然后打个断点。然后访问一个不存在的页面。
发现 worker thread 的入口是 ngx_worker_thread。

// ngx_process_cycle.c
static ngx_thread_value_t __stdcall ngx_worker_thread(void *data);

继续看之前,先看看 __stdcall 是啥意思。搜了下,没看懂。
跟踪了一下,这个是怎么起来的:

// nginx.c
int ngx_cdecl main(int argc, char *const *argv) {
  // end of the function
  ngx_master_process_cycle(cycle);
}

// ngx_process_cycle.c
void ngx_master_process_cycle(ngx_cycle_t *cycle) {
  // some setup code

  // use ngx_process to check if the current process is a worker or not. 
  if (ngx_process == NGX_PROCESS_WORKER) {
    // this is the place to start ngx_worker_thread 
    ngx_worker_process_cycle(cycle, ngx_master_process_event_name); 
 
  // more setup

  // create an event. It is used for communication between worker
  ngx_master_process_event = CreateEvent(NULL, 1, 0, ngx_master_process_event_name); 

  // Setup other events
  // Setup a mutex for cache manager

  // It seems that it is the places to start the other processes. 
  if (ngx_start_worker_processes(cycle, NGX_PROCESS_RESPAWN) == 0) {
    exit(2); 
  }

  // handle processes logic
  for ( ; ; ) {
    // an inifinite loop
  }
}

// mevn is the event name
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn) {
  // setup some internal events

  // Open Event with mevn
  mev = OpenEvent(EVENT_MODIFY_STATE, 0, mevn);
  SetEvent(mev); 

  // Get the mutex. The mutex is created by the main process. Use name to get for the current process. 
  ngx_cache_manager_mutex = OpenMutex(SYNCHRONIZE, 0, ngx_cache_manager_mutex_name);
}

  ngx_cache_manager_event = CreateEvent(NULL, 1, 0, NULL);

  // Create 3 threads for different purposes
  if (ngx_create_thread(&wtid, ngx_worker_thread, NULL, log) != 0) goto failed;
  if (ngx_create_thread(&cmtid, ngx_cache_manager_thread, NULL, log) != 0)  goto failed;
  if (ngx_create_thread(&cltid, ngx_cache_loader_thread, NULL, log) != 0) goto failed;

 



发现到处都是 ngx_time_update() 的调用。似乎是一个时间缓存的机制,见:https://blog.csdn.net/fengmo_q/article/details/6302354

后来找到一篇很好的源码分析博客。基本看完,IOCP 的部分跳过了,准备先看看 IOCP 的基础先。
https://www.twblogs.net/a/5b87b6962b71775d1cd8a35a

一些小知识点,Windows 里有个 API 叫 SetEnvironmentVariable. 这里的环境变量是针对 Process 的,而不是系统的。另外,由这个 Process 创建的子进程也会继承这个环境变量。一个子进程启动的时候,也是从 main 开始执行的(参数可以由主进程决定)。所以可以利用这个环境变量来判断当前进程是否子进程,执行不同的行为。

这样看下来,还是很有收获的。主要是关于在 C 里,怎么写多进程,多线程代码:

  • 需要有全局变量,并且在程序启动时,做好初始化,程序结束前,都一直有效。这样对这个上下文的访问本身就是安全的。
  • 全局变量 (nginx 里的 cycle) 是一个 struct。变量本身会被多个线程访问,但都是只读,真正操作的是变量里的 member。member 有两种保证安全的方式:
    • 可以由主线程来写,但必须在读线程访问前初始化好,之后不再改变。跟全局变量本身的初始化类似。
    • 只有一个线程读写。
  • C 没有闭包,没有 event loop,没有 OOP,所以线程模型跟之前的认知是不一样的:
    • 在之前的模型里,我们倾向于 class 优先于线程。意思是,尽量将线程这个概念做到透明,每个模块管理自己的线程,让自己大部分逻辑跑在自己管理的线程当中。在对外的接口实现中,做到线程安全。这样的设计会让接口变成异步。
    • 在 Nginx 中,线程模型是比较严谨地设计的。在 worker 进程起来的时候,就把主要的线程初始化好,生命周期也是阻塞式控制的。线程的 main body 里会轮询在这个线程中操作的 manager 的函数。所以这种模型,更像是线程持有 class。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容

  • 看完这本书已经有段时间了,但是还是想写点什么东西,至少是可以平静一下这可烦躁的心。 《解忧杂货店》是我所看的第一本...
    苏阿柒阅读 366评论 0 0
  • 四季里,我最不喜欢春天,尤其不喜欢春天的天气。南方的春天,天气多变,翻脸比翻书还快,是出了名的。前一刻天朗气清,脾...
    夕月摇篮阅读 217评论 0 0
  • 生活是一面镜子,你对生活笑,它便对你笑! 微笑执着每一天!
    二年级锦妈阅读 173评论 0 0
  • 在具体业务中,会遇到需要批量插入和修改数据库的情况.我们需要实现的是: 该条数据不存在,进行插入操作 该条数据存在...
    sea_biscute阅读 26,749评论 8 9