Ero sivun ”Fork()” versioiden välillä
p (jospa se järjestelmään kuuluisi) |
(→Taustaprosessin luominen: ISO C90 kieltää esittelyjen ja koodin sekoittamisen) |
||
(13 välissä olevaa versiota 5 käyttäjän tekeminä ei näytetä) | |||
Rivi 1: | Rivi 1: | ||
Fork on SVr4, 4.3BSD ja POSIX.1-2001 - | '''Fork()''' on SVr4, 4.3BSD ja POSIX.1-2001 -standardien mukainen funktio [[C]]-kielessä. Sillä luodaan ohjelmalle kutsun suorituskohtaan lapsiprosessi vastaavassa tilassa. Funktion esittely löytyy <tt>unistd.h</tt>-otsikkotiedostosta. | ||
==Prototyyppi== | |||
pid_t fork() | |||
===Paluuarvo=== | |||
Palautusarvo (tyyppiä <tt>pid_t</tt>) on -1 virheen tapahtuessa, muuten se vastaa lapsiprosessin [[pid|prosessitunnusta]]. Lapsiprosessille palautusarvo näkyy nollana (0x0). | |||
==Käyttö== | |||
Fork on se tapa, jolla uusia prosesseja luodaan [[unix]]eissa. Jos lapsiprosessin pitää suorittaa toista ohjelmaa, se käyttää [[exec]]-kutsua forkin ja mahdollisten siivoustoimien jälkeen. Vaikka prosessin kopioiminen ennen kopion korvaamista toisella saattaa tuntua resurssien haaskaukselta, se ei sitä ole: lapsiprosessin muistiavaruus osoittaa samaa fyysistä muistia, kunnes lapsiprosessi kirjoittaa siihen, eikä käyttämätöntä muistia siis tarvitse kopioida ("Copy-on-Write"). | |||
Fork-kutsun lisäksi on olemassa [[clone]]-kutsu, jolla voi tarkemmin määritellä mitkä resurssit jäävät prosessien yhteisiksi. Tällä kutsulla luodaan [[säie|säikeet]]. | |||
=== Esimerkki === | |||
Luodaan seuraavanlainen C-ohjelma: | |||
<source lang="c"> | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
int main() { | |||
pid_t pid; | |||
printf("Luodaan taustaprosessi\n"); | |||
pid = fork(); | |||
if (pid==0) /* Lapsiprosessille pid näkyy nollana */ | |||
printf("Olen lapsiprosessi\n"); | |||
else if (pid>0) /* Forkkaus onnistui, tämä on isäntä */ | |||
printf("Olen isäntäprosessi\n"); | |||
printf("Terve Linux.fi\n"); | |||
return 0; | |||
} | |||
</source> | |||
Tallennetaan koodi tiedostoon <tt>fork.c</tt> ja käännetään se komennolla <tt>[[gcc]] fork.c -o fork</tt>. Nyt ohjelman tuloste olisi seuraavanlainen: | |||
<pre> | |||
Luodaan taustaprosessi | |||
Olen lapsiprosessi | |||
Terve Linux.fi | |||
Olen isäntäprosessi | |||
Terve Linux.fi | |||
</pre> | |||
Lisäämällä ehtolauseisiin yhden tulostusrivin sijaan vaikkapa silmukassa ajettavaa koodia (esim. <tt>while(1) printf("Lapsiprosessi");</tt>) huomataan, että prosesseja ajetaan vuorotellen. | |||
===[[demoni|Taustaprosessin]] luominen=== | |||
fork-funktion ajavan ohjelman toinen osa jää taustalle ja alkuperäinen ohjelma voidaan sammuttaa. Esimerkkikoodi: | |||
<source lang="c"> | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
int main() { | |||
pid_t pid; | |||
printf("Luodaan taustaprosessi\n"); | |||
pid = fork(); | |||
if (pid > 0) return 0; /* Isäntäprosessi loppuu */ | |||
if (pid < 0) return -1; /* Forkkaus ei onnistunut 0_o */ | |||
while(1) { } /* Ikuinen silmukka */ | |||
return 0; | |||
} | |||
</source> | |||
Tallennetaan koodi tiedostoon <tt>taustaprosessi.c</tt>, käännetään se komennolla <tt>gcc taustaprosessi.c -o taustaprosessi</tt> ja ajetaan se (<tt>./taustaprosessi</tt>). Tuloste on seuraavanlainen: | |||
$ ./taustaprosessi | |||
Luodaan taustaprosessi | |||
$ | |||
Ohjelma siis näyttää sammuvan heti tulostettuaan tekstirivin. Tutkitaanpa asiaa hieman tarkemmin. Aja komento | |||
[[ps]] aux | [[grep]] taustaprosessi | |||
Jolloin huomaat, että taustaprosessi-niminen ohjelma on yhä ajossa. Myös [[top]]:in prosessilistauksessa sen pitäisi näkyä yläpäässä kuluttamassa paljon prosessoritehoa. Voit tappaa sen komennolla <tt>[[killall]] taustaprosessi</tt>. | |||
[[Luokka:Järjestelmä]] | [[Luokka:Järjestelmä]] | ||
[[Luokka:Prosessienhallinta]] |
Nykyinen versio 15. lokakuuta 2016 kello 23.42
Fork() on SVr4, 4.3BSD ja POSIX.1-2001 -standardien mukainen funktio C-kielessä. Sillä luodaan ohjelmalle kutsun suorituskohtaan lapsiprosessi vastaavassa tilassa. Funktion esittely löytyy unistd.h-otsikkotiedostosta.
Prototyyppi[muokkaa]
pid_t fork()
Paluuarvo[muokkaa]
Palautusarvo (tyyppiä pid_t) on -1 virheen tapahtuessa, muuten se vastaa lapsiprosessin prosessitunnusta. Lapsiprosessille palautusarvo näkyy nollana (0x0).
Käyttö[muokkaa]
Fork on se tapa, jolla uusia prosesseja luodaan unixeissa. Jos lapsiprosessin pitää suorittaa toista ohjelmaa, se käyttää exec-kutsua forkin ja mahdollisten siivoustoimien jälkeen. Vaikka prosessin kopioiminen ennen kopion korvaamista toisella saattaa tuntua resurssien haaskaukselta, se ei sitä ole: lapsiprosessin muistiavaruus osoittaa samaa fyysistä muistia, kunnes lapsiprosessi kirjoittaa siihen, eikä käyttämätöntä muistia siis tarvitse kopioida ("Copy-on-Write").
Fork-kutsun lisäksi on olemassa clone-kutsu, jolla voi tarkemmin määritellä mitkä resurssit jäävät prosessien yhteisiksi. Tällä kutsulla luodaan säikeet.
Esimerkki[muokkaa]
Luodaan seuraavanlainen C-ohjelma:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("Luodaan taustaprosessi\n");
pid = fork();
if (pid==0) /* Lapsiprosessille pid näkyy nollana */
printf("Olen lapsiprosessi\n");
else if (pid>0) /* Forkkaus onnistui, tämä on isäntä */
printf("Olen isäntäprosessi\n");
printf("Terve Linux.fi\n");
return 0;
}
Tallennetaan koodi tiedostoon fork.c ja käännetään se komennolla gcc fork.c -o fork. Nyt ohjelman tuloste olisi seuraavanlainen:
Luodaan taustaprosessi Olen lapsiprosessi Terve Linux.fi Olen isäntäprosessi Terve Linux.fi
Lisäämällä ehtolauseisiin yhden tulostusrivin sijaan vaikkapa silmukassa ajettavaa koodia (esim. while(1) printf("Lapsiprosessi");) huomataan, että prosesseja ajetaan vuorotellen.
Taustaprosessin luominen[muokkaa]
fork-funktion ajavan ohjelman toinen osa jää taustalle ja alkuperäinen ohjelma voidaan sammuttaa. Esimerkkikoodi:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("Luodaan taustaprosessi\n");
pid = fork();
if (pid > 0) return 0; /* Isäntäprosessi loppuu */
if (pid < 0) return -1; /* Forkkaus ei onnistunut 0_o */
while(1) { } /* Ikuinen silmukka */
return 0;
}
Tallennetaan koodi tiedostoon taustaprosessi.c, käännetään se komennolla gcc taustaprosessi.c -o taustaprosessi ja ajetaan se (./taustaprosessi). Tuloste on seuraavanlainen:
$ ./taustaprosessi Luodaan taustaprosessi $
Ohjelma siis näyttää sammuvan heti tulostettuaan tekstirivin. Tutkitaanpa asiaa hieman tarkemmin. Aja komento
ps aux | grep taustaprosessi
Jolloin huomaat, että taustaprosessi-niminen ohjelma on yhä ajossa. Myös top:in prosessilistauksessa sen pitäisi näkyä yläpäässä kuluttamassa paljon prosessoritehoa. Voit tappaa sen komennolla killall taustaprosessi.