日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Nginx >内容正文

Nginx

Nginx学习笔记(七) 创建子进程

發(fā)布時(shí)間:2023/12/31 Nginx 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx学习笔记(七) 创建子进程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Nginx創(chuàng)建子進(jìn)程

  ngx_start_worker_processes位于Nginx_process_cycle.c中,主要的工作是創(chuàng)建子進(jìn)程。

  在Nginx中,master進(jìn)程和worker進(jìn)程是通過(guò)socketpair函數(shù)創(chuàng)建一對(duì)socket來(lái)實(shí)現(xiàn),父進(jìn)程與子進(jìn)程之間的通信的。而這對(duì)socket被保存在進(jìn)程結(jié)構(gòu)體ngx_process中的channel[2]數(shù)組中,其中channel[0]為父進(jìn)程的socket,channel[1]為子進(jìn)程的socket。

static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) {ngx_int_t i;ngx_channel_t ch;ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");//傳遞給其他進(jìn)程的命令ch.command = NGX_CMD_OPEN_CHANNEL;for (i = 0; i < n; i++) {//創(chuàng)建n個(gè)子進(jìn)程ngx_spawn_process(cycle, ngx_worker_process_cycle,(void *) (intptr_t) i, "worker process", type);//保存當(dāng)前worker進(jìn)程的信息ch.pid = ngx_processes[ngx_process_slot].pid;ch.slot = ngx_process_slot; //ngx_process_slot是進(jìn)程信息在全局進(jìn)程數(shù)組中存放的下標(biāo)ch.fd = ngx_processes[ngx_process_slot].channel[0];//channel[0]為父進(jìn)程的socket,channel[1]為子進(jìn)程的socket//向每一個(gè)進(jìn)程的父進(jìn)程發(fā)送本進(jìn)程的信息ngx_pass_open_channel(cycle, &ch);}

  具體分析一下創(chuàng)建子進(jìn)程的函數(shù),也就是分析ngs_spawn_process:

ngx_pid_tngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,char *name, ngx_int_t respawn){u_long on;ngx_pid_t pid;ngx_int_t s; //可創(chuàng)建進(jìn)程的位置if (respawn >= 0) {s = respawn; //如果類型大于0,表示該進(jìn)程已經(jīng)退出,可以重啟該進(jìn)程} else {for (s = 0; s < ngx_last_process; s++) { //遍歷所有進(jìn)程,找到可用的已退出的進(jìn)程if (ngx_processes[s].pid == -1) { break;}}//超過(guò)最大進(jìn)程限制會(huì)報(bào)錯(cuò)if (s == NGX_MAX_PROCESSES) {ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,"no more than %d processes can be spawned",NGX_MAX_PROCESSES);return NGX_INVALID_PID;}}if (respawn != NGX_PROCESS_DETACHED) {/* Solaris 9 still has no AF_LOCAL *///創(chuàng)建socketpair用于進(jìn)程間通信,master進(jìn)程為每個(gè)worker創(chuàng)建一對(duì)socketif (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1){ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"socketpair() failed while spawning \"%s\"", name);return NGX_INVALID_PID;}ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,"channel %d:%d",ngx_processes[s].channel[0],ngx_processes[s].channel[1]);//設(shè)置非阻塞模式if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,ngx_nonblocking_n " failed while spawning \"%s\"",name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,ngx_nonblocking_n " failed while spawning \"%s\"",name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}//設(shè)置異步模式on = 1;if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { //FIOASYNC異步輸入/輸出標(biāo)志ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"ioctl(FIOASYNC) failed while spawning \"%s\"", name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {//F_SETOWN設(shè)置異步I/O的所有者ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"fcntl(F_SETOWN) failed while spawning \"%s\"", name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}//若進(jìn)程執(zhí)行了exec后,關(guān)閉socketif (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;}ngx_channel = ngx_processes[s].channel[1];} else {ngx_processes[s].channel[0] = -1;ngx_processes[s].channel[1] = -1;}ngx_process_slot = s; //創(chuàng)建子進(jìn)程pid = fork();switch (pid) {case -1:ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,"fork() failed while spawning \"%s\"", name);ngx_close_channel(ngx_processes[s].channel, cycle->log);return NGX_INVALID_PID;case 0:ngx_pid = ngx_getpid();proc(cycle, data); //調(diào)用ngx_worker_process_cycle()子進(jìn)程循環(huán)處理事件break;default:break;}ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);ngx_processes[s].pid = pid;ngx_processes[s].exited = 0;//大于0,說(shuō)明確定重啟該進(jìn)程if (respawn >= 0) {return pid;}//設(shè)置進(jìn)程信息ngx_processes[s].proc = proc;ngx_processes[s].data = data;ngx_processes[s].name = name;ngx_processes[s].exiting = 0;//設(shè)置狀態(tài)信息switch (respawn) {case NGX_PROCESS_NORESPAWN:ngx_processes[s].respawn = 0;ngx_processes[s].just_spawn = 0;ngx_processes[s].detached = 0;break;case NGX_PROCESS_JUST_SPAWN:ngx_processes[s].respawn = 0;ngx_processes[s].just_spawn = 1;ngx_processes[s].detached = 0;break;case NGX_PROCESS_RESPAWN:ngx_processes[s].respawn = 1;ngx_processes[s].just_spawn = 0;ngx_processes[s].detached = 0;break;case NGX_PROCESS_JUST_RESPAWN:ngx_processes[s].respawn = 1;ngx_processes[s].just_spawn = 1;ngx_processes[s].detached = 0;break;case NGX_PROCESS_DETACHED:ngx_processes[s].respawn = 0;ngx_processes[s].just_spawn = 0;ngx_processes[s].detached = 1;break;}if (s == ngx_last_process) {ngx_last_process++;}return pid;}

  接下來(lái),看看Nginx是如何在進(jìn)程間進(jìn)行通信的,ngx_pass_open_channel函數(shù):

static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) {ngx_int_t i;//遍歷所有進(jìn)程for (i = 0; i < ngx_last_process; i++) {//跳過(guò)本進(jìn)程和退出/不能通信的進(jìn)程if (i == ngx_process_slot || ngx_processes[i].pid == -1|| ngx_processes[i].channel[0] == -1){continue;}ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,"pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",ch->slot, ch->pid, ch->fd,i, ngx_processes[i].pid,ngx_processes[i].channel[0]);/* TODO: NGX_AGAIN *///把本進(jìn)程的信息發(fā)送給每一個(gè)進(jìn)程的父進(jìn)程ngx_write_channel(ngx_processes[i].channel[0],ch, sizeof(ngx_channel_t), cycle->log);} }

?  ngx_write_channel原型:

ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, //ch內(nèi)儲(chǔ)存著本進(jìn)程的信息,s是父進(jìn)程的socket值(channel[0])ngx_log_t *log) {ssize_t n;ngx_err_t err;struct iovec iov[1];struct msghdr msg;#if (NGX_HAVE_MSGHDR_MSG_CONTROL)union {struct cmsghdr cm;char space[CMSG_SPACE(sizeof(int))];} cmsg;if (ch->fd == -1) {msg.msg_control = NULL;msg.msg_controllen = 0;} else {msg.msg_control = (caddr_t) &cmsg;msg.msg_controllen = sizeof(cmsg);cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));cmsg.cm.cmsg_level = SOL_SOCKET;cmsg.cm.cmsg_type = SCM_RIGHTS;/** We have to use ngx_memcpy() instead of simple* *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;* because some gcc 4.4 with -O2/3/s optimization issues the warning:* dereferencing type-punned pointer will break strict-aliasing rules** Fortunately, gcc with -O1 compiles this ngx_memcpy()* in the same simple assignment as in the code above*/ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));}msg.msg_flags = 0;#elseif (ch->fd == -1) {msg.msg_accrights = NULL;msg.msg_accrightslen = 0;} else {msg.msg_accrights = (caddr_t) &ch->fd;msg.msg_accrightslen = sizeof(int);}#endifiov[0].iov_base = (char *) ch;iov[0].iov_len = size;msg.msg_name = NULL;msg.msg_namelen = 0;msg.msg_iov = iov;msg.msg_iovlen = 1;n = sendmsg(s, &msg, 0);//sendmsg函數(shù),在這里用于進(jìn)程間通信if (n == -1) {err = ngx_errno;if (err == NGX_EAGAIN) {return NGX_AGAIN;}ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");return NGX_ERROR;}return NGX_OK; }

?

轉(zhuǎn)載于:https://www.cnblogs.com/coder2012/p/3188355.html

總結(jié)

以上是生活随笔為你收集整理的Nginx学习笔记(七) 创建子进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 女人扒开腿让男人捅爽 | 精品一二三四区 | 围产精品久久久久久久 | 嫩草伊人久久精品少妇av | 一级黄色影院 | 直接看毛片 | 国产激情综合五月久久 | 久av在线 | 成人在线免费播放视频 | av在线片| 国产中文欧美日韩在线 | 日韩欧美国产高清91 | 黄色网址你懂的 | 精品人妻一区二区三区三区四区 | 亚洲一区二区三区影院 | 狠狠干天天色 | 国产精品一二区在线观看 | 老鸭窝久久 | 久久久久国产精品夜夜夜夜夜 | 神马午夜嘿嘿 | 中文字幕无码乱码人妻日韩精品 | youjizz韩国| 亚洲最大av网站 | 久草中文在线 | 又欲又污又肉又黄短文 | 久久精品免费电影 | 亚洲天堂激情 | 亚洲综合专区 | 女同互舔视频 | www.第四色| 爱情岛论坛自拍亚洲品质极速最新章 | 久久久久久一区二区三区 | 91好色先生| 久久黄网站 | 毛片看看 | 樱桃视频一区二区三区 | 蜜臀av性久久久久蜜臀aⅴ四虎 | www.亚洲人 | 夜色福利视频 | 亚洲国产精一区二区三区性色 | 在线免费观看一区 | 久久久久久久久久久91 | 欧美日韩在线不卡 | 91精品国产乱码 | 亚洲色图19p | 国产又粗又硬 | 亚洲视频免费在线播放 | 中文字幕亚洲乱码熟女1区2区 | 久久精品国产免费看久久精品 | 免费毛片在线播放免费 | 久色综 | 深夜视频在线免费观看 | 欧美一级二级在线观看 | 国产亚洲在线观看 | av小次郎收藏 | 天天看天天射 | 又黄又爽视频在线观看 | 国产成人无码精品久久久性色 | 激情婷婷六月 | 黄色大片黄色大片 | 久久免费观看视频 | 精品国产乱码久久久久久鸭王1 | h色视频在线观看 | 国产欧美一区二区在线观看 | 欧美日韩高清一区二区 国产亚洲免费看 | 国产一区二区三区乱码 | 久久久午夜精品 | 久久99热这里只有精品 | 欧美成人tv | 亚洲黄色中文字幕 | 国产视频二区三区 | 国产哺乳奶水91在线播放 | 久久久亚洲一区二区三区 | 成年人久久 | 日韩av电影在线播放 | 浮妇高潮喷白浆视频 | 精品综合久久久久 | 激情久久网 | 亚洲一区第一页 | va婷婷 | 国产美女被草 | 奇米色婷婷 | 网爆门在线 | 视频1区2区| 成人精品水蜜桃 | 在线国产不卡 | 中文一区二区 | 久久深夜 | 高潮无码精品色欲av午夜福利 | 国产一精品一aⅴ一免费 | 二区视频在线 | 久久综合热 | 国产午夜精品久久久久久久 | 免费99视频| 伊人免费| 欧美一级性视频 | 香蕉久久夜色精品国产使用方法 | 亚洲一线二线在线观看 | 免费黄色一级片 |