当前位置: 首页 > news >正文

项目定制开发网站长沙市公司

项目定制开发网站,长沙市公司,嘉兴网站设计,产品开发设计文章目录 nginx运行模式与进程模式进程模式流程图默认初始化运行模式与进程模式(宏展开)cpu_affinity多CPU绑定合理性判定Nginx的daemon创建#xff08;os/unix/ngx_daemon.c#xff09;运行模式、进程模式启动 多进程模式下master处理流程设置进程信号、初始化信号掩码、屏蔽… 文章目录 nginx运行模式与进程模式进程模式流程图默认初始化运行模式与进程模式(宏展开)cpu_affinity多CPU绑定合理性判定Nginx的daemon创建os/unix/ngx_daemon.c运行模式、进程模式启动 多进程模式下master处理流程设置进程信号、初始化信号掩码、屏蔽相关信号调用ngx_start_worker_processes函数派生Worker进程创建cache进程用于缓存管理进入主循环通过sigsuspend使进程等待信号 调用ngx_start_worker_processes函数派生Worker进程ngx_pass_open_channel函数ngx_write_channel函数 讨论 nginx运行模式与进程模式 nginx有守护daemon模式与非守护非daemon模式两种模式两种模式在运行后的区别在于 守护模式nginx启动后直接回到命令提示符界面不接受任何的输入和输出其父进程为Linux的init进程启动nginx进程后会使用fork创建子进程进行后续操作启动进程会自动结束。非守护模式nginx启动后没有回到命令提示符界面当nginx有输出时会直接在终端输出其父进程为bash。 进程模式分为单进程模式和多进程模式 进程模式流程图 默认初始化运行模式与进程模式(宏展开) static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)//函数中(core/nginx.c文件中) { ………ngx_conf_init_value(ccf-daemon, 1); //守护进程daemon守护方式ngx_conf_init_value(ccf-master, 1); //多进程模式………ngx_conf_init_value(ccf-worker_processes, 1); //默认一个worker………//worker进程绑定CPU设置合理性判断用户名文件锁等初始化return NGX_CONF_OK; }//宏定义展开如下 #define NGX_CONF_UNSET -1 ……… #define ngx_conf_init_value(conf, default) \ if (conf NGX_CONF_UNSET) { \ conf default; \ } ………static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)//函数中(core/nginx.c文件中) {………//ngx_conf_init_value(ccf-daemon, 1)按宏展开;if (ccf-daemon -1) {//守护进程daemon守护方式ccf-daemon 1; }//以下ngx_conf_init_value宏类似展开………return NGX_CONF_OK; }cpu_affinity多CPU绑定合理性判定 进行绑定时必须cpu数目与worker进程数目相等否则不好绑定 #if (NGX_HAVE_CPU_AFFINITY) //支持多CPU绑定if (!ccf-cpu_affinity_auto //非自动 ccf-cpu_affinity_n //非0 ccf-cpu_affinity_n ! 1 //非1 ccf-cpu_affinity_n ! (ngx_uint_t) ccf-worker_processes) //与工作进程数相等 { //错误处理及记录} #endifNginx的daemon创建os/unix/ngx_daemon.c 创建一个子进程自己父进程关闭结束.创建新的会话设置进程的umask为0daemon模式下没有输入输出返回 //创建新的会话 ……… switch (fork()) { case -1: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, fork() failed); return NGX_ERROR; case 0: break; //子进程default: exit(0); //父进程退出结束} ………//在守护模式下没有输出nginx采用重定向的方式对输出进行重定向 ……… fd open(/dev/null, O_RDWR); if (fd -1) { //错误记录处理 return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) -1) { //错误记录处理 return NGX_ERROR; } //将标准输入重定位到fd即null设备 if (dup2(fd, STDOUT_FILENO) -1) {//错误记录处理 return NGX_ERROR; } //将标准输出重定位到fd即null设备 ………ngx_int_t ngx_daemon(ngx_log_t *log) //汇总与总结 {//定义变量//创建一个子进程自己父进程关闭结束ngx_parent ngx_pid; //ngx_pid为全局变量 ngx_pid ngx_getpid(); if (setsid() -1) { //创建新的会话 //错误处理与记录后返回} umask(0);//设置掩码为0//daemon模式下关闭标准输入与输出 }运行模式、进程模式启动 在Nginx的main函数最后一切准备就绪后根据ngx_process 值的指示判定单/多进程模式 int ngx_cdecl main(int argc, char *const *argv) {………//前期内存池等各种准备if (ngx_process NGX_PROCESS_SINGLE) { //为0 ngx_single_process_cycle(cycle); //单进程模式} else //不为0{ ngx_master_process_cycle(cycle); //多进程模式}return 0; }多进程模式下master处理流程 设置进程信号、初始化信号掩码屏蔽相关信号。调用ngx_start_worker_processes函数派生Worker进程ngx_start_cache_manager_processes函数派生cache manager进程以及cache loader进程 cache进程用于缓存管理进入主循环通过sigsuspend使进程等待信号待收到信号后进入ngx_signal_handler进行信号处理 设置进程信号、初始化信号掩码、屏蔽相关信号 //Nginx定义的几个常见信号 #define NGX_SHUTDOWN_SIGNAL QUIT //终端退出 #define NGX_TERMINATE_SIGNAL TERM //软件终止 #define NGX_NOACCEPT_SIGNAL WINCH //窗口大小改变 #define NGX_RECONFIGURE_SIGNAL HUP //终端挂起或终端控制进程结束nginx信号解析 #define ngx_signal_helper(n) SIG##n // 表示前后两个字符串合并宏 #define ngx_signal_value(n) ngx_signal_helper(n) //程序中使用的宏ngx_signal_value NGX_RECONFIGURE_SIGNAL//经过宏展开后 1. ngx_signal_value HUP 经过宏展开后 2. ngx_signal_helper HUP 再经过宏展开后 3. SIGHUP 这正是Linux的信号………//定义局部临时变量 sigemptyset(set); sigaddset(set, SIGCHLD); //Linux信号标准名字 sigaddset(set, SIGALRM); //Linux信号标准名字 sigaddset(set, SIGIO); //Linux信号标准名字 sigaddset(set, SIGINT); //Linux信号标准名字 sigaddset(set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); //Linux信号别名 sigaddset(set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, set, NULL) -1) { //若新增屏蔽搁置信号集合set 失败 //错误处理并记录 } sigemptyset(set);//清空信号集以便后面使用 ………调用ngx_start_worker_processes函数派生Worker进程 ……… ccf (ngx_core_conf_t *) ngx_get_conf(cycle-conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf-worker_processes, NGX_PROCESS_RESPAWN); ………创建cache进程用于缓存管理 ……… ngx_start_cache_manager_processes(cycle, 0); ………进入主循环通过sigsuspend使进程等待信号 ……… for(;;){………//设置时钟sigsuspend(set); ngx_time_update();//更新时钟……… }调用ngx_start_worker_processes函数派生Worker进程 多进程模式下Worker进程的作用os/unix/ ngx_process_cycle.c 读取请求、解析请求、处理请求产生结果后返回给客户最后断开连接。一个请求在一个且仅在该worker内处理完成ngx_start_worker_processes函数调用ngx_spawn_process函数派生worker进程. ngx_start_worker_processes函数的主要功能及其过程如下 局部临时变量定义。如创建一个ngx_channel_t 变量ch并将ch的command置为NGX_CMD_OPEN_CHANNEL;表示新建一个进程循环创建n个worker进程调用ngx_spawn_process创建一个worker进程设置ngx_process_slot 值为了ngx_processes数组的值同步设置好ch的其它字段的值调用ngx_pass_open_channel广播使得以前创建的进程更新ngx_processes数据重复3~5直至n个worker创建完成。 //第三个参数type #define NGX_PROCESS_NORESPAWN -1 //子进程退出父进程不重启 #define NGX_PROCESS_JUST_SPAWN -2 //区分刚建的子进程与其它子进程 #define NGX_PROCESS_RESPAWN -3//子进程退出父进程重启 #define NGX_PROCESS_JUST_RESPAWN -4//区分刚建的子进程与其它子进程子进程退出父进程重启 #define NGX_PROCESS_DETACHED -5 //新派生进程与父进程脱离关系//第二个参数n 创建worker进程的总数 static voidngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)struct ngx_cycle_s { void ****conf_ctx; //保持所有模块的配置结构体ngx_pool_t *pool; //内存池ngx_log_t *log; //日志信息ngx_log_t new_log; ngx_uint_t log_use_stderr; /* unsigned log_use_stderr:1; */ ngx_connection_t **files; //文件句柄ngx_connection_t *free_connections; //可用连接池ngx_uint_t free_connection_n;//可用连接池总数ngx_module_t **modules; //模块信息ngx_uint_t modules_n; ngx_uint_t modules_used; /* unsigned modules_used:1; */ ngx_queue_t reusable_connections_queue; //再利用连接队列ngx_uint_t reusable_connections_n; //再利用连接数ngx_array_t listening; //被监听端口ngx_array_t paths; //操作目录ngx_array_t config_dump; ngx_rbtree_t config_dump_rbtree; ngx_rbtree_node_t config_dump_sentinel; ngx_list_t open_files; //打开文件ngx_list_t shared_memory; //共享文件ngx_uint_t connection_n; //当前进程中所有连接对象的总数ngx_uint_t files_n;//代开文件个数ngx_connection_t *connections; //指向当前进程中的所有连接对象 ngx_event_t *read_events; //读事件ngx_event_t *write_events; //写事件ngx_cycle_t *old_cycle; //old cycle指针ngx_str_t conf_file; //配置文件ngx_str_t conf_param; //配置参数ngx_str_t conf_prefix; //配置前缀ngx_str_t prefix; //前缀ngx_str_t lock_file; //用于进程间同步的文件锁ngx_str_t hostname;//主机名 };ngx_channel_t结构体 //ngx_channel_t 的command #define NGX_CMD_OPEN_CHANNEL 1 //新建 #define NGX_CMD_CLOSE_CHANNEL 2 //关闭 #define NGX_CMD_QUIT 3 //退出 #define NGX_CMD_TERMINATE 4 //终止 #define NGX_CMD_REOPEN 5 //重新打开重启 typedef struct { ngx_uint_t command; //命令ngx_pid_t pid; //进程号ngx_int_t slot; // ngx_processes 数组中worker进程下标ngx_fd_t fd;//保存用于socketpair全双工的socket } ngx_channel_t;ngx_processes数组 作用有以下几个方面 1保存创建进程的有关信息 2便于worker进程间通信 3便于worker进程与master进程间通信 ngx_process_t ngx_processes[NGX_MAX_PROCESSES];typedef struct { ngx_pid_t pid; //worker进程的PIDint status; //状态ngx_socket_t channel[2]; //worker与master之间通信的socketpair ngx_spawn_proc_pt proc; //回调函数void *data; // proc回调函数的参数char *name; //worker子进程的名字unsigned respawn:1; //是否重启unsigned just_spawn:1; //是否刚创建unsigned detached:1; //是否脱离unsigned exiting:1; unsigned exited:1; } ngx_process_t;static voidngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type){ ………// 创建并初始化ngx_channel_t结构体类型ch; ngx_channel_t ch; ch.command NGX_CMD_OPEN_CHANNEL; for (i 0; i n; i) { //依次创建n个worker进程ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, worker process, type);//调用 ngx_spawn_process函数创建worker进程其信息ngx_processes数组ngx_process_slot 元素的中; ch.pid ngx_processes[ngx_process_slot].pid; ch.slot ngx_process_slot; ch.fd ngx_processes[ngx_process_slot].channel[0]; //刚创建进程的写端给其它进程便于后续通信ngx_pass_open_channel(cycle, ch); //调用ngx_pass_open_channel广播这是有linux的进程机制决定的fork时父子进程会共享内存当进程对内存内容进行修改时内核会复制一份数据到另一片内存时这时前后的内容会不一致所以才需要广播 } }ngx_spawn_process函数 在ngx_processes数组中找到一个保存worker进程信息的元素下标s①如果respawn大于0 respawn就是s②如果不大于0从ngx_processes数组中找到其元素的pid成员为-1的空闲元素该元素就是的数组下标就是s但该s不能超过最大worker范围。 if (respawn 0) { s respawn; // ①} else { // ②遍历ngx_processes数组确定sfor (s 0; s ngx_last_process; s) { if (ngx_processes[s].pid -1) { break; } } if (s NGX_MAX_PROCESSES) { //最大为1024 //超过最大worker数限制错误处理并记录return NGX_INVALID_PID; } }如果respawn不是NGX_PROCESS_DETACHED即派生子进程与父进程不是非脱离关系①创建通信socketpair ②以非阻塞方式设置读写端 ③将写端设置为异步写 ④并将写端的SIGIO以及SIGURG信号的属主设为父进程 ⑤设置Master、worker进程执行exec()函数后关闭socket。 ①创建通信socketpairif (respawn ! NGX_PROCESS_DETACHED) {//2如果非关系成立if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) -1) // ①{//错误处理并记录return NGX_INVALID_PID; }②以非阻塞方式设置读写端if (ngx_nonblocking(ngx_processes[s].channel[0]) -1) { //设置写端 //错误处理并记录return NGX_INVALID_PID; }③将写端设置为异步写on 1; if (ioctl(ngx_processes[s].channel[0], FIOASYNC, on) -1) { // ③ // 错误处理并记录return NGX_INVALID_PID; }④并将写端的SIGIO以及SIGURG信号的属主设为ngx_pid父进程if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) -1) { // ④ // 错误处理并记录return NGX_INVALID_PID; }⑤设置Master、worker进程执行exec()函数后关闭socket。 if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) -1) { // ⑤ // 错误处理并记录return NGX_INVALID_PID; }//以下设置当前子进程的socketMaster进程用于监听 ngx_channel ngx_processes[s].channel[1];//给全局变量ngx_channel 赋值 }如果respawn是NGX_PROCESS_DETACHED设置该worker的通信通道都为-1; else//是2的if的else分支否则则是NGX_PROCESS_DETACHED脱离关系{ ngx_processes[s].channel[0] -1; //创建的是master通信pair置为-1 ngx_processes[s].channel[1] -1; }fork派生worker进程 //为ngx_start_worker_processes函数记下ngx_process_slot 值ngx_process_slot s; //ngx_process_slots是全部变量pid fork(); //派生子进程worker子进程执行回调proc switch (pid) { case -1: 错误处理并记录return NGX_INVALID_PID; case 0: //5子进程执行回调函数procngx_parent ngx_pid; ngx_pid ngx_getpid(); proc(cycle, data); break; default: break; //父进程往后执行}父进程填充worker子进程的信息到ngx_processes数组s元素中 ngx_processes[s].pid pid; //ngx_processes[s].exited 0; f (respawn 0) { //如果是重启子进程返回return pid; }ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, worker process, type);1.第一个参数 cycle ngx_start_worker_processes函数 2.第二个参数回调函数ngx_worker_process_cycle该函数在os/unix/ ngx_process_cycle.c中定义 3.第三个参数i即第几个worker 4.第四个参数worker进程名字 5.第五个参数类型来自ngx_start_worker_processes函数的形参ngx_pass_open_channel函数 遍历ngx_processes数组广播对每个worker子进程发送信息。 static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) 对每个非刚创建、不存在进程以及父进程socket关闭的子进程调用ngx_write_channel发送消息内容 typedef struct { ngx_uint_t command; //命令见下页ngx_pid_t pid; //进程号ngx_int_t slot; // ngx_processes 数组中worker进程下标ngx_fd_t fd;//保存用于socketpair全双工的socket } ngx_channel_t;static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) {for (i 0; i ngx_last_process; i) { //过滤刚建的子进程、不存在的子进程以及关闭socket的子进程if (i ngx_process_slot || //刚刚创建的ngx_processes[i].pid -1 || //没有进程数据的数组元素ngx_processes[i].channel[0] -1) //无法通信了{ continue; } .......... //给每个子进程的父进程发送刚建进程的worker信息ngx_write_channel(ngx_processes[i].channel[0], ch, sizeof(ngx_channel_t), cycle-log); } }ngx_write_channel函数 构造struct msghdr 类型msg//Linux系统层次接口调用sendmsg发送msg//Linux系统层次接口 ngx_int_tngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log) {ssize_t n; //声明所需变量ngx_err_t err; struct iovec iov[1]; struct msghdr msg; ……iov[0].iov_base (char *) ch; //构造msgiov[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);//发送msgLinux编程接口……//错误处理等return NGX_OK; }讨论 为什么nginx使用的是进程不是线程 是因为 Nginx 要保证高可用性多线程之间会共享地址空间当某一个第三方模块引发了一个段错误时就会导致整个 Nginx 进程挂掉。而采用多进程模型不会出现这个问题
http://www.dnsts.com.cn/news/46852.html

相关文章:

  • 浙江省嘉兴建设局官方网站wordpress search标签页
  • 中国做乱的小说网站中国建设银行保函查询网站
  • 制作网站的主题景安网站
  • 做怎样的企业网站php源代码做网站
  • 在中国备案的网站服务器免费做代理的网站
  • 云南企业建站济宁网站建设有限公司
  • 重庆装修房子可以提取公积金吗莆田seo培训
  • 网站介绍怎么写安阳那里可以制作网站
  • 怎样在国外网站做推广深圳公司排名前50
  • 外国网站接单做翻译网络营销作业
  • seo整站优化一年价格多少网站群发软文软件
  • 企业网站托管外包方案wordpress排版教程
  • 国家电网网站开发图片素材wordpress云采集
  • 查销售数据的网站域名最新通知
  • 女的和男做那个视频网站个人网站免费搭建
  • 揭阳网站制作工具做电子商务网站 费用
  • 安徽区块链虚拟币网站开发方案服装设计自学软件
  • 做ppt常用的网站有哪些南通装饰网站建设
  • 同城可以做别人一样的门户网站吗北京市建设工程安全质量监督总站网站
  • 阳江新农村建设网站上海福州路附近做网站的公司
  • 网站策划与设计做网站App价格多少
  • 金华建站软件临沂市建设局的网站
  • 做二手车网站需要什么安顺市建设局网站
  • 网站开发asp 视频深圳专业做网站设计
  • 做婚恋网站要多少钱网站上搜索的动图怎么做壁纸
  • 网站上传好了如何做定向宁波网页设计多少钱
  • 学做电商的网站网站销售需要注册公司吗
  • 网站怎么做qq微信登陆网站建设动图代码
  • 养殖企业网站模板免费浏览器加速器
  • 装修企业网站源码商标查询入口