Comment fork ()?
Im vraiment nouveau à la fourche, ce qui est le pid faire dans ce code? Quelqu'un peut-il expliquer ce qui arrive à la ligne X et la ligne de Y ?
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#define SIZE 5
int nums[SIZE] = {0,1,2,3,4};
int main()
{
int i;
pid_t pid;
pid = fork();
if (pid == 0) {
for (i = 0; i < SIZE; i++) {
nums[i] *= -i;
printf("CHILD: %d ",nums[i]); /* LINE X */
}
}
else if (pid > 0) {
wait(NULL);
for (i = 0; i < SIZE; i++)
printf("PARENT: %d ",nums[i]); /* LINE Y */
}
return 0;
}
Avez-vous essayé en fait de la compilation et de l'exécution? Que PENSEZ-vous qui va arriver?
Vous pouvez prendre un coup d'oeil ici: ideone.com/DasYqa
l'homme à la fourche
Assurez-vous de mettre des retours à la ligne à la fin de la
ideone.com/dNpNSD
Vous pouvez prendre un coup d'oeil ici: ideone.com/DasYqa
l'homme à la fourche
Assurez-vous de mettre des retours à la ligne à la fin de la
printf()
états; sinon, rien n'est garanti à apparaître. Vous devriez #include <sys/wait.h>
de déclarer wait()
; vous n'avez probablement pas besoin de #include <sys/types.h>
explicitement.ideone.com/dNpNSD
OriginalL'auteur PhoonOne | 2013-02-27
Vous devez vous connecter pour publier un commentaire.
fork()
duplique le processus, donc après l'appel de la fourche il y a en fait 2 instances de votre programme en cours d'exécution.Comment savez-vous quelle est l'origine (parent), et qui est le nouveau (l'enfant)?
Dans le processus parent, le PID du processus fils (qui sera un entier positif) est retourné à partir de
fork()
. C'est pourquoi laif (pid > 0) { /* PARENT */}
code fonctionne. Dans le processus de l'enfant,fork()
retourne juste0
.Ainsi, en raison de la
if (pid > 0)
vérifier, le processus père et le processus de l'enfant va produire de sortie différents, que vous pouvez voir ici (tel que fourni par @jxh dans les commentaires).non pas que vous ne savez pas, mais pour d'autres personnes qui pourraient ne pas - Vous pouvez utiliser
perror(fork)
pour les valeurs de retour de la fourche qui indique les erreurs.man perror
OriginalL'auteur MatthewD
Exemple le plus simple pour fork()
La valeur de retour de fork(). Valeur de retour -1= échec; 0= l'enfant dans le processus; positif = dans le processus parent (et la valeur de retour est l'enfant de l'id de processus)
Ce qui est différent dans le processus de l'enfant que le parent?
Maintenant, nous allons visualiser le code de votre programme
Maintenant OS faire deux copies identiques d'espaces d'adressage, un pour la mère et l'autre pour l'enfant.
À la fois le parent et l'enfant de démarrage du processus de leur exécution juste après l'appel système fork(). Depuis les deux processus sont identiques, mais des espaces d'adressage différents, ces variables initialisées avant l'appel fork() ont les mêmes valeurs dans les deux espaces d'adressage. Chaque processus a son propre espace d'adressage ainsi toute modification sera indépendant des autres. Si le parent change la valeur de la variable, la modification n'affecte que la variable dans le parent de l'espace d'adressage du processus. D'autres espaces d'adressage créé par fork() système d'appels ne seront pas affectées, même si ils ont les mêmes noms de variables .
Ici parent pid est non-nul, il appelle la fonction ParentProcess(). D'autre part, l'enfant a un zéro pid et il appelle ChildProcess() comme indiqué ci-dessous:
Dans votre code parent processus d'appel
wait()
il s'arrête à ce point, jusqu'à ce que l'enfant quitte. Si l'enfant est de sortie s'affiche en premier.De SORTIE de processus enfant
Puis après que l'enfant quitte, le parent continue d'après le wait() appel et imprime sa sortie prochaine.
De SORTIE de processus parent:
Au dernier les deux sorties combinées à l'enfant et le parent processus sera affiché sur le terminal comme suit:
Pour plus d'info consultez ce lien
Oui je suis d'accord avec votre suggestion . Je vais bientôt mettre à jour la réponse de référence approprié . Merci pour la suggestion
Est-ce suffisant ou dois-je améliorer la réponse plus ? Toutes les suggestions sont les bienvenues 🙂
Assurez-vous de mentionner que vous avez obtenu les images à partir de ce lien. Si vous copiez des images ou le code ou le texte d'ailleurs ensuite vous avez toujours besoin de lien avec l'attribution.
J'ai juste inséré comme vous l'avez suggéré .. je vais takecare à l'avenir
OriginalL'auteur Punit Vara
La
fork()
fonction est spécial parce qu'il renvoie en fait à deux reprises: une fois pour le processus père et le processus de l'enfant. Dans le processus parent,fork()
retourne le pid de l'enfant. Dans le processus de l'enfant, elle renvoie 0. Dans le cas d'une erreur, pas de processus enfant est créé et -1 est retourné à la société mère.Après un appel réussi à
fork()
, le processus de l'enfant est essentiellement une copie exacte du processus parent. Les deux ont leurs propres copies de l'ensemble des variables locales et globales, et de leurs propres copies de tous les descripteurs de fichiers ouverts. Les deux processus s'exécutent simultanément, et parce qu'ils partagent les mêmes descripteurs de fichiers, la sortie de chaque processus sera probablement interleave les uns avec les autres.Prenant un coup d'oeil à l'exemple de la question:
Cela permettra de sortie suivants:
Parce que le processus parent appels
wait()
il s'arrête à ce point, jusqu'à ce que l'enfant quitte. Ainsi, l'enfant est sortie apparaît en premier. Puis, après que l'enfant quitte, le parent continue d'après lewait()
appel et imprime sa sortie prochaine.OriginalL'auteur dbush
fork()
est un appel de fonction qui crée un processus. Le processus qui appellefork()
est appelé le processus parent, et le nouveau processus est appelé la processus enfant.Sur le retour de la
fork()
appel système, les deux processus ont des copies à l'identique de leur niveau de l'utilisateur contexte, sauf pour la valeur de retour,pid
.Dans le processus parent,
pid
est leChild process ID
(ID de processus du nouvellement créé processus enfant).Dans le processus enfant,
pid
est0
.Le noyau ne la séquence des opérations pour
fork()
.ID
nombre à la processus enfant.les parties d'un processus, tels que la région de texte, peuvent être partagées entre
processus, le noyau peut parfois incrémenter une région de comptage de référence
au lieu de copier la région vers un nouvel emplacement physique dans la mémoire,
processus.
ID
numéro de l'enfant à la processus parent, et un0
de la valeur à la processus enfant.Voyons maintenant ce qui se passe dans votre code lorsque vous appelez
fork()
Ligne 01:
fork()
est appelé, processus enfant est créé.fork()
les rendements et la valeur de retour est stockée danspid
.[Note: comme il n'y a pas d'erreur, vérifiez à l'OP du code, il sera discuté plus tard]
Ligne 02:
pid
valeur est comparée à la valeur0
. Notez que cette vérification est effectuée à la fois la processus parent et le nouvellement créé processus enfant. Comme mentionné ci-dessus, la valeur depid
sera0
dans processus enfant, etchild process ID
dans processus parent. Donc, cette condition de vérifier évalue àTrue
dans processus enfant, etFalse
dans processus parent. Donc lignes 03-07 sont exécutées dans le processus enfant.Ligne 03-07: Ces lignes sont assez directe. Le
num[]
tableau de la processus enfant est changé (nums[i] *= -i;
), et est imprimé à l'aide deprintf("CHILD: %d ",nums[i]);
.La chose à noter ici est que les valeurs qui sont en cours d'impression sont de la
num[]
tableau de la processus enfant. Lenum[]
tableau de la processus parent est jusqu'à présent qu'elle était avant.Il y a un truc intéressant en cause ici appelé copy-on-write. Bien qu'il n'est pas demandé dans cette question, encore être une lecture intéressante.
Ligne 08: Cette ligne est maintenant cochée dans la processus parent. Il ne sera pas de vérification de l' processus enfant que la précédente
if
a été un succès. Un ID de processus est toujours un nombre positif, alors quand processus parent eu l'ID de processus de l'enfant nouvellement créé processus, il sera toujours passer le testelse if (pid > 0)
, et entrez dans le bloc.[Note: Il ne peut jamais être
0
parce que0
réservés. Lire ici.]Ligne 09: Cette ligne rend le processus parent attendre jusqu'à ce que le processus enfant a terminé son exécution. C'est la raison pour laquelle vous allez en voir de toutes les
printf()
de processus enfant avant tout de laprintf()
de la processus parent.Ligne 10-12: C'est aussi une jolie avant
for
boucle, qui imprime la valeur denum[]
tableau. Notez que les valeurs sont inchangées pour le processus parent. Comme il a été changé par le processus enfant précédemment, qui possède sa propre copie de la matricenum[]
.Quand
fork()
échoue.Il y a une possibilité que
fork()
appel peut échouer. Dans un tel cas, la valeur de retour est-1
. Cela devrait également être pris en charge par le programme pour être bon.Certains contenus du livre La Conception du Système d'Exploitation UNIX.
OriginalL'auteur Haris
Dans les cas les plus simples, le comportement de
fork()
est très simple — si c'est un peu hallucinant sur votre première rencontre avec elle. Elle renvoie soit une fois avec une erreur, ou qu'elle renvoie à deux reprises, une fois dans l'original (parent), et une fois dans un tout nouveau presque exacte copie de l'original du processus (le processus de l'enfant). Après le retour, les deux processus sont théoriquement indépendantes, même si elles partagent beaucoup de ressources.Le processus de l'enfant est une copie de la mère. Il a le même ensemble de descripteurs de fichiers ouverts, par exemple; chaque descripteur de fichier N qui a été ouverte dans le parent est ouverte à l'enfant, et ils partagent la même description du fichier ouvert. Cela signifie que si l'un des processus modifie la lire ou de la position d'écriture dans un fichier, qui affecte également les autres processus. D'autre part, si l'un des processus de fermeture d'un fichier, qui n'a pas d'effet direct sur le fichier dans l'autre processus.
Cela signifie également que si il y avait des données stockées dans les e/S standard dans le package du processus parent (par exemple, certaines données ont été lues à partir de l'entrée standard descripteur de fichier (
STDIN_FILENO
) dans le tampon de données pourstdin
, alors que les données sont disponibles à la fois pour le parent et l'enfant, et les deux peuvent lire que les données mises en mémoire tampon, sans affecter les autres, ce qui permettra également de voir les mêmes données. D'autre part, une fois que le tampon de données est en lecture, si le parent qui lit un autre tampon plein, qui déplace la position courante dans le fichier pour à la fois le parent et l'enfant, de sorte que l'enfant ne puis voir les données que le parent viens de lire (mais si l'enfant lit un bloc de données, le parent de ne pas le voir). Cela peut être source de confusion. Par conséquent, il est généralement une bonne idée de faire en sorte qu'il n'y a pas dans l'attente d'e/S standard avant de bifurquer —fflush(0)
est une façon de le faire.Dans le fragment de code,
assert(original == getppid() || getppid() == 1);
la possibilité que par le temps que l'enfant exécute l'instruction, le processus parent peut avoir quitté, dans ce cas, l'enfant aura été transmise par un système de processus — qui normalement a le PID 1 (je ne connais pas POSIX système où les orphelins, les enfants sont héritées par un PID différente, mais il y a probablement un).D'autres ressources communes, telles que des fichiers mappés en mémoire ou de la mémoire partagée, continuent à être disponibles dans les deux. Le comportement ultérieur d'un fichier mappé en mémoire dépend des options utilisées pour créer le mapping; MAP_PRIVATE signifie que les deux processus indépendants des copies des données, et MAP_SHARED signifie qu'ils partagent la même copie des données et les modifications apportées par un processus sera visible dans l'autre.
Cependant, pas tous les programmes qui fourche est un simple que l'histoire décrite jusqu'à présent. Par exemple, le processus parent peut avoir acquis quelques (conseils) de serrures; ces verrous ne sont pas héritées par l'enfant. Le parent peut avoir été multi-threaded; l'enfant a un seul thread d'exécution — et il y a des contraintes sur ce que l'enfant peut le faire en toute sécurité.
La spécification POSIX pour
fork()
indique les différences dans le détail:La plupart de ces problèmes n'affectent pas la plupart des programmes, mais des programmes multi-thread qui fourche devez être très prudent. Il vaut la peine de lire la section "Justification" de POSIX définition de
fork()
.À l'intérieur du noyau, le système gère toutes les questions mises en évidence dans la définition ci-dessus. Page de la mémoire des tables de correspondance doivent être répliquées. Le noyau est généralement la marque de l' (écriture) des pages de mémoire comme la VACHE — copie sur écriture, de sorte que jusqu'à ce que l'un ou l'autre processus modifie la mémoire, ils peuvent accéder à la même mémoire. Cela permet de minimiser le coût de la réplication du processus; mémoire page ne sont que des faits distincts, alors qu'ils sont modifiés. De nombreuses ressources, tels que les descripteurs de fichiers, doivent être répliquées, donc
fork()
est tout à fait une opération coûteuse (mais pas aussi cher que leexec*()
fonctions). Notez que la reproduction d'un fichier descripteur de feuilles à la fois les descripteurs se référant à la même description du fichier ouvert — voir leopen()
etdup2()
appels système pour une discussion de la distinction entre les descripteurs de fichier et ouvrir le fichier description.OriginalL'auteur Jonathan Leffler