/* ================================================ mingw64でfork(),waitpid(), kill()を何とかしたい ================================================ ●参照させて頂いたページ https://gist.github.com/Cr4sh/126d844c28a7fbfd25c6 http://7shi.hateblo.jp/entry/2012/06/19/213405 http://www.fireproject.jp/feature/c-language/process/fork-wait.html ●コンパイル: gcc -c fork.cpp ●その他 「mingw64でfork()を何とかしたい」の後に読むと分かりやすいかも ちなみにWindowsのコマンドプロンプトではprintf()の表示がされない(理由不明)ので > fork2 > dummy.txt などとして確認すること。 */ /* * fork.c * Experimental fork() on Windows. Requires NT 6 subsystem or * newer. * * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * This software is provided 'as is' and without any warranty, express or * implied. In no event shall the authors be liable for any damages arising * from the use of this software. */ #define _WIN32_WINNT 0x0600 #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winnt.h> #include <ntdef.h> #include <stdio.h> #include <errno.h> #include <process.h> #ifdef __MINGW32__ typedef struct _CLIENT_ID { PVOID UniqueProcess; PVOID UniqueThread; } CLIENT_ID, *PCLIENT_ID; typedef struct _SECTION_IMAGE_INFORMATION { PVOID EntryPoint; ULONG StackZeroBits; ULONG StackReserved; ULONG StackCommit; ULONG ImageSubsystem; WORD SubSystemVersionLow; WORD SubSystemVersionHigh; ULONG Unknown1; ULONG ImageCharacteristics; ULONG ImageMachineType; ULONG Unknown2[3]; } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; typedef struct _RTL_USER_PROCESS_INFORMATION { ULONG Size; HANDLE Process; HANDLE Thread; CLIENT_ID ClientId; SECTION_IMAGE_INFORMATION ImageInformation; } RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; #define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001 #define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002 #define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004 #define RTL_CLONE_PARENT 0 #define RTL_CLONE_CHILD 297 #endif typedef NTSTATUS (*RtlCloneUserProcess_f) (ULONG ProcessFlags, PSECURITY_DESCRIPTOR ProcessSecurityDescriptor /* optional */, PSECURITY_DESCRIPTOR ThreadSecurityDescriptor /* optional */, HANDLE DebugPort /* optional */, PRTL_USER_PROCESS_INFORMATION ProcessInformation); pid_t fork(void) { HMODULE mod; RtlCloneUserProcess_f clone_p; RTL_USER_PROCESS_INFORMATION process_info; NTSTATUS result; mod = GetModuleHandle("ntdll.dll"); if (!mod) return -ENOSYS; //clone_p = GetProcAddress(mod, "RtlCloneUserProcess"); // Ebata clone_p = (RtlCloneUserProcess_f)GetProcAddress(mod, "RtlCloneUserProcess"); if (clone_p == NULL) return -ENOSYS; /* lets do this */ result = clone_p(RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED | RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES, NULL, NULL, NULL, &process_info); if (result == RTL_CLONE_PARENT) { HANDLE me = GetCurrentProcess(); pid_t child_pid; child_pid = GetProcessId(process_info.Process); ResumeThread(process_info.Thread); CloseHandle(process_info.Process); CloseHandle(process_info.Thread); return child_pid; } else if (result == RTL_CLONE_CHILD) { /* fix stdio */ AllocConsole(); return 0; } else return -1; /* NOTREACHED */ return -1; } int kill(pid_t pid, int sig) { int ret; HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); ret = TerminateProcess(h, 0) ? 0 : -1; CloseHandle(h); return ret; } #if 0 int waitpid(pid_t pid, int *stat_loc, int options) { int i = 1; return _cwait(stat_loc, pid, WAIT_CHILD); } #endif int waitpid(pid_t pid, DWORD dwMilliseconds) // Ebata's original waitpid() { HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); // WaitForSingleObject(h, INFINITE); int ret = WaitForSingleObject(h, dwMilliseconds); CloseHandle(h); return ret; } #if 0 // サンプルプログラム int main(void){ pid_t result_pid = fork(); if (result_pid == 0){ // 子プロセス printf("Child process started.\n"); printf("Wait 10 seconds.\n"); printf("result_pid = %d child process.\tpid = %d\n",result_pid,getpid()); fflush(stdout); Sleep(10000); // 10秒くらいの生存期間 fprintf(stdout,"Child process ended.\n"); fflush(stdout); } else{ // 親プロセス printf("Parents process started.\n"); fflush(stdout); // 親プロセスの方には、子プロセスのIDが入るので、それを監視する waitpid(result_pid, INFINITE); // 子プロセス(1つのみ)が終了するまで止まる //waitpid(result_pid, 100); // 100msのみ停止 fprintf(stdout,"Parent process ended.\n"); fflush(stdout); } return 0; } #endif // サンプルプログラム ========================================================== /* シュタインズゲートの「タイムリープ」をコーディングするとこんな感じ gcc -c fork_test.cpp gcc -g fork.cpp fork_test.cpp -o fork_test */ #include <windows.h> #include <stdio.h> #include <process.h> extern pid_t fork(void); extern int waitpid(pid_t pid, DWORD dwMilliseconds); // Ebata's original waitpid() extern int kill(pid_t pid, int sig); int main(void){ pid_t result_pid = -1; // fork()が吐き出さない値をダミーに入れておく int init_i = -1; for (int i = 0; i < 100; i++){ if (i == 17){ // iが17になった時に、子プロセスを起動 result_pid = fork(); init_i = i ; } if (result_pid == 0){ // 子プロセス printf("c:\t%d\n", i); fflush(stdout); if (i > init_i + 50){ // 「岡部、50回先の未来に行く」 exit(0); // 子プロセスの強制終了 } } else { waitpid(result_pid, INFINITE); // 子プロセス(1つのみ)が終了するまで止まる printf("p:%d\n", i);// 「岡部、リーディングシュタイナー発動(記憶を維持したまま、50回前の過去にタイムリープ」 fflush(stdout); } } }
push_back()によるクラスのリストが、実体を繋いでいるのか、コピーして繋いでいるのかの実験。
Newした以上DELETEが必要なのか、について調査中
/* g++ -g stl_test3.cpp -o stl_test3 -static-libstdc++ */ #include <iostream> #include <list> // list 利用のため using namespace std; class PERSON { public: int age; int sex; int life; PERSON(int _age, int _sex) { age = _age; sex = _sex; life = 1; } void func(void){ age += 1; } }; int main(){ list<PERSON> person_list; PERSON *person1 = new PERSON(18, 0); PERSON *person2 = new PERSON(23, 1); PERSON *person3 = new PERSON(101, 1); PERSON *person4 = new PERSON(1, 1); PERSON *person5 = new PERSON(10, 10); #if 0 cout << "step1" << "\n"; person3->life = -1; // cout << person3->age << " " << person3->sex << " " << person3->life << "\n"; cout << "\n"; #endif // どうやらpush_backはコピーするらしい person_list.push_back(*person1); person_list.push_back(*person2); person_list.push_back(*person3); person_list.push_back(*person4); #if 1 delete person1; delete person2; delete person3; delete person4; delete person5; #endif cout << "step2" << "\n"; list<PERSON>::iterator pos; for(pos = person_list.begin(); pos!=person_list.end(); ++pos){ cout << pos->age << " " << pos->sex << " " << pos->life << "\n"; } cout << "\n"; person3->life = -1; // cout << person3->age << " " << person3->sex << " " << person3->life << "\n"; cout << "\n"; #if 1 cout << "step3" << "\n"; //list<PERSON>::iterator pos; for(pos = person_list.begin(); pos!=person_list.end(); ++pos){ if (pos->age == 101){ pos->life = -1; pos->func(); } } #endif cout << "step4" << "\n"; // list<PERSON>::iterator pos; for(pos = person_list.begin(); pos!=person_list.end(); ++pos){ cout << pos->age << " " << pos->sex << " " << pos->life << "\n"; } cout << "\n"; #if 1 cout << "step5" << "\n"; for ( pos = person_list.begin(); pos != person_list.end(); ){ //<-「it++」を削除 if( pos->life == -1 ) { pos = person_list.erase( pos ); continue; } pos++; // ここで次のイテレートに } #endif cout << "step6" << "\n"; //list<PERSON>::iterator pos; for(pos = person_list.begin(); pos!=person_list.end(); ++pos){ cout << pos->age << " " << pos->sex << " " << pos->life << "\n"; } return(0); }