kategoria: ANSI C
[#1] pseudo fork()
Wyszukałem przykład, ponoć kompiluje się pod ixemul na amigaos.


/*
* 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);
}




Próbuję skompilować pod ixemul na morphos (gcc 2.95.3) i mam tak:


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



Dlaczego ?



Ps. Docelowo chcę mieć port bash do odpalania pewnych skryptów (dużo), sh i ksh nie poradzi.


Ostatnia aktualizacja: 20.02.2015 11:06:49 przez ede
[#2] Re: pseudo fork()

@ede, post #1

Wygląda na to, że linkerowi brakuje jakiejś binarki, w której są zdefiniowane '__dbsize', '__datadata_relocs' i '__datadata_relocs'. Albo masz złą wersję libów.
Na początek spróbowałbym znaleźć liba z tymi symbolami (np. przegrepowawszy liby) i potem skompilować wszystko jeszcze raz, wskazując bezpośrednio odpowiedni lib linkerowi.
[#3] Re: pseudo fork()

@BigBang, post #2

Przegripowałem od razu, co prawda mosowym Find. Siedzi np. w libc.a, sh. Zaciągnę sdk source, popatrzę, może coś...
[#4] Re: pseudo fork()

@BigBang, post #2

Ano nie ma ich w crt0.o (sdk-bin 3.5). Natomiast w crt0.c są (sdk-source 3.4). Może to będzie to.
[#5] Re: pseudo fork()

@ede, post #4

Ano... samo napisanie programu to dopiero połowa sukcesu :)
[#6] Re: pseudo fork()

@BigBang, post #5

Tak... no ale żeby już na wstępie mocno biło po łapkach :)

Wyczaiłem jeszcze, że trzeba użyć ix_get_variables(int).


/* 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);


Tylko o co chodzi z tym 'crt0.c' ? Jak tego użyć żeby zadziałalo ?
[#7] Re: pseudo fork()

@ede, post #6

Brak libsyscall.a (quark) - czyli kompilacje ixemul.library (w tym to dobre crt0.c) można sobie między bajki włożyć ?





Ostatnia aktualizacja: 23.02.2015 02:39:19 przez ede
[#8] Re: pseudo fork()

@ede, post #7

libsyscall na pewno nie jest wymagany do kompilacji. Odnośnie forkowania + ixemul - nie trać czasu, ixemul nie wspiera prawdziwego fork'a, a bez tego port basha jest nietrywialny.
[#9] Re: pseudo fork()

@Jacek Piszczek, post #8

Ok, jak nie uda się z bashem to trudno. Jednak jak już 'zmarnowalem' tyle czasu to chciałbym przynajmniej jakąś wypadkową z tego. A nóż, widelec przyda się do portowania czegoś innego.
Dałem radę z lseek64(), socketpair(), getaddrinfo() których brak w ixemul. Teraz przyszła kolej na nieprawdziwego fork'a :}

Ciekawy jestem dlaczego ix_vfork() a dokładniej ix_vfork_setup_child() nie kompiluje się pod MorphOS...

libsyscall na pewno nie jest wymagany d kompilacji


To jak zrobić żeby nie krzyczało : brak -lsyscall ?
[#10] Re: pseudo fork()

@Jacek Piszczek, post #8

bez tego port basha jest nietrywialny


:) nie no bez to jest trywialny.


[#11] Re: pseudo fork()

@ede, post #1

Wyszukałem przykład, ponoć kompiluje się pod ixemul na amigaos.


Ponoć straciło uzasadnienie.

AmigaOS:
gcc pseudofork.c -resident -o fork



Po wielu próbach i błędach wykminiłem.
MorphOS:
gcc pseudofork.c -mresident32 -o fork
[#12] Re: pseudo fork()

@ede, post #11

Swietne ! kiedy bedzie na aminecie ?
[#13] Re: pseudo fork()

@sand, post #12

Jeśli chodzi o przykładowy kod to w zasadzie jest z Aminet-u właśnie :) o ile dobrze sobie przypominam.
[#14] Re: pseudo fork()

@ede, post #13

Bardziej interesuje mnie port basha. ;]
[#15] Re: pseudo fork()

@sand, post #14

W tym z obrazka działają jedynie wewnętrzne komendy. Póki co jest jakiś postęp ale pomimo, że efekt wygląda dość obiecująco, to ten eksperymentalny port jakby to powiedzieć... jeszcze nie przypomina posłusznego niewolnika :) Także nie ma co wysyłać na razie.
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem