/*
* 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 %d\n", id, pid);
write(1, buf, strlen(buf));
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "%s, with pid %d, value = %d\n", 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: %d\n", 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: %d\n", arg, tmp);
write(1, buf, strlen(buf));
ix_vfork_resume();
F(tmp);
free(tmp);
_exit(0);
}
else if (rc < 0)
{
sprintf(buf, "ix_vfork: %s\n", 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);
}
$ gcc pseudofork.c -o fork pseudofork.c: In function `branch': pseudofork.c:94: warning: assignment makes pointer from integer without a cast /gg/ppc-morphos/lib/libc.a(vfork_setup_child.o): In function `ix_vfork_setup_child': vfork_setup_child.o(.text+0xc): undefined reference to `__dbsize' vfork_setup_child.o(.text+0x16): undefined reference to `__datadata_relocs' vfork_setup_child.o(.text+0x1e): undefined reference to `__datadata_relocs' collect2: ld returned 1 exit status $
@ede, post #1
@BigBang, post #5
/* This function is used to obtain and set variables from ixemul.library.
* In general, this is not a function you should call yourself.
* Only the startup code should use this. If you need to call this
* function for some reason, I recommend that the ix_get_variables()
* function from crt0.c is used instead (see below).
*/
void ix_get_vars(int argc, char **ctype, int *_sys_nerr,
struct Library **sysbase, struct Library **dosbase,
FILE ***fpp, char ***environ_out, char ***environ_in,
int *real_errno, int *real_h_errno, struct __res_state *_res,
int *_res_socket, int *ExecLib);
/* A wrapper function for ix_get_vars(). This is not an ixemul function,
* but it is part of crt0.c. The single argument should be set to 0.
*/
void ix_get_variables(int from_vfork_setup_child);
@Jacek Piszczek, post #8
libsyscall na pewno nie jest wymagany d kompilacji