2011|08|
2013|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|05|06|07|08|09|10|11|12|
2016|01|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|

2018-02-21 シュタインズゲートの「タイムリープ」「リーディングシュタイナー」をコーディングするとこんな感じ [長年日記]

/*
  ================================================
  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);
	}
  }
}
syntax2html