libuv 학습 노트 (10)
22888 단어 학습 노트
uv_process_t 데이터 구조 와 관련 함수
데이터 구조
typedef struct uv_process_s uv_process_t;
struct uv_process_s {
UV_HANDLE_FIELDS//uv_handle_t ,
uv_exit_cb exit_cb;//
int pid;// id
//UV_PROCESS_PRIVATE_FIELDS :
struct uv_process_exit_s {
UV_REQ_FIELDS//uv_req_t , ,
} exit_req;
BYTE* child_stdio_buffer;//
int exit_signal;//
HANDLE wait_handle;// , closehandle
HANDLE process_handle;//
volatile char exit_cb_pending;//
};
프로 세 스 구성 체:
typedef struct uv_process_options_s {
uv_exit_cb exit_cb; //
const char* file;// utf8
// utf8 。 args[0] 。windows CreateProcess , args
// , , windows_verbatim_arguments
char** args;
// utf8
char** env;
// utf8
const char* cwd;
// uv_spawn
unsigned int flags;
//`stdio` uv_stdio_container_t ,uv_stdio_container_t
// 。 ,stdio[0] stdin, fd 1 stdout, fd 2 stderr.
// windows , MSVCRT 2
int stdio_count;
uv_stdio_container_t* stdio;
//windows
uv_uid_t uid;
uv_gid_t gid;
} uv_process_options_t;
상관 함수
1. 하위 프로 세 스 생 성.함수 내 보 내기, uv. h 에서 설명, process. c 에서 정의
초기 화, 내부 함수, uvspawn 에서 호출
static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);
handle->exit_cb = NULL;
handle->pid = 0;
handle->exit_signal = 0;
handle->wait_handle = INVALID_HANDLE_VALUE;
handle->process_handle = INVALID_HANDLE_VALUE;
handle->child_stdio_buffer = NULL;
handle->exit_cb_pending = 0;
uv_req_init(loop, (uv_req_t*)&handle->exit_req);// , UV_PROCESS_EXIT
handle->exit_req.type = UV_PROCESS_EXIT;
handle->exit_req.data = handle;
}
하위 프로 세 스 생 성
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,
const uv_process_options_t* options)
{
int i;
int err = 0;
WCHAR* path = NULL, *alloc_path = NULL;
BOOL result;
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
*env = NULL, *cwd = NULL;
STARTUPINFOW startup;
PROCESS_INFORMATION info;
DWORD process_flags;
uv_process_init(loop, process);// uv_process_t
process->exit_cb = options->exit_cb;//
if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
return UV_ENOTSUP;//windows
}
if (options->file == NULL || options->args == NULL) {
return UV_EINVAL;// ,
}
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
// utf8 utf16
err = uv_utf8_to_utf16_alloc(options->file, &application);
if (err)
goto done;
// ,UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS “”
err = make_program_args(
options->args,
options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
&arguments);
if (err)
goto done;
//
if (options->env) {
err = make_program_env(options->env, &env);
if (err)
goto done;
}
//
if (options->cwd) {
/* Explicit cwd */
err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);
if (err)
goto done;
} else {// ,
/* Inherit cwd */
DWORD cwd_len, r;
cwd_len = GetCurrentDirectoryW(0, NULL);
if (!cwd_len) {
err = GetLastError();
goto done;
}
cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));
if (cwd == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
}
r = GetCurrentDirectoryW(cwd_len, cwd);
if (r == 0 || r >= cwd_len) {
err = GetLastError();
goto done;
}
}
// PATH
path = find_path(env);
if (path == NULL) {
DWORD path_len, r;
path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (path_len == 0) {
err = GetLastError();
goto done;
}
alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
if (alloc_path == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
}
path = alloc_path;
r = GetEnvironmentVariableW(L"PATH", path, path_len);
if (r == 0 || r >= path_len) {
err = GetLastError();
goto done;
}
}
// options stdio process->child_stdio_buffer
//child_stdio_buffer 3 , 255, option 3 , child_stdio_buffer
// UV_IGNORE( )。 options->stdio ,
//
err = uv__stdio_create(loop, options, &process->child_stdio_buffer);
if (err)
goto done;
// ( )
application_path = search_path(application,
cwd,
path);
if (application_path == NULL) {
/* Not found. */
err = ERROR_FILE_NOT_FOUND;
goto done;
}
// startup(STARTUPINFOW)
startup.cb = sizeof(startup);
startup.lpReserved = NULL;
startup.lpDesktop = NULL;
startup.lpTitle = NULL;
startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);
startup.lpReserved2 = (BYTE*) process->child_stdio_buffer;
// ( )
startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);
startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
} else {
startup.wShowWindow = SW_SHOWDEFAULT;
}
process_flags = CREATE_UNICODE_ENVIRONMENT;
if (options->flags & UV_PROCESS_DETACHED) {
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
}
//
if (!CreateProcessW(application_path,
arguments,
NULL,
NULL,
1,
process_flags,
env,
cwd,
&startup,
&info)) {
/* CreateProcessW failed. */
err = GetLastError();
goto done;
}
// id
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
// , job ,
if (!(options->flags & UV_PROCESS_DETACHED)) {
//uv__init_global_job_handle , uv__init_global_job_handle
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
//
if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
DWORD err = GetLastError();
if (err != ERROR_ACCESS_DENIED)
uv_fatal_error(err, "AssignProcessToJobObject");
}
}
// id
for (i = 0; i < options->stdio_count; i++) {
const uv_stdio_container_t* fdopt = &options->stdio[i];
if (fdopt->flags & UV_CREATE_PIPE &&
fdopt->data.stream->type == UV_NAMED_PIPE &&
((uv_pipe_t*) fdopt->data.stream)->ipc) {
((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId;
}
}
// , ,
result = RegisterWaitForSingleObject(&process->wait_handle,
process->process_handle, exit_wait_callback, (void*)process, INFINITE,
WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
if (!result) {
uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
}
//
CloseHandle(info.hThread);
assert(!err);
// uv_process_t
uv__handle_start(process);
//
done:
uv__free(application);
uv__free(application_path);
uv__free(arguments);
uv__free(cwd);
uv__free(env);
uv__free(alloc_path);
//
if (process->child_stdio_buffer != NULL) {
/* Clean up child stdio handles. */
uv__stdio_destroy(process->child_stdio_buffer);
process->child_stdio_buffer = NULL;
}
return uv_translate_sys_error(err);
}
하위 스 레 드 가 닫 힌 후 반전 함수 exitwait_callback, windows 스 레 드 탱크 에서 호출 됩 니 다.
static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout)
{
uv_process_t* process = (uv_process_t*) data;
uv_loop_t* loop = process->loop;
assert(didTimeout == FALSE);
assert(process);
assert(!process->exit_cb_pending);
process->exit_cb_pending = 1;
// iocp
POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
}
uv_run 에 서 는 스 레 드 종료 정 보 를 받 은 후 uv 를 호출 합 니 다.process_reqs 처리 요청, 최종 호출 uvprocess_proc_exit
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle)
{
int64_t exit_code;
DWORD status;
assert(handle->exit_cb_pending);
handle->exit_cb_pending = 0;
// handle , handle。 uv_close
//handle
/* callback now. */
if (handle->flags & UV__HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return;
}
//
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(handle->wait_handle);
handle->wait_handle = INVALID_HANDLE_VALUE;
}
// handle
uv__handle_stop(handle);
if (GetExitCodeProcess(handle->process_handle, &status)) {
exit_code = status;
} else {
/* Unable to to obtain the exit code. This should never happen. */
exit_code = uv_translate_sys_error(GetLastError());
}
//
if (handle->exit_cb) {
handle->exit_cb(handle, exit_code, handle->exit_signal);
}
}
uv 통과 하기close 닫 기 uvprocess_t, 최종 호출 uvprocess_close
void uv_process_close(uv_loop_t* loop, uv_process_t* handle)
{
uv__handle_closing(handle);// UV_HANDLE_CLOSING
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
//
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
if (!r) {
/* This should never happen, and if it happens, we can't recover... */
uv_fatal_error(GetLastError(), "UnregisterWaitEx");
}
handle->wait_handle = INVALID_HANDLE_VALUE;
}
// exit_wait_callback , handle, loop
// handle
if (!handle->exit_cb_pending) {
uv_want_endgame(loop, (uv_handle_t*)handle);
}
}
libuv 를 사용 하여 하위 프로 세 스 를 만 듭 니 다. 출력, 입력 방향 을 바 꾸 거나 이름 파 이 프 를 사용 하여 프로 세 스 간 통신 을 할 수 있 습 니 다. 이 부분 은 다음 uv 와 통신 할 수 있 습 니 다.pipe_t 및 uvstream_t 등 내용 관련.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
STL 학습노트(6) 함수 객체모방 함수는 모두pass-by-value이다 함수 대상은 값에 따라 전달되고 값에 따라 되돌아오기 때문에 함수 대상은 가능한 한 작아야 한다(대상 복사 비용이 크다) 함수 f와 대상 x, x 대상에서 f를 호출하면:...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.