communication interprocessus (IPC)
Avant cela, nous devons comprendre la raison pour laquelle le système d'exploitation pour assurer une communication inter-processus pour les utilisateurs?
Pour les marrons, pourquoi nous pouvons être très lisse et connecter avec d'autres personnes? R: Parce que l'air est un écart moyen du son. Eh bien, vous pouvez regarder l'analogie entre processus d'indépendance, qui fonctionne son propre espace d'adressage virtuel, il ne peut pas communiquer directement avec d'autres processus. S'il n'y a pas les médias publics entre deux entités indépendantes, ils ne communiquent pas, le système d'exploitation est de fournir un tel milieu public.
Scénario de communication: transfert de données, le partage des données, le contrôle des données de
communication entre les processus Il existe quatre: tuyaux, mémoire partagée, les files d' attente de messages, les sémaphores
1, le tuyau
conduit est essentiellement un tampon de noyau, via plusieurs processus accédant à la même pièce un tampon pour la communication.
pipes Catégorie: tuyaux anonymes et les pipes nommés
(1) de tuyau anonyme
a les appels système de processus dans le noyau crée un pipeline, et l'appel retourne une poignée pour faire fonctionner le gazoduc, ce pipeline il n'y a pas d' autre identifiant, il ne peut y accéder par la poignée de commande. Par conséquent, seuls les tuyaux anonymes pour la communication interprocessus, qui sont liées, parce que la seule copie du parent par l'enfant avec un moyen d'obtenir une poignée pour faire fonctionner le pipeline, puis accéder au même tampon. Et assurez - vous de créer un processus enfant créé avant.
poignées de pipeline Opération: deux descripteurs de fichiers.
La question est, pourquoi avoir deux? En fait, ce pipeline avec notre vie de tous les jours un peu comme, en un. Cependant, nous sous Linux un conduit pour la lecture des données, une pour l' écriture des données.
Fonction: tube int (int pipefd [2
]) -----> int pipefd [2] tuyau (pipefd) signifie qu'il y a un tableau de type int deux éléments, alors la première adresse du col de la matrice dans, à travers le pipefd de retour deux poignées de fonctionnement. Où:
pipefd [0] - est utilisé pour lire pipeline de données
pipefd [1] - pour l' écriture de données au pipeline
Valeur de retour: renvoie 0, -1 échec
Exemple:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int pid=0;
int pipefd[2];
int ret=pipe(pipefd); //创建管道应该在创建子进程之前
if(ret<0)
{
perror("pipe error\n");
return -1;
}
pid=fork(); //创建进程
if(pid==0) //子进程读数据
{
char buf[1024]={0};
int ret=read(pipefd[0],buf,1023);
if(ret<0)
{
perror("read error\n");
return -1;
}
printf("child read data:[%s]\n",buf);
}
else //父进程写数据
{
char *ptr="cold day";
int ret=write(pipefd[1],ptr,strlen(ptr));
if(ret<0)
{
perror("write error\n");
return -1;
}
}
}
Le résultat:
vous pouvez le voir, l'enfant et le processus parent lire les données écrire les données sont cohérentes.
** 1) ** Si vous laissez le processus parent que le sommeil (5)? Qu'est - ce qui se passe alors? En fait, cela signifie que le pipeline serait pas de données parce que cinq secondes avant le début, le processus parent n'a pas produit de données, l'enfant lu quand il bloquera jusqu'à ce qu'il y a des données
** 2) ** Lorsque le pipeline est rempli de données, écriture continuer à blocs de données d'écriture jusqu'à ce que les données sont lues
dans la figure ci - dessous, nous laissons le sommeil de l' enfant 5 secondes
if(pid==0) //子进程读数据
{
sleep(5);
char buf[1024]={0};
........
Laissez le processus parent aux données d'écriture, et calcule la somme de la longueur des données
else //父进程写数据
{
int pipe_size=0; //定义起始数据长度为0
while(1)
{
char *ptr="cold day";
int ret=write(pipefd[1],ptr,strlen(ptr));
if(ret<0)
{
perror("write error\n");
return -1;
}
}
pipe_size+=ret; //写入的数据长度总和
printf("write data:%d\n",pipe_size); //打印总共写了多少
}
Le programme fonctionne, l'enfant dormira cinq premières secondes, puis le processus parent écriture de données, tranche de temps après, l'enfant se réveille, puis a commencé à lire les données, regardons les résultats (aucun contrôle sur le format de sortie est bien ici, pardonnez - moi):
résultats confirme aussi notre conjecture, parent 65536 a écrit, quand l'enfant commence à lire.
** 3) ** Si toute la fin d'écriture du tube est fermé, puis lire les données après la lecture ne bloquent pas le pipeline, mais renvoie 0 (renvoie 0, indiquant personne à écrire, continuer à lire les mots qui ont pas de sens)
* * 4) ** Si toute la fin de lecture du tube est fermé, lorsque les données d'écriture sont écrites, il déclenche une exception, les sorties de processus
comme le montre , nous avons fermé la fin de lecture du processus parent, le processus se ferme inopinément.
5 **) ** lu lorsque le pipeline, si la taille des données d'écriture ne dépasse pas PIPE_BUF = 4096 taille, l'opération atomique peut être garantie.
Ce sont les cinq caractéristiques dont nous parlons au sujet du pipeline.
Mutuellement exclusif: Un seul peut effectuer flux de données des ressources critiques des opérations pour atteindre la sécurité des données opérationnelles, assurer le fonctionnement en toute sécurité des données de
synchronisation: Arrêt par moment, pour obtenir l' accès aux ressources de la rationalité de synchronisation de la rue
(2) nom pipeline
canaux nommés: un tampon de noyau a un identificateur de pièce qui se trouve dans une canalisation du système de fichiers
caractéristiques: tout procédé peut être utilisé sur la même communication inter-hôte
Remarque: si le canal nommé à lecture seule ouverture il bloque jusqu'à ce que le fichier de pipeline par d' autres processus pour écrire la voie ouverte
si le canal nommé à écrire seule façon ouverte bloquera jusqu'à ce que le fichier de pipeline par d' autres processus pour lire la voie ouverte
fonction: int mkfifo (const char chemin * , le mode mode_t )
chemin: pipeline chemin d'accès en
mode: fichier pipeline autorisation d' exploitation
valeur de retour: le retour réussi 0, -1 échec
suivant démo montre le fonctionnement de base des canaux nommés:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errono.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
char *file="./test.fifo";
int ret=mkfifo(file,0664); //创建一个管道
if(ret<0)
{
if(errno!=EEXIST) //说明是其他方面的报错
{
perror("mkfifo error");
return -1;
}
}
int fd=open(file,O_RDWR); //以可读可写方式打开这个文件
if(fd<0)
{
perror("open error");
return -1;
}
printf("open success\n");
return 0;
}
Lorsque nous compilons le code est compilé avec succès trouvé
2, la mémoire partagée
Mémoire partagée: le partage des données entre l' utilisation et processus
caractéristiques: communication inter-processus plus rapide
pour atteindre les principes:
1) d'ouvrir un espace dans la mémoire physique, cet espace est dans le noyau a identifié
2) cet espace par la page pour cartographier leur espace d'adressage virtuel des
opérations 3) réalisées par l'adresse de mémoire virtuelle
4) supprime l'association entre
5) effacer la mémoire partagée
- Par rapport à une autre mémoire partagée communication inter-processus, dans le processus de communication, les données sont copiées deux fois moins mode utilisateur et le mode noyau, et est donc le plus rapide.
Tailler une mémoire: int shmget (clé key_t, la taille size_t, int shmflag)
- Paramètre Description:
clé: l' identification de la mémoire partagée dans le noyau, et d' autres processus ouvrent la même mémoire par le même logo
taille: la taille de la mémoire partagée
shmflg: IPC_CREAT | IPC_EXCL | Mode drapeau
Valeur de retour: le retour réussi de la poignée de commande partagée défaillance de la mémoire retourner -1;
Établir le mappage: void la shmat (int shmid, const void shmaddr, int shmflg)
Paramètres:
shmid: poignée de fonctionnement
par shmaddr: cartographie de la première adresse
shmflg: Opération
Valeur de retour: renvoie le premier succès de mappage d'adresses, l' échec -1
shmdt (shm_start), la relation de mappage, faisant allusion à la première adresse peut être placé
shmctl (shmid, IPC_RMID, NULL); supprimer la mémoire partagée
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#define IPC_KEY 0x12345678
#define SHM_SIZE 4096
int main()
{
int shmid=shmget(IPC_KEY,SHM_SIZE,IPC_CREAT|664); //创建一个共享内存
if(shmid<0){
perror("shmget error");
return -1;
}
void *shm_start=shmat(shmid,NULL,0);
if(shm_start==(void*)-1)
{
perror("start error");
return -1;
}
int i=0;
while(1)
{
sprintf(shm_start,"%s-%d\n","good day",i++);//格式化字符串放到buff里面
sleep(1);
}
shmdt(shm_start); //解除映射关系,放入影射首地址就可以
shmctl(shmid,IPC_RMID,NULL); //删除共享内存
return 0;
}
3, la file d'attente de messages
-
Action: une transmission de bloc de données entre les processus
-
Essence: file d'attente de priorité noyau, une pluralité de processus en plaçant un noeud de file d'attente pour une file d'attente ou d'obtenir le même noeud communiquer
-
Le principe
(1) créer une file d' attente dans le noyau
(2) l' addition d' un noeud à la queue
(3) obtenir à partir du noeud file d' attente
(4) supprimer la file d' attente de messages -
Caractéristiques:
(1) portant une synchronisation de file d'attente de messages et de l' exclusion mutuelle: Si la file d' attente a pas de données, le récepteur est bloqué, si la file d' attente est pleine, les données sont ensuite obstruction également ajouté
(2) présente un type de bloc de données de transmission de
données (3) ne soit pas adhérences
file d' attente de messages a été éliminé
4, le sémaphore
- Sémaphore: la synchronisation et de l' exclusion mutuelle entre les processus d'
exclusion mutuelle: un seul processus accès aux ressources critiques peut en même temps, le fonctionnement en toute sécurité des données - accès aux données de sécurité de
synchronisation: à en juger par un certain nombre de conditions doivent obtenir des ressources critiques le caractère raisonnable de l' accès aux données - afin d'accès - Essence: + est un compteur file d'attente, mais seulement 0/1 contre deux états
- réalisation
- Exclusif: le montant de l' accès par l'état actuel d'un marqueur d'état des ressources critiques, ce qui marque le premier jugement avant l'accès aux ressources critiques, si l'état est accessible, ce statut sera modifié comme inaccessible, et d'accéder aux données, l' accès sera terminée avant état révisé pour être accessible. Mettre en œuvre un compteur de seulement 0/1
- Synchronisation: via un compteur pour compter le nombre de ressources, lorsque vous souhaitez obtenir des ressources critiques, d' abord déterminer le nombre, si les ressources sont accessibles, et si oui, comptez-1, pour obtenir une ressource à exploiter, si aucune ressource (c. -à- est compteur <= 0), puis attend jusqu'à ce que les autres données de production de processus comptent + 1, puis se réveillent processus en attente. Une détermination est obtenue en comptant la fonction réveil et attente
- Les primitives de PV
- opérations p: détermination du nombre, alors -1 si aucune ressource est attendu
- v Fonctionnement: 1 impair, le processus de réveil est en attente dans la file d'attente
résumé
L'auteur de la communication entre les processus de la première consolidation ici, suivi sera révisé pour continuer d'ajouter insuffisante, s'il vous plaît également préoccupé par le signal de suivi Linux-