static PHP_METHOD(swoole_process, __construct) { zend_bool redirect_stdin_and_stdout = 0; zend_bool create_pipe = 1; zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bb", &callback, &redirect_stdin_and_stdout, &create_pipe) == FAILURE) { RETURN_FALSE; } char *func_name = NULL; if (!zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); swWorker *process = emalloc(sizeof(swWorker)); bzero(process, sizeof(swWorker)); process->id = php_swoole_worker_round_id++; if (php_swoole_worker_round_id == 0) { php_swoole_worker_round_id = 1; } if (redirect_stdin_and_stdout) { process->redirect_stdin = 1; process->redirect_stdout = 1; create_pipe = 1; } if (create_pipe) { swPipe *_pipe = emalloc(sizeof(swWorker)); if (swPipeUnsock_create(_pipe, 1, SOCK_STREAM) < 0) { RETURN_FALSE; } process->pipe_object = _pipe; process->pipe_master = _pipe->getFd(_pipe, SW_PIPE_MASTER); process->pipe_worker = _pipe->getFd(_pipe, SW_PIPE_WORKER); process->pipe = process->pipe_master; zend_update_property_long(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("pipe"), process->pipe_master TSRMLS_CC); } swoole_set_object(getThis(), process); zend_update_property(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("callback"), callback TSRMLS_CC); }
/** * Process manager */ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key) { bzero(pool, sizeof(swProcessPool)); pool->workers = sw_calloc(worker_num, sizeof(swWorker)); pool->worker_num = worker_num; pool->max_request = max_request; if (pool->workers == NULL) { swWarn("malloc[1] failed."); return SW_ERR; } pool->pipes = sw_calloc(worker_num, sizeof(swPipe)); if (pool->pipes == NULL) { swWarn("malloc[2] failed."); sw_free(pool->workers); return SW_ERR; } int i; if (msgqueue_key > 0) { if (swQueueMsg_create(&pool->queue, 1, msgqueue_key, 1) < 0) { return SW_ERR; } pool->use_msgqueue = 1; pool->msgqueue_key = msgqueue_key; } else { swPipe *pipe; for (i = 0; i < worker_num; i++) { pipe = &pool->pipes[i]; if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0) { return SW_ERR; } swProcessPool_worker(pool, i).pipe_master = pipe->getFd(pipe, 1); swProcessPool_worker(pool, i).pipe_worker = pipe->getFd(pipe, 0); } } for (i = 0; i < worker_num; i++) { swProcessPool_worker(pool, i).id = i; swProcessPool_worker(pool, i).pool = pool; } pool->main_loop = swProcessPool_worker_start; return SW_OK; }
int swProcessPool_add_worker(swProcessPool *ma, swWorkerCall cb) { swPipe pipe; if (ma->worker_num >= ma->max_num) { swWarn("[swProcessPool_create] too many worker[max_num=%d]", ma->max_num); return SW_ERR; } int cur_id = ma->worker_num++; swProcessPool_worker(ma, cur_id).call = cb; if (swPipeUnsock_create(&pipe, 1, SOCK_STREAM) < 0) { return SW_ERR; } swProcessPool_worker(ma, cur_id).pipe_master = pipe.getFd(&pipe, 1); swProcessPool_worker(ma, cur_id).pipe_worker = pipe.getFd(&pipe, 0); swProcessPool_worker(ma, cur_id).id = cur_id; return cur_id; }
/** * Process manager */ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key, int ipc_mode) { bzero(pool, sizeof(swProcessPool)); pool->worker_num = worker_num; pool->max_request = max_request; pool->workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, worker_num * sizeof(swWorker)); if (pool->workers == NULL) { swSysError("malloc[1] failed."); return SW_ERR; } if (ipc_mode == SW_IPC_MSGQUEUE) { pool->use_msgqueue = 1; pool->msgqueue_key = msgqueue_key; pool->queue = sw_malloc(sizeof(swMsgQueue)); if (pool->queue == NULL) { swSysError("malloc[2] failed."); return SW_ERR; } if (swMsgQueue_create(pool->queue, 1, pool->msgqueue_key, 1) < 0) { return SW_ERR; } } else if (ipc_mode == SW_IPC_SOCKET) { pool->use_socket = 1; pool->stream = sw_malloc(sizeof(swStreamInfo)); if (pool->stream == NULL) { swWarn("malloc[2] failed."); return SW_ERR; } pool->stream->last_connection = 0; } else if (ipc_mode == SW_IPC_UNIXSOCK) { pool->pipes = sw_calloc(worker_num, sizeof(swPipe)); if (pool->pipes == NULL) { swWarn("malloc[2] failed."); return SW_ERR; } swPipe *pipe; int i; for (i = 0; i < worker_num; i++) { pipe = &pool->pipes[i]; if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0) { return SW_ERR; } pool->workers[i].pipe_master = pipe->getFd(pipe, SW_PIPE_MASTER); pool->workers[i].pipe_worker = pipe->getFd(pipe, SW_PIPE_WORKER); pool->workers[i].pipe_object = pipe; } } else { swWarn("unknown ipc_type [%d].", ipc_mode); return SW_ERR; } pool->map = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, NULL); if (pool->map == NULL) { swProcessPool_free(pool); return SW_ERR; } pool->ipc_mode = ipc_mode; pool->main_loop = swProcessPool_worker_loop; return SW_OK; }
//create worker child proccess static int swFactoryProcess_manager_start(swFactory *factory) { swFactoryProcess *object = factory->object; int i, pid, ret; int writer_pti; swServer *serv = factory->ptr; #if SW_WORKER_IPC_MODE == 2 #define _SW_PATH_BUF_LEN 128 //这里使用ftok来获取消息队列的key char path_buf[_SW_PATH_BUF_LEN]; char *path_ptr = getcwd(path_buf, _SW_PATH_BUF_LEN); //读数据队列 if(swQueueMsg_create(&object->rd_queue, 1, ftok(path_ptr, 1), 1) < 0) { swError("[Master] swPipeMsg_create[In] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } //为TCP创建写队列 if (serv->have_tcp_sock == 1) { //写数据队列 if(swQueueMsg_create(&object->wt_queue, 1, ftok(path_ptr, 2), 1) < 0) { swError("[Master] swPipeMsg_create[out] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } } #else object->pipes = sw_calloc(object->worker_num, sizeof(swPipe)); if (object->pipes == NULL) { swError("malloc[worker_pipes] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } //worker进程的pipes for (i = 0; i < object->worker_num; i++) { if (swPipeUnsock_create(&object->pipes[i], 1, SOCK_DGRAM) < 0) { swError("create unix socket[1] fail"); return SW_ERR; } object->workers[i].pipe_master = object->pipes[i].getFd(&object->pipes[i], 1); object->workers[i].pipe_worker = object->pipes[i].getFd(&object->pipes[i], 0); } #endif if (serv->task_worker_num > 0) { if (swProcessPool_create(&SwooleG.task_workers, serv->task_worker_num, serv->max_request)< 0) { swWarn("[Master] create task_workers fail"); return SW_ERR; } //设置指针和回调函数 SwooleG.task_workers.ptr = serv; SwooleG.task_workers.onTask = swTaskWorker_onTask; } pid = fork(); switch (pid) { //创建manager进程 case 0: for (i = 0; i < object->worker_num; i++) { // close(worker_pipes[i].pipes[0]); writer_pti = (i % object->writer_num); object->workers[i].writer_id = writer_pti; pid = swFactoryProcess_worker_spawn(factory, i); if (pid < 0) { swError("Fork worker process fail"); return SW_ERR; } else { object->workers[i].pid = pid; } } //创建task_worker进程 if (serv->task_worker_num > 0) { swProcessPool_start(&SwooleG.task_workers); } //标识为管理进程 SwooleG.process_type = SW_PROCESS_MANAGER; ret = swFactoryProcess_manager_loop(factory); exit(ret); break; //主进程 default: object->manager_pid = pid; //TCP需要writer线程 if (serv->have_tcp_sock == 1) { int ret = swFactoryProcess_writer_start(factory); if (ret < 0) { return SW_ERR; } } #if SW_WORKER_IPC_MODE != 2 for (i = 0; i < object->worker_num; i++) { writer_pti = (i % object->writer_num); object->workers[i].writer_id = writer_pti; if (serv->have_tcp_sock == 1) { //将写pipe设置到writer的reactor中 object->writers[writer_pti].reactor.add(&(object->writers[writer_pti].reactor), object->workers[i].pipe_master, SW_FD_PIPE); } } #endif break; case -1: swError("[swFactoryProcess_worker_start]fork manager process fail\n"); return SW_ERR; } return SW_OK; }
/** * Process manager */ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key, int create_pipe) { bzero(pool, sizeof(swProcessPool)); pool->worker_num = worker_num; pool->max_request = max_request; if (msgqueue_key > 0) { pool->use_msgqueue = 1; pool->msgqueue_key = msgqueue_key; } pool->workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, worker_num * sizeof(swWorker)); if (pool->workers == NULL) { swSysError("malloc[1] failed."); return SW_ERR; } pool->map = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, NULL); if (pool->map == NULL) { return SW_ERR; } pool->queue = sw_malloc(sizeof(swQueue)); if (pool->queue == NULL) { swSysError("malloc[2] failed."); return SW_ERR; } int i; if (pool->use_msgqueue) { if (swQueueMsg_create(pool->queue, 1, pool->msgqueue_key, 1) < 0) { return SW_ERR; } } else if (create_pipe) { pool->pipes = sw_calloc(worker_num, sizeof(swPipe)); if (pool->pipes == NULL) { swWarn("malloc[2] failed."); sw_free(pool->workers); return SW_ERR; } swPipe *pipe; for (i = 0; i < worker_num; i++) { pipe = &pool->pipes[i]; if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0) { return SW_ERR; } pool->workers[i].pipe_master = pipe->getFd(pipe, SW_PIPE_MASTER); pool->workers[i].pipe_worker = pipe->getFd(pipe, SW_PIPE_WORKER); pool->workers[i].pipe_object = pipe; } } pool->main_loop = swProcessPool_worker_start; return SW_OK; }
//create worker child proccess static int swFactoryProcess_manager_start(swFactory *factory) { swFactoryProcess *object = factory->object; int i, pid, ret; int reactor_pti; swServer *serv = factory->ptr; if (serv->ipc_mode == SW_IPC_MSGQUEUE) { //读数据队列 if (swQueueMsg_create(&object->rd_queue, 1, serv->message_queue_key, 1) < 0) { swError("[Master] swPipeMsg_create[In] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } //为TCP创建写队列 if (serv->have_tcp_sock == 1) { //写数据队列 if (swQueueMsg_create(&object->wt_queue, 1, serv->message_queue_key + 1, 1) < 0) { swError("[Master] swPipeMsg_create[out] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } } } else { object->pipes = sw_calloc(serv->worker_num, sizeof(swPipe)); if (object->pipes == NULL) { swError("malloc[worker_pipes] fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } //worker进程的pipes for (i = 0; i < serv->worker_num; i++) { if (swPipeUnsock_create(&object->pipes[i], 1, SOCK_DGRAM) < 0) { swError("create unix socket[1] fail"); return SW_ERR; } object->workers[i].pipe_master = object->pipes[i].getFd(&object->pipes[i], 1); object->workers[i].pipe_worker = object->pipes[i].getFd(&object->pipes[i], 0); } } if (SwooleG.task_worker_num > 0) { key_t msgqueue_key = 0; if (SwooleG.task_ipc_mode > 0) { msgqueue_key = serv->message_queue_key + 2; } if (swProcessPool_create(&SwooleG.task_workers, SwooleG.task_worker_num, serv->max_request, msgqueue_key)< 0) { swWarn("[Master] create task_workers fail"); return SW_ERR; } //设置指针和回调函数 SwooleG.task_workers.ptr = serv; SwooleG.task_workers.onTask = swTaskWorker_onTask; if (serv->onWorkerStart != NULL) { SwooleG.task_workers.onWorkerStart = swTaskWorker_onWorkerStart; } } pid = fork(); switch (pid) { //创建manager进程 case 0: //创建子进程 for (i = 0; i < serv->worker_num; i++) { //close(worker_pipes[i].pipes[0]); reactor_pti = (i % serv->writer_num); object->workers[i].reactor_id = reactor_pti; pid = swFactoryProcess_worker_spawn(factory, i); if (pid < 0) { swError("Fork worker process fail"); return SW_ERR; } else { object->workers[i].pid = pid; } } /** * create task worker pool */ if (SwooleG.task_worker_num > 0) { swProcessPool_start(&SwooleG.task_workers); } //标识为管理进程 SwooleG.process_type = SW_PROCESS_MANAGER; ret = swFactoryProcess_manager_loop(factory); exit(ret); break; //主进程 default: SwooleGS->manager_pid = pid; break; case -1: swError("[swFactoryProcess_worker_start]fork manager process fail"); return SW_ERR; } return SW_OK; }
static PHP_METHOD(swoole_process, __construct) { zend_bool redirect_stdin_and_stdout = 0; long pipe_type = 2; zval *callback; //only cli env if (!SWOOLE_G(cli)) { swoole_php_fatal_error(E_ERROR, "swoole_process must run at php_cli environment."); RETURN_FALSE; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bl", &callback, &redirect_stdin_and_stdout, &pipe_type) == FAILURE) { RETURN_FALSE; } char *func_name = NULL; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { swoole_php_fatal_error(E_ERROR, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); swWorker *process = emalloc(sizeof(swWorker)); bzero(process, sizeof(swWorker)); process->id = php_swoole_worker_round_id++; if (php_swoole_worker_round_id == 0) { php_swoole_worker_round_id = 1; } if (redirect_stdin_and_stdout) { process->redirect_stdin = 1; process->redirect_stdout = 1; process->redirect_stderr = 1; pipe_type = 2; } if (pipe_type > 0) { swPipe *_pipe = emalloc(sizeof(swWorker)); int socket_type = pipe_type == 1 ? SOCK_STREAM : SOCK_DGRAM; if (swPipeUnsock_create(_pipe, 1, socket_type) < 0) { RETURN_FALSE; } process->pipe_object = _pipe; process->pipe_master = _pipe->getFd(_pipe, SW_PIPE_MASTER); process->pipe_worker = _pipe->getFd(_pipe, SW_PIPE_WORKER); process->pipe = process->pipe_master; zend_update_property_long(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("pipe"), process->pipe_master TSRMLS_CC); } swoole_set_object(getThis(), process); zend_update_property(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("callback"), callback TSRMLS_CC); }