Forking processes / 2012-01-06 17:21:45

Thanks to binkd and other sources on the Internet, I think that I was able to correctly use the ixemul.library to "fork" processes . Here is a code snippet:

 /*  *  fork.c -- An example of using ixemul.library pseudo-forking function  *  *  Copyright (c) 2011 Tygre (yann-gael@gueheneuc.net)  *  * This program is free software: you can redistribute it and/or modify  * it under the terms of the GNU General Public License as published by  * the Free Software Foundation, either version 3 of the License, or  * (at your option) any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU General Public License for more details.  *  * You should have received a copy of the GNU General Public License  * along with this program.  If not, see .  */      #include   #include   #include    #define   MAX_COUNT  5 #define   BUF_SIZE   100   /*   * The function that will be called by two separate processes.  * It just prints out MAX_COUNT times a counter while sleeping  * in between each print to show the "forking".   */ static void forked_print(char *id)  {     pid_t   pid = getpid();     int     i;     char    bufBUF_SIZE;      srand(time(NULL));      sprintf(buf, "%s pid is %dn", id, pid);     write(1, buf, strlen(buf));      for (i = 1; i <= MAX_COUNT; i++) {         sprintf(buf, "%s, with pid %d, value = %dn", id, pid, i);         write(1, buf, strlen(buf));         sleep(rand() % 4);     }      sprintf(buf, "%s, with pid %d, just quitted!n", id, pid);     write(1, buf, strlen(buf)); }    /*  * This function does the "magic" of "forking" the main process.  * It is heavily inspired by the function "branch" available in  * the 0.9.9 release of "binkd" in the file "branch.c".  * Below is the copying permission statement from "branch.c":  *  *  branch.c -- Create co-processes  *  *  branch.c is a part of binkd project  *  *  Copyright (C) 1996-1998  Dima Maloff, 5047/13  *  *  This program is free software; you can redistribute it and/or modify  *  it under the terms of the GNU General Public License as published by  *  the Free Software Foundation; either version 2 of the License, or  *  (at your option) any later version. See COPYING.  */ static int branch(register void (*F) (void *), register void *arg, register size_t size) {     char            bufBUF_SIZE;     register int    rc;     static char    *tmp;          /*       * We print out some information regarding the "arg" and its "size".      */     sprintf(buf, "Before ix_vfork, arg: %d, size: %dn", arg, size);     write(1, buf, strlen(buf));      if(!(rc = ix_vfork()))     {         vfork_setup_child();              /*           * We make our own copy of arg for the child as the parent           * may destroy it before the child finish to use it.           */         if(size > 0)         {             if((tmp = malloc(size)) == NULL)             {                 perror("Malloc failed");                 return -1;             }             else             {                 memcpy(tmp, arg, size);             }         }         else         {             tmp = 0;         }              /*           * We print out some information regarding the "arg" and its copy, "tmp".          * It is important to note that the pointer value for "arg" did not change          * after the "forking" because it is not a true "forking" but rather the          * creation of a thread.           * See http://binkd.sourcearchive.com/documentation/0.9.9plus-p20060809-1/branch_8c-source.html          */         sprintf(buf, "Before ix_vfork, arg: %d, tmp: %dn", arg, tmp);         write(1, buf, strlen(buf));          ix_vfork_resume();         F(tmp);         free(tmp);         _exit(0);     }     else if (rc < 0)     {         sprintf(buf, "ix_vfork: %sn", strerror(errno));         write(1, buf, strlen(buf));     }          return rc; }    int main(void) {     char id2;      /*      * We "fork" the function "forked_print", using "C" to denote the child.      */     sprintf(id, "C");     if(branch((void *) forked_print, (void *) id, sizeof(id)) < 0)     {         perror("Cannot branch!");     }     else      {         /*          * We call the function "forked_print" in the parent process, using "P".          */         sprintf(id, "P");         sleep(3);         forked_print(id);     }     exit(0); } 

 

To (cross-)compile this code (for example in CygWin), just call:

 /usr/local/amiga/bin/m68k-amigaos-gcc.exe fork.c -o fork 

 

Running the fork program in WinUAE typically outputs:

 Before ix_vfork, arg: ...10, size: 2 Before ix_vfork, arg: ...10, tmp: ...28 C pid is ...60 C, with pid ...60, value = 1 C, with pid ...60, value = 2 C pid is ...36 P, with pid ...36, value = 1 C, with pid ...60, value = 3 P, with pid ...36, value = 2 C, with pid ...60, value = 4 P, with pid ...36, value = 3 P, with pid ...36, value = 4 C, with pid ...60, value = 5 P, with pid ...36, value = 5 P, with pid ...36, just quitted! C, with pid ...60, just quitted! 

 

I believe that this code is correct, please let me know if I overlooked something!