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-04 副業シミュレーション [長年日記]

/*
  gcc -g second_job.cpp -o second_job
 
 
  考え方
  
  (1)8時間労働、8時間睡眠、8時間余暇を基本として考える。
  (2)8時間余暇の中には、通勤時間1.5時間 食事時間1.5時間が含まれるものとする
  (3)とすれば、残りの余暇5時間をどのような使い方をするのかが問題となる。
  
  (4)十分な余暇は、基本的に正業のパフォーマンスを上げるものであるとする。
  (4)余暇を使った副業は、収入になるものとする
 
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct person {
  double first_business_hour;
  double sleep_hour;
  double commute_time;
  double meal_time;
 
  double max_remain_time;
  double second_business_hour;
  double final_remain_time;
 
  double fb_fee;
  double sb_fee;
  
  double fatigue_func;
  double cost;
 
  struct person *prev;  /* 前の構造体を示すポインタ */
  struct person *next;  /* 次の構造体を示すポインタ */
} PERSON;
 
 
double min(double a, double b)
{
  if (a > b)
	return b;
  else
	return a;
}
 
double diff(double a, double b)
{
  if (a > b)
	return a - b;
  else
	return 0;
}
 
 
double fatigue_func(double time)
{
  if (time < 1.0){
	return 0.5;
  }
  else if ((time >= 1.0) && (time < 3.0)){
	return (1.0 - 0.5)/(3.0 - 1.0) * (time - 1.0) + 0.5;
  }
  else {
	return 1.0;
  }
}
 
const double First_Business_hourly_fees = 2000;
const double First_Business_extra_fees = First_Business_hourly_fees * 1.25;
const double Second_Business_hourly_fees = 1000;
 
 
int main()
{
  srand(13);
 
  PERSON* first_p_person= (PERSON*)malloc(sizeof(PERSON));
  PERSON* last_p_person= (PERSON*)malloc(sizeof(PERSON));
 
  PERSON*  p_prev_person = first_p_person;
 
  for (int i = 0; i < 100; i++){
	
	PERSON* p_person= (PERSON*)malloc(sizeof(PERSON));
	memset(p_person, 0, sizeof(PERSON));
 
 
	//////// ポインタの貼り替え //////////
	p_prev_person->next = p_person;
	p_person->next = last_p_person;
	p_person->prev = p_prev_person;
	p_prev_person = p_person;
	//////////////////////////////////////
 
	p_person->first_business_hour = 8.0 + 2.0 * (double)rand()/RAND_MAX;    // 8~10時間
 
	p_person->first_business_hour = 8.0;    // 8~10時間
 
	p_person->sleep_hour = 7.0 + 1.0 * (1.0 - 2.0 * (double)rand()/RAND_MAX); // 6~8時間
	p_person->commute_time = 1.0 + 0.5 * (1.0 - 2.0 * (double)rand()/RAND_MAX); // 0.5~1.5時間
	p_person->meal_time = 1.0 + 0.5 * (1.0 - 2.0 * (double)rand()/RAND_MAX);  // 0.5~1.5時間
	
	p_person->max_remain_time = 
	  24.0 - 
	  p_person->first_business_hour -
	  p_person->sleep_hour - 
	  p_person->commute_time - 
	  p_person->meal_time;    // 最悪でも3時間の、最良で9時間の余暇時間ができる
 
#if 1
	p_person->second_business_hour = p_person->max_remain_time * (double)rand()/RAND_MAX; //余暇の時間を適当に振る
#else
	p_person->second_business_hour = 0;
#endif
 
	p_person->final_remain_time = p_person->max_remain_time - p_person->second_business_hour;
	
	p_person->fb_fee = 
	  min(p_person->first_business_hour, 8.0) * First_Business_hourly_fees +
	  diff(p_person->first_business_hour, 8.0) * First_Business_extra_fees;
	
	p_person->sb_fee = p_person->second_business_hour * Second_Business_hourly_fees;
	p_person->fatigue_func = fatigue_func(p_person->final_remain_time);
 
	p_person->cost =	
	  p_person->fb_fee * p_person->fatigue_func + p_person->sb_fee;
  
	//printf("%d:cost = %f\n", i, p_person->cost);
 
  }
 
 
  double total_cost = 0.0;
  
  PERSON* p_person = first_p_person->next;
 
  printf("本業時間,睡眠時間,通勤時間,食事時間,余暇時間,副業時間,残余暇時間,RATIO,収入\n");
 
  while(p_person->next != last_p_person){
	total_cost += p_person->cost;
	
	printf("%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
		   p_person->first_business_hour,
		   p_person->sleep_hour,
		   p_person->commute_time,
		   p_person->meal_time,
		   p_person->max_remain_time,
		   p_person->second_business_hour,
		   p_person->final_remain_time,
		   p_person->fatigue_func,
		   p_person->cost
		   );
	
	p_person = p_person->next;
 
  }
  
  printf("total cost = %f\n", total_cost);  
 
 
}
syntax2html

2018-02-13 DMTCP: Distributed MultiThreaded CheckPointing [長年日記]

途中の状態のプロセスを凍らせてセーブするもの(らしい)

途中の状態のプロセスを凍らせてセーブするもの(らしい)

この説明が詳しい http://dmtcp.sourceforge.net/dmtcp-mug-17.pdf

プロセスの保存と復元によるGUIアプリケーションの起動高速化

http://oberon.nagaokaut.ac.jp/katsuk/papers/ipsj/10/IPSJ/pdf/arc/3L_7.pdf


2018-02-14 mingw64でfork()を何とかしたい [長年日記]

/*
  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
syntax2html

2018-02-16 mingw64でfork(),waitpid(), kill()を何とかしたい [長年日記]

/*
  ================================================
  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 -g fork2.cpp -o fork2
 
  ●その他
  「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>
 
#define CHILD_NUM 10
#define WNOHANG		1	/* dont hang in wait */ // ここではコンパイル通す為のダミー値
 
#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;
}
 
 
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;
}
syntax2html

2018-02-17 シュタインズゲートに登場する「世界線」、使い方間違っているぞ。 [長年日記]

_ 疑問:コンピュータの中で作り出した仮想世界で「流れる時間」(×時間、×時刻)の概念を現わす用語を「世界線」といって良いか。


============
(1)調査結果
============

(その1)

定義:「世界線」は簡単にいえば、物質が「時空」の中を動く経路を線であらわしたもの

具体例:

(1)X軸が時間、Y軸が距離と座標軸を決めて、右上がりの直線のグラフをを書いた時のグラフの線が世界線。
(2)このグラフは、物体の目に見えるままの運動を表していない。
(3)時間と空間を組み合わせた速さを表現している。速さという目に見えない抽象世界を表現している

その他:
ニュートンの古典力学は、時間と空間を個別に考えていた。比して、アインシュタインが提唱した相対性理論では、時間と空間は一体化して「時空」と考えるようになり、時空を移動するという抽象概念として「世界線」という言葉がつくられた


(その2)
定義:4次元時空の中で動く粒子の軌跡(ただし、4次元時空とはミンコフスキー空間)

具体例;
(1)3次元時間(x,y,z)という概念に時間(ct)を取り入れたx,y,z,ct(時間)を4次元空間と呼び、これをミンコフスキー時空という。
(2)空間と時間の各成分の2乗を足すときに、時間の前の係数を-1 にして足すことによって不変量、すなわち長さを求めることができる。計量の各成分の符号が異なるような空間をミンコフスキー空間とよび、また、その計量はミンコフスキー計量という。

その他:
ミンコフスキー空間によって、時間と空間をゴチャにした(アインシュタインの相対性理論の)概念がキレイに整理される(高校レベルの数学で)

=======
(2)結論
=======

●コンピュータの中で作り出した仮想世界に「流れる時間」(×時間、×時刻)の概念を現わる用語を「世界線」と呼ぶのは妥当ではない。

●(迂遠ではあるが)ここは素直に「仮想世界時間」であり、その時間の概念は「仮想世界時間軸」と呼ぶことにする。

==========
(3)その他
==========


■英語にすると、これが長くて、特にパワーポイントの改行がウザい (正直これが辛い。私は論文で略号を使うの嫌いな人)
「世界線」→"world line" 「仮想世界時間軸」→ "Virtual world time axis"

■シュタインズゲートに登場する「世界線」、使い方間違っているぞ。
α世界線 → α世界 / α世界空間 あたりが妥当かと思う。
(「α並列世界」でも、ちょっと変だと思う。並列というからには、世界の時空ベクトルが同一方向を向いているという、暗黙の設定が入るから)

# (提言)岡部は仕方ないとして、紅莉栖は科学者なんだから、岡部に正しい用語の使い方を説明すべきだと思う。
# 少なくとも、相対論に精通している紅莉栖が「世界線」を使っちゃうのば、やっぱりマズいと思う。

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