版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/81229261
接着上面server的start过程,我们继续分析factory对象的start过程,这里按不同模式,factory的start过程也是不一样的,我们分别进行分析,首先分析单进程单线程模式的factory的start,其定义在E:\swoole-src-master\src\factory\Factory.c文件中,定义如下:
int swFactory_start(swFactory *factory)
{
//标记全局变量SwooleWG的run_always属性为1,也就是一直运行。
SwooleWG.run_always = 1;
return SW_OK;
}
接下来我们分析多进程模式的factory的start过程,其定义在E:\swoole-src-master\src\factory\FactoryProcess.c文件中。
static int swFactoryProcess_start(swFactory *factory)
{
int i;
swServer *serv = factory->ptr;//获取server对象
swWorker *worker;
//循环创建worker,这里worker分event worker,task worker,user worker,task和user这两种是目前PHP侧可以控制的,而event worker用于外部提供event事件给reactor做管理的,后续再分析。
for (i = 0; i < serv->worker_num; i++)
{
worker = swServer_get_worker(serv, i);//获取worker对象
if (swWorker_create(worker) < 0)//创建worker的发送buffer,这里通过共享内存的方式创建,如果创建失败,则退出。
{
return SW_ERR;
}
}
//设置reactor_pipe_num属性值,这个值是通过work_num和reactor_num来计算的,即表示一个reactor管理多少个worker。
serv->reactor_pipe_num = serv->worker_num / serv->reactor_num;
//在多进程模式下,除了master进程,还有manger和worker进程,这里是启动manager进程和worker进程,详情后面展开分析
if (swManager_start(factory) < 0)
{
swWarn("swFactoryProcess_manager_start failed.");
return SW_ERR;
}
//设置factory的finish回调函数
factory->finish = swFactory_finish;
return SW_OK;
}
static sw_inline swWorker* swServer_get_worker(swServer *serv, uint16_t worker_id)
{
//外部提供的event worker,这里通过worker_id来区分想要的worker类型,如果worker_id小于worker_num,则worker的获取是从serv->gs->event_workers.workers[worker_id]处获取。
if (worker_id < serv->worker_num)
{
return &(serv->gs->event_workers.workers[worker_id]);
}
//task类型的worker,如果worker_id大于worker_num,且小于task_worker_max,则获取task类型的worker,即从serv->gs->task_workers.workers[worker_id - serv->worker_num]处获取。
uint16_t task_worker_max = serv->task_worker_num + serv->worker_num;
if (worker_id < task_worker_max)
{
return &(serv->gs->task_workers.workers[worker_id - serv->worker_num]);
}
//用户类型的worker,如果worker_id大于task_worker_max,且小于user_worker_max,则获取用户类型的worker,即从serv->user_workers[worker_id - task_worker_max]处获取。
uint16_t user_worker_max = task_worker_max + serv->user_worker_num;
if (worker_id < user_worker_max)
{
return &(serv->user_workers[worker_id - task_worker_max]);
}
return NULL;
}
int swManager_start(swFactory *factory)
{
swFactoryProcess *object = factory->object;//获取FactoryProcess对象
int i;
pid_t pid;
swServer *serv = factory->ptr;//获取server对象
//初始化FactoryProcess对象的Pipe管道信息
object->pipes = sw_calloc(serv->worker_num, sizeof(swPipe));
if (object->pipes == NULL)//申请空间失败
{
swError("malloc[worker_pipes] failed. Error: %s [%d]", strerror(errno), errno);
return SW_ERR;
}
//worker进程对象的pipe初始化
for (i = 0; i < serv->worker_num; i++)
{
//创建全双工的socketpair管道,用于woker进程间通信
if (swPipeUnsock_create(&object->pipes[i], 1, SOCK_DGRAM) < 0)
{
return SW_ERR;
}
serv->workers[i].pipe_master = object->pipes[i].getFd(&object->pipes[i], SW_PIPE_MASTER);//设置第i个swWorker对象的pipe_master属性,这个文件描述符记录的是管道描述符的文件ID
serv->workers[i].pipe_worker = object->pipes[i].getFd(&object->pipes[i], SW_PIPE_WORKER);//设置第i个swWorker对象的pipe_worker属性,这个属性记录的是管道描述符文件ID
serv->workers[i].pipe_object = &object->pipes[i];//设置worker对象的pipe_object属性
//设置server对象connection_list的最小文件描述符ID,这个最小ID是存放在connection_list[1].fd中。
swServer_store_pipe_fd(serv, serv->workers[i].pipe_object);
}
//task对象的初始化
if (serv->task_worker_num > 0)
{
if (swServer_create_task_worker(serv) < 0)
{
return SW_ERR;
}
swProcessPool *pool = &serv->gs->task_workers;
swTaskWorker_init(pool);
swWorker *worker;
for (i = 0; i < serv->task_worker_num; i++)
{
worker = &pool->workers[i];
if (swWorker_create(worker) < 0)
{
return SW_ERR;
}
if (serv->task_ipc_mode == SW_TASK_IPC_UNIXSOCK)
{
swServer_store_pipe_fd(SwooleG.serv, worker->pipe_object);
}
}
}
//用户worker对象的初始化,用户worker是有绑定PHP侧的回调函数的worker的抽象
if (serv->user_worker_num > 0)
{
serv->user_workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, serv->user_worker_num * sizeof(swWorker));
if (serv->user_workers == NULL)
{
swoole_error_log(SW_LOG_ERROR, SW_ERROR_SYSTEM_CALL_FAIL, "gmalloc[server->user_workers] failed.");
return SW_ERR;
}
swUserWorker_node *user_worker;
i = 0;
LL_FOREACH(serv->user_worker_list, user_worker)
{
memcpy(&serv->user_workers[i], user_worker->worker, sizeof(swWorker));
if (swWorker_create(&serv->user_workers[i]) < 0)
{
return SW_ERR;
}
i++;
}
}
//设置serv的message_box属性,这里通过共享内存创建
serv->message_box = swChannel_new(65536, sizeof(swWorkerStopMessage), SW_CHAN_LOCK | SW_CHAN_SHM);
if (serv->message_box == NULL)//创建失败
{
return SW_ERR;
}
pid = fork();//执行fork操作,则当前进程,也就是master为父进程,而fork后的进程为子进程
switch (pid)
{
//子进程,也就是manager进程的逻辑
case 0:
SW_START_SLEEP;//等待父进程处理完
if (serv->gs->start == 0)//这里判断swServer是否已经启动,如果未启动属于异常情况,这里只是退出。
{
return SW_OK;
}
//fork后,父进程创建的listen描述符在子进程也存在,这里关闭子进程的listen描述符
swServer_close_listen_port(serv);
//如果有task_worker_num属性,则创建task worker
if (serv->task_worker_num > 0)
{
//启动task worker
swProcessPool_start(&serv->gs->task_workers);
}
//创建worker进程
for (i = 0; i < serv->worker_num; i++)
{
//执行实际的worker进程创建流程
pid = swManager_spawn_worker(factory, i);
if (pid < 0)//创建失败
{
swError("fork() failed.");
return SW_ERR;
}
else//创建成功
{
serv->workers[i].pid = pid;//第i个worker保存自己的PID值
}
}
//创建用户侧的worker对象
if (serv->user_worker_list)
{
swUserWorker_node *user_worker;
LL_FOREACH(serv->user_worker_list, user_worker)//遍历所有的user_worker对象
{
if (user_worker->worker->pipe_object)
{
swServer_store_pipe_fd(serv, user_worker->worker->pipe_object);
}
//创建新进程,调用PHP侧的onUserWorkerStart回调函数,这里循环调用的原因是有多个worker进程,每个进程都需要回调onUserWorkerStart函数。
swManager_spawn_user_worker(serv, user_worker->worker);
}
}
SwooleG.process_type = SW_PROCESS_MANAGER;//设置属性
SwooleG.pid = getpid();//设置全局对象SwoolG的pid属性
exit(swManager_loop(factory));
break;
default://master进程的执行逻辑
serv->gs->manager_pid = pid;//master进程负责设置全局变量manager_pid属性,也就是manager进程的进程编号
break;
case -1://fork失败
swError("fork() failed.");
return SW_ERR;
}
return SW_OK;
}