Forking processes / 2012-01-06 17:11:41
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:
Code:
/* * 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 <http://www.gnu.org/licenses/>. */ #include <errno.h> #include <stdio.h> #include <ix.h> #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 buf[BUF_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 buf[BUF_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 id[2]; /* * 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:
Code:
/usr/local/amiga/bin/m68k-amigaos-gcc.exe fork.c -o fork
Running the fork program in WinUAE typically outputs:
Code:
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!
|