4

Can somebody help me to make this C POSIX code to port it to run under Windows? (no Cygwin, MinGW just Windows native APIs and Visual Studio), tried many things without any luck.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

void usage(char *s);
int test_function(char *host);
FILE *infile, *outfile;
int numforks = 0;

void usage(char *s) {
        printf("Usage: %s <input> <childs>\n", s);
        exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[]) {
        char buf[1024];
        time_t start;
        if (argc < 2)
                usage(argv[0]);
        outfile = fopen("test.txt", "a+");
        infile = fopen(argv[1], "r");
        printf("[*] In: %s Childs: %s\n", argv[1], argv[2]);
        start = time(0);
        while (!feof(infile)) {
                fgets((char *)&buf, sizeof(buf), infile);
                if (buf[strlen (buf) - 1] == '\n')
                        buf[strlen (buf) - 1] = '\0';
                if (!(fork())) {
                        test_function(buf);
                        exit(0);
                } else {
                        numforks++;
                        if (numforks > atoi(argv[2]))
                                for (numforks; numforks > atoi(argv[2]); numforks--)
                                        wait(NULL);
                }
        }
        fclose(infile);
        fclose(outfile);
        printf("[*] Completed in: %lu secs\n", (time(0) - start));
        exit(EXIT_SUCCESS);
}

int test_function(char *host) {
  usleep(2000000); // for debugging
  fprintf(outfile, "%s\n", host);
  printf("%s\n", host);
  return 1;
}

I tried to do this:

#include <stdio.h>
#include <string.h>
#ifdef LINUX
  #include <unistd.h>
#endif
#include <time.h>
#include <stdlib.h>

#ifdef WIN32
  #define fork _forkWin32
  #define usleep Sleep
  #include <cstdlib>
  #include <cstring>
  #include <iostream>
  #include <process.h>
  #include <windows.h>
  using   namespace  std;
#endif

void usage(char *s);
#ifdef WIN32
unsigned int _stdcall test_function(void *ptr);
#else
int test_function(char *host);
#endif
FILE *infile, *outfile;
int numforks = 0;
char proc;

void usage(char *s) {
        printf("Usage: %s <input> <threads>\n", s);
        exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[]) {
        char buf[1024];
        time_t start;
        //#ifdef WIN32
        //HANDLE      child;
        //#endif
        if (argc < 3)
                usage(argv[0]);
        outfile = fopen("test.txt", "a+");
        infile = fopen(argv[1], "r");
        printf("[*] In: %s Threads: %s\n", argv[1], argv[2]);
        start = time(0);
        HANDLE      child;
        while (!feof(infile)) {
                fgets((char *)&buf, sizeof(buf), infile);
                if (buf[strlen (buf) - 1] == '\n')
                        buf[strlen (buf) - 1] = '\0';
                #ifdef WIN32
                child = (HANDLE) _beginthreadex(NULL, 0, test_function, buf, 0, NULL);
                if (child != 0) {
                #else
                if (!(fork())) {
                        test_function(buf);
                #endif
                        exit(0);
                } else {
                        numforks++;
                        if (numforks > atoi(argv[2]))
                                for (numforks; numforks > atoi(argv[2]); numforks--)
                                        #ifdef WIN32
                                        WaitForSingleObject(child, INFINITE);
                                        #else
                                        wait(NULL);
                                        #endif
                }
        }
        fclose(infile);
        fclose(outfile);
        printf("[*] Completed in: %lu secs\n", (time(0) - start));
        exit(EXIT_SUCCESS);
}

#ifdef WIN32
unsigned int test_function(void *ptr) {
    char* host = (char*)ptr;
#else
int test_function(char *host) {
#endif
  usleep(2000000); // for debugging
  fprintf(outfile, "%s\n", host);
  printf("%s\n", host);
  return 1;
}

Doesn't seem to do anything. What am I doing wrong? Is it all wrong?

8
  • 1
    The fork function (actually a system call) is only in Posix. You want to use a Posix environment for Windows (and Cygwin might help). Feb 1, 2013 at 8:46
  • 1
    The way fork works in e.g. Cygwin is to use CreateProcess to load the program again, and insert custom code to jump to the point where the fork call is made in the new process. It's a hack since Windows otherwise doesn't have functionality similar to the fork call. Cygwin is open-source, so you can see how they do it if you want to know the exact technical details. Feb 1, 2013 at 8:49
  • I actually don't want to use Cygwin but native WinAPI. Isn't there a simple way to do in Windows what my code does under POSIX capable OSes (*nix, Linux, BSD, Mac)?
    – bsteo
    Feb 1, 2013 at 8:56
  • No, there is no simple way to do a fork-like thing on Windows, because Windows has a notion of process which is different from the Unix way. Did you consider installing Linux (perhaps inside some VM) on the machine??? And your example is not ANSI C, it is a Posix conforming code. (C standards don't know about processes) Feb 1, 2013 at 9:21
  • I'm normally coding under POSIX systems (Linux in this case) so no need to install any Linux or Linux under VM, I just need to port this code under Windows native, fork or not fork, I need just to make it work under Windows with same or almost the same results (threads).
    – bsteo
    Feb 1, 2013 at 9:32

1 Answer 1

4

Windows doesn't support fork() at all. The Unix fork() is a system call that makes an identical copy of a process, and that's not at all easy to do in Windows.

If at all possible, I'd say using threads to simulate forks is the least bad choice. It does however change a few things - mainly that filehandles are SHARED, not duplicated, so the forked process mustn't close them in the same way as in a true forked process.

Basically, what I'm trying to say is that you are in for a world of pain if you plan on doing something more complicated than a few simple print statements in your forked process, and whilst threads can simulate fork in some cases, it's almost impossible to entirely simulate how fork works in Windows without A LOT of work.

6
  • Those prints ar just for the test functions, my real functions connects to my webservers and get some data.
    – bsteo
    Feb 1, 2013 at 11:43
  • In which case you probably should prepare to have to do some more work. It's probably still easier to use threads than to try to implement fork(), but be prepared for some interesting behaviour if you just compile with #define fork() createthread(... stuff goes here ... ) [Don't think macro is quite the right solution here, but you get the idea] Feb 1, 2013 at 11:45
  • 1
    "I'd say using threads to simulate forks is the least bad choice" -- on the contrary. Threads are the correct choice, using fork is a bad choice. fork does have its advantages, but few of them. Working around lack of thread support in the operating system is not one. Windows properly supports threads, so there's nothing wrong with using them. Still, overall, the correct answer(+1) :-)
    – Damon
    Feb 1, 2013 at 14:01
  • With that in mind, one might want to rewrite this using pthreads. This will "work" (although with fork or sys_clone, not with "threads") under POSIX systems, and pthreads is available and works fine under Windows, too. That'll be the same code everywhere.
    – Damon
    Feb 1, 2013 at 14:05
  • My point is that if the code is originally written to use fork then threads MAY bring some problems. Sure, threads are, generally a better/lighter weight way to create "execute this several times 'simultaneously'.. ". Feb 1, 2013 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.