/* mingw64でfork()を何とかしたい gcc -g fork.c -o fork (ちゃんと動いているのかどうか不明だけど) ちなみに、"コマンドプロント"だけだと、"ko"が出てこないので、 fork > dummy.txt みたいにしないと、稼動確認できないみたい ちなみにタスクマネージャで見る限り、2つのプロセスは動いているみたい gcc -g fork.c -o fork fork.c:81:7: warning: conflicting types for built-in function 'fork' pid_t fork(void) ^ fork.c: In function 'fork': fork.c:92:11: warning: assignment from incompatible pointer type clone_p = GetProcAddress(mod, "RtlCloneUserProcess"); という警告がでるが、良く分からんので、今は放置 */ /* * 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"); 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; } #if 0 // #ifdef __TEST__ int main(int argc, const char *argv[]) { pid_t pid = fork(); printf("pid %d\n", pid); switch (pid) { case 0: { printf("parent %d\n", pid); FILE *f = fopen("forktest.dat", "w"); fprintf(f, "ok\n"); fclose(f); break; } default: printf("child %d\n", pid); int i = 0; while (i < 10000){ i++; } break; } } //#endif #endif #if 1 int main(int argc, char *argv[]) { int i,pid; int pid2; int status; // printf("---Fork test---\n"); pid = fork(); /*子プロセスの生成。戻り値 0:子プロセス -1:エラー 0以上:親プロセス */ printf("fork() : pid = %d\n" , pid); for(i = 0 ; i < 5 ; i++){ //my_sleep(1); /*一秒待機*/ Sleep(1000); pid2 = getpid(); printf("%d : %s %d %d\n" , i , pid > 0 ? "Oya:" : "Ko :" , pid2, pid); fflush(stdout); // これを省略すると、バラバラに出力されなくなる } //wait(&status); /*子プロセスが終了するのを待つ→wait()関数がない*/ return EXIT_SUCCESS; } #endif