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-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