Threads vs Processus dans Linux
J'ai récemment entendu quelques personnes dire que sous Linux, il est presque toujours préférable d'utiliser des processus au lieu de threads, étant donné que Linux est très efficace dans le traitement des processus, et parce qu'il ya tellement de nombreux problèmes (tels que le verrouillage) associés avec les threads. Cependant, je me méfie, car il semble que les threads pourrait donner un assez gros gain de performances dans certaines situations.
Donc ma question est, lorsqu'ils sont confrontés à une situation que les threads et les processus pourrait à la fois gérer assez bien, dois-je utiliser des threads ou processus? Par exemple, si j'avais écrit un serveur web dois-je utiliser des threads ou processus (ou une combinaison)?
- Est-il une différence avec Linux 2.4?
- La différence entre les processus et les threads sous Linux 2.4, c'est que les threads partagent plusieurs parties de leur état (espace d'adressage, les descripteurs de fichiers, etc) que sur les processus, qui n'est généralement pas le cas. La NPTL sous Linux 2.6, en fait un peu plus clair, en leur donnant "thread groupes" qui sont un peu comme des "processus" dans win32 et Solaris.
- Oui, NPTL est agréable: il fait des choses comme tuer, exec, etc. travailler comme vous pouvez vous attendre dans un programme multi-threadé (l'ancien LinuxThreads comportements de sens compte tenu de la mise en œuvre, mais ont été dégueulasse). Otoh, que d'un "groupe de thread" est juste une collection de "fils", et ne prennent pas vraiment de ressources lui-même, c'est donc un ton plus léger qu'un NT ou Solaris processus.
- httpd.apache.org/docs/2.0/mod/worker.html est la valeur par défaut pour le serveur web apache. son multi processus multi-thread de configuration.
- La programmation simultanée est difficile. Sauf si vous avez besoin de très haute performance, l'aspect le plus important dans votre compromis sera souvent le difficulté de débogage. Processus pour le beaucoup plus facile de solution à cet égard, parce que toute communication est explicite (facile à vérifier, journal, etc.). En revanche, la mémoire partagée threads crée des gazillions de lieux où un thread peut, à tort, de l'impact de l'autre.
- La programmation simultanée peut être multi-thread ainsi que multi-processus. Je ne vois pas pourquoi vous êtes en supposant que la programmation simultanée est multithread seulement. Il pourrait être en raison de certaines limitations de langue, mais en général, il peut être les deux.
- Je lien Lutz est simplement indiqué que la programmation simultanée est difficile, selon ce qui est choisi processus ou threads - mais que, parallèlement à la programmation à l'aide de processus facilite le débogage dans de nombreux cas.
Vous devez vous connecter pour publier un commentaire.
Linux utilise un 1-1 modèle de thread, avec (pour le noyau) pas de distinction entre les processus et les threads -- tout est simplement une tâche exécutable. *
Sur Linux, le système d'appel
clone
clones d'une tâche, avec une configurables niveau de partage qui sont, entre autres:CLONE_FILES
: partager le même fichier descripteur de table (au lieu de créer une copie)CLONE_PARENT
: ne pas configurer une relation parent-enfant entre à la tâche de nouveau et de l'ancien (sinon, l'enfantgetppid()
= parentgetpid()
)CLONE_VM
: partager le même espace mémoire (au lieu de créer un VACHE copie)fork()
appelsclone(
moins de partage)
etpthread_create()
appelsclone(
de partage plus)
. **fork
ing coûte un tout petit peu plus depthread_create
ing en raison de la copie de tables et création de VACHE mappages de la mémoire, mais les développeurs du noyau Linux ont essayé (et réussi) à minimiser les coûts.De commutation entre les tâches, si elles partagent le même espace mémoire et divers tableaux, sera un tout petit peu moins cher que si ils ne sont pas partagés, car les données peuvent déjà être chargées dans le cache. Cependant, les tâches de commutation est toujours très rapide, même si rien n'est partagé -- c'est autre chose que les développeurs du noyau Linux essayer de faire en sorte (et de réussir à assurer).
En fait, si vous êtes sur un système multi-processeur, pas partage de l'information peut être bénéfique à la performance: si la tâche est en cours d'exécution sur un processeur différent, la synchronisation de la mémoire partagée est cher.
* Simplifié.
CLONE_THREAD
causes des signaux de livraison à usage en commun (qui doitCLONE_SIGHAND
, qui partage le gestionnaire de signal de la table).** Simplifié. Il existe deux
SYS_fork
etSYS_clone
syscalls, mais dans le noyau, lesys_fork
etsys_clone
sont à la fois très mince wrappers autour de la mêmedo_fork
fonction, qui elle-même est une fine enveloppecopy_process
. Oui, les termesprocess
,thread
, ettask
sont plutôt utilisés de façon interchangeable dans le noyau Linux...socket
,bind
,listen
,fork
, puis ont de multiples processusaccept
connexions sur le même socket d'écoute. Un processus peut cesser d'accepter si elle est occupée, et le noyau de la route les connexions entrantes vers un autre processus (si personne n'est à l'écoute, noyau de la file d'attente ou à la baisse, en fonction delisten
carnet de commandes). Vous n'avez pas beaucoup plus de contrôle sur la répartition du travail que cela, mais généralement c'est assez bon!clone()
déterminer les ressources sont partagées. Une tâche peut égalementunshare()
ressources à tout autre point dans le temps.task_struct
pour chaque tâche. Ceci est souvent appelé un "processus" dans tout le code du noyau, mais il correspond à chaque exécutable fil. Il n'y a pas deprocess_struct
; si un groupe detask_struct
s sont liés par leurthread_group
liste, alors qu'ils sont de la même "processus" à l'espace utilisateur. Il y a un peu de manutention spéciale de "thread"s, par exemple, tous les, de frère, de fils sont arrêtés sur fork et exec, et seul le "principal" fil s'affiche dansls /proc
. Chaque fil est accessible via/proc/pid
cependant, si elle n'est répertorié dans/proc
ou pas.clone(CLONE_THREAD | CLONE_VM | CLONE_SIGHAND))
vous donnerait un nouveau "thread" qui ne partagent pas le répertoire de travail, des fichiers ou des serrures, tandis queclone(CLONE_FILES | CLONE_FS | CLONE_IO)
serait de vous donner un "processus" qui ne. Le système sous-jacent crée des tâches par clonage;fork()
etpthread_create()
sont juste des fonctions de la bibliothèque qui l'invoque,clone()
différemment (comme je l'ai écrit dans cette réponse).Linux (et Unix) vous donne une troisième option.
Option 1 - processus de
Créer un exécutable autonome qui gère une partie (ou de la totalité) de votre application, et de l'invoquer séparément pour chaque processus, par exemple, le programme exécute des copies de lui-même à déléguer des tâches.
Option 2 - fils
Créer un exécutable autonome qui démarre avec un seul fil, et créer des threads supplémentaires pour certaines tâches
Option 3 - fourche
Uniquement disponible sous Linux/Unix, c'est un peu différent. Un fork du processus est vraiment son propre processus avec son propre espace d'adressage - il n'y a rien que l'enfant peut faire (normalement) pour affecter l'un de ses parents ou les frères et sœurs de l'espace d'adresse (contrairement à un fil) - de sorte que vous obtenez une plus grande robustesse.
Cependant, les pages de mémoire ne sont pas copiés, ils sont de copie sur écriture, donc moins de mémoire est généralement utilisé que vous pourriez imaginer.
Envisager un programme de serveur web qui se compose de deux étapes:
Si vous avez utilisé les threads, l'étape 1 serait fait une fois, et l'étape 2 fait dans plusieurs threads. Si vous avez utilisé "traditionnel", les processus, les étapes 1 et 2 devront être répétées pour chaque processus, et de la mémoire pour stocker la configuration de l'exécution et des données dupliquées. Si vous avez utilisé fork(), alors vous pouvez faire l'étape 1 une fois, et puis fork(), laissant les données d'exécution et de configuration en mémoire, intacte et non copié.
Donc il y a vraiment trois choix.
Qui dépend de beaucoup de facteurs. Les processus sont plus lourdes que les threads, et ont un meilleur démarrage et d'arrêt de coût. Communication interprocessus (IPC) est également plus difficile et plus lente que interthread communication.
À l'inverse, les processus sont plus sécuritaires que les threads, car chaque processus s'exécute dans son propre espace d'adressage virtuel. Si un processus tombe en panne ou a un dépassement de tampon, il n'affecte pas les autres processus à tous, alors que si un thread se bloque, il prend toutes les autres threads du processus, et si un thread a un dépassement de tampon, il ouvre un trou de sécurité dans tous les threads.
Donc, si votre application, les modules peuvent fonctionner essentiellement de façon autonome avec peu de communication, vous devriez probablement utiliser des processus si vous pouvez vous permettre le démarrage et l'arrêt des coûts. L'impact sur les performances de l'IPC sera minime, et vous serez légèrement plus sûr contre les bugs et failles de sécurité. Si vous avez besoin de tous les bits de l'exécution, vous pouvez obtenir ou ont un grand nombre de données partagées (comme les structures de données complexes), aller avec les threads.
D'autres ont discuté de la des considérations.
Peut-être la différence importante est que, dans les processus Windows sont lourdes et coûteuses par rapport aux threads, et dans Linux, la différence est beaucoup plus petit, donc l'équation soldes à un point différent.
Une fois, il y a Unix et dans ce bon vieux Unix il y avait beaucoup de frais généraux pour les processus, de sorte à ce que certains gens intelligents n'était de créer des threads, qui permettrait de partager le même espace d'adressage avec le processus parent et ils ont seulement besoin d'une réduction de changement de contexte, ce qui rendrait le changement de contexte plus efficace.
Dans un style contemporain de Linux (2.6.x) il n'y a pas beaucoup de différence de performances entre un changement de contexte d'un processus par rapport à un fil (uniquement la MMU les trucs supplémentaires pour la discussion).
Là est le problème avec l'espace d'adressage partagé, ce qui signifie qu'un mauvais pointeur dans un thread peut corrompre la mémoire du processus parent ou un autre thread dans le même espace d'adressage.
Un processus est protégé par la MMU, donc un mauvais pointeur va juste provoquer un signal de 11 et de la corruption.
En général je dirais utilisation des processus (pas beaucoup de changement de contexte généraux dans Linux, mais la protection de la mémoire en raison de MMU), mais pthreads si j'aurais besoin d'un temps réel planificateur de classe, ce qui est une autre tasse de thé tous ensemble.
Pourquoi pensez-vous que les fils sont un aussi gros gain de performance sur Linux? Avez-vous des données pour cela, ou est-ce qu'un mythe?
Comment étroitement couplées sont vos tâches?
Si ils peuvent vivre de façon indépendante les uns des autres, puis d'utiliser les processus. Si ils comptent les uns sur les autres, puis utiliser des threads. De cette façon, vous pouvez arrêter et redémarrer un mauvais processus sans interférer avec le fonctionnement des autres tâches.
Pour compliquer encore les choses, il ya une telle chose comme fil de stockage local, et Unix mémoire partagée.
Thread-local de stockage permet à chaque thread d'avoir une instance distincte des objets globaux. La seule fois où je l'ai utilisé c'était lors de la construction d'un environnement d'émulation sous linux/windows, pour le code de l'application qui a couru dans un RTOS. Dans le RTOS chaque tâche a été un processus avec son propre espace d'adressage, dans l'environnement d'émulation, chaque tâche a un thread (avec un espace d'adressage partagé). À l'aide de TLS pour des choses comme des singletons, nous avons été en mesure d'avoir une instance distincte pour chaque thread, juste comme dans le "vrai" système d'exploitation temps réel de l'environnement.
De la mémoire partagée peut (évidemment), de vous donner les avantages de performance d'avoir plusieurs processus d'accès à la mémoire, mais le rapport coût/risque d'avoir à synchroniser les processus correctement. Une façon de le faire est d'avoir un processus de créer une structure de données dans la mémoire partagée, et ensuite envoyer une poignée pour que la structure via traditionnels de communication inter-processus (comme un tube nommé).
Je dois d'accord avec ce que vous avez entendu. Lorsque nous comparons notre cluster (
xhpl
et par exemple), nous avons toujours obtenir de bien meilleures performances, avec des procédés plus de threads.</anecdote>
La décision entre thread/processus dépend un peu de ce que vous allez être l'utilisant pour.
L'un des avantage de ce processus est qu'il a un PID et peut être tué sans résiliation de la mère.
Pour un exemple réel d'un serveur web, apache 1.3 utilisé pour prendre en charge uniquement les processus multiples, mais en 2.0 ils ont ajouté une abstraction de sorte que vous pouvez swtch entre les deux. Commentaires semble pour d'accord que les processus sont plus robustes, mais les threads peuvent donner un peu de meilleures performances (à l'exception de windows, où les performances pour les processus suce et que vous souhaitez uniquement utiliser des threads).
Dans mon travail récent avec LINUX, c'est une chose d'être conscient de est les bibliothèques. Si vous êtes à l'aide de threads assurez-vous que toutes les bibliothèques que vous pouvez utiliser dans les threads sont thread-safe. Ce qui m'a brûlée, un couple de fois. Notamment libxml2 n'est pas thread-safe hors de la boîte. Il peut être compilé avec "thread-safe" mais ce n'est pas ce que vous obtenez avec aptitude install.
Pour la plupart des cas, je préfère que ce processus sur les threads.
les fils peuvent être utiles lorsque vous avez un de relativement petites tâches (processus généraux >> le temps pris par chacune des tâches de l'unité) et il y a un besoin de mémoire de partage entre eux. Pensez d'un grand tableau.
Aussi (hors-sujet), notez que si votre utilisation de l'UC est à 100% ou presque, il n'y a pas d'avantage de multithreading et de transformation. (en fait, il va s'aggraver)
Fils -- > les Fils de partage d'un espace de mémoire,c'est une abstraction de la CPU,il est léger.
Processus --> Processus ont leur propre espace mémoire,c'est une abstraction d'un ordinateur.
Paralléliser les tâches que vous devez abstrait d'un CPU.
Cependant, les avantages de l'utilisation d'un processus sur un thread est de la sécurité,de la stabilité, tandis qu'un thread utilise moins de mémoire que les processus et offre une moindre latence.
Un exemple en termes de web serait de chrome et firefox.
Dans le cas de Chrome chaque onglet est un nouveau procédé d'où l'utilisation de la mémoire de chrome est plus élevé que firefox ,tandis que la sécurité et la stabilité est mieux que firefox.
La sécurité fournie par google chrome est mieux,puisque chaque onglet est un nouveau processus différents onglet ne peut pas snoop dans l'espace mémoire d'un processus donné.
Je pense que tout le monde a fait un excellent travail pour répondre à votre question. Je suis juste en ajoutant plus d'informations sur fil versus le processus dans Linux afin de clarifier et résumer quelques-uns des réponses précédentes dans le contexte de noyau. Donc, ma réponse est en ce qui concerne le noyau de code spécifique à Linux. Selon Noyau Linux documentation, il n'y a pas de distinction claire entre thread versus le processus, sauf thread utilise partagé l'espace d'adressage virtuel à la différence des processus. A noter aussi, le Noyau Linux utilise le terme "tâche" pour se référer à des processus et des threads en général.
"Il n'y a pas de structures internes, la mise en œuvre de processus ou threads, au lieu de cela il est un struct task_struct qui décrivent un résumé de la planification d'unité de tâche"
Également selon Linus Torvalds, vous ne devriez PAS penser sur les processus plutôt que le fil à tous et parce que c'est trop restrictif et que la seule différence est COE ou le Contexte de l'Exécution en termes de "séparer l'espace d'adressage de la mère" ou de l'espace d'adressage partagé. En fait, il utilise un serveur web exemple de faire de son point de ici (qui recommande fortement la lecture).
Pleine de crédit à le noyau linux documentation
Si vous avez besoin de partager des ressources, vous devriez vraiment utiliser des threads.
Aussi considérer le fait que les changements de contexte entre les threads sont beaucoup moins chers que les changements de contexte entre les processus.
Je ne vois aucune raison d'accéder de manière explicite avec des processus séparés, sauf si vous avez une bonne raison de le faire (la sécurité, la performance éprouvée de tests, etc...)