Fork ()
La fuzione fork()
__pid_t fork (void)
crea una copia del processo. Il processo originario è chiamato "Padre ", il processo clone è chiamato "Figlio ".
Se la funzione "fork()" ha successo, essa ritorna il valore 0 (zero) al processo Figlio, e ritorna al processo Padre il valore del pid del processo Figlio (che sarà esclusivo e diverso dal pid del processo Padre). In caso di errore la funzione ritorna -1.
L'esecuzione del processo Padre è svincolata da quella del processo 'Figlio; e pertanto procedono indipendentemente l'una dall'altra.
Volendola utilizzare direttamente in Gambas, bisognerà dichiararla con Extern, nonché dichiarare la libreria di C: libc.so.6, nella quale la funzione è contenuta:
Private Extern fork() As Integer In "libc:6"
Mostriamo di seguito alcuni esempi di uso in Gambas.
1° esempio
Library "libc:6" ' __pid_t fork (void) ' Clone the calling process, creating an exact copy. Private Extern fork() As Integer Public Sub Main() Dim pid, i, n As Integer pid = fork() If pid = 0 Then ' "fork()" ritorna 0 al processo "Figlio". ' Dunque qui siamo nel processo "Figlio": For i = 0 To 9 Print "Figlio: "; i Wait 0.3 Next Quit Else If pid > 0 ' "fork()" ritorna al processo "Padre" il pid del processo "Figlio". ' Dunque qui siamo nel processo "Padre": For n = 0 To 9 Print "Padre: "; n Wait 0.6 Next Else Error.Raise("Errore nel fork !") Endif End
2° esempio
In questo esempio vengono creati 4 Figli di un medesimo processo Padre:
Library "libc:6" ' __pid_t fork (void) ' Clone the calling process, creating an exact copy. Private Extern fork() As Integer ' __pid_t getpid (void) ' Get the process ID of the calling process. Private Extern getpid() As Integer ' __pid_t getppid (void) ' Get the process ID of the calling process's parent. Private Extern getppid() As Integer ' void exit(int status) ' Terminates the calling process immediately. Any open file descriptors belonging to the process are closed. Private Extern exit_C(status As Integer) Exec "exit" ' __pid_t wait (__WAIT_STATUS __stat_loc) ' Wait for a child to die. Private Extern wait_C(__stat_loc As Pointer) As Integer Exec "wait" Public Sub Main() Dim b As Byte Dim i As Integer Dim pid As New Integer[4] For b = 0 To pid.Max pid[b] = fork() If pid[b] = 0 Then Print "Figlio con PID: "; getpid(); " - Il PID del Padre è "; getppid() exit_C(0) Else i = pid[b] wait_C(VarPtr(i)) ' Aspetta che il figlio sia creato Endif Next End
3° esempio
In quest'altro esempio, facendo anche uso delle funzioni esterne "mmap()" e "wait()", si provvederà a passare dei dati per mezzo di una variabile di tipo Puntatore dal processo Figlio al processo Padre.
Tale variabile di tipo Puntatore rappresenterà la memoria condivisa (shared memory ) tra il processo Padre e quello Figlio.
Library "libc:6" Private Const PROT_READ As Integer = 1 Private Const PROT_WRITE As Integer = 2 Private Const MAP_SHARED As Integer = 1 Private Const MAP_ANONYMOUS As Integer = 32 ' void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, __off_t __offset) ' Map addresses starting near ADDR and extending for LEN bytes. Private Extern mmap(__addr As Pointer, __len As Long, __prot As Integer, __flags As Integer, __fd As Integer, __offset As Long) As Pointer ' __pid_t fork(void) ' Clone the calling process, creating an exact copy. Private Extern fork() As Integer ' __pid_t wait (__WAIT_STATUS __stat_loc) ' Wait for a child to die. Private Extern wait_C(__stat_loc As Pointer) As Integer Exec "wait" Public Sub Main() Dim p As Pointer Dim x, pid As Integer Dim st As Stream ' Crea la memoria condivisa: p = mmap(0, SizeOf(gb.Pointer), PROT_READ Or PROT_WRITE, MAP_SHARED Or MAP_ANONYMOUS, -1, 0) pid = fork() Select Case pid Case -1 Case 0 ' Processo Figlio ' Il processo figlio gli dà un valore all'area di memoria condivisa: st = Memory p For Write Write #st, "Gambas" st.Close Case Else ' Processo Padre wait_C(VarPtr(x)) ' Si potrebbe utilizzare anche un semplice " Sleep 0.1 " ' Il padre stampa il valore scritto dal processo figlio: Print "Il valore della shared memory è: "; String@(p) End Select End