[Processus] Comprendre le processus et les démonstrations de code associées

Table des matières

0. Aperçu du processus

1. Créer un processus

1.1 Création du processus : fonction fork

1.2 Processus en attente : wait(), waitpid()

1.3 Processus spéciaux : processus zombies, processus orphelins, processus démons

1.4 Fin du processus : fonctions exit et _exit

1.5 Nettoyage de sortie de processus : fonction atexit

1.6 Création de processus : fonction vfork

2. Remplacement de processus : famille de fonctions d'exécution

3. fonction du système :

Résumer:


0. Aperçu du processus

définition du processus

La différence entre programme et processus :

  •         Programme : Il s’agit d’un fichier statique exécutable stocké sur le disque.
  •         Processus : il est dynamique et constitue une instance d'exécution d'un programme exécuté en mémoire.
  •         Un programme est une collection ordonnée d'instructions et un processus est le processus d'exécution d'un programme. Un processus est un processus d'exécution d'un programme.
  •         L'état d'un processus change, y compris sa création, sa planification et sa mort.
  •         Tant que le programme est en cours d'exécution, c'est un processus. Si le programme n'est pas exécuté une seule fois, un processus sera créé.

Dans les systèmes Linux, les processus constituent l'unité de base pour la gestion des transactions.

Un processus possède son propre environnement de traitement indépendant et ses propres ressources système (processeur, mémoire, périphériques d'E/S, données, programmes).

Statut du processus et transitions :

Le cycle de vie complet d’un processus peut être simplement divisé en trois états :

État prêt :

        Le processus dispose de toutes les conditions d'exécution et attend que le temps de traitement CPU soit alloué.

Statut d'exécution :

        Le processus utilise du processeur pour s'exécuter.

État d'attente :

        État dans lequel un processus est temporairement incapable de poursuivre son exécution car il ne remplit pas certaines conditions d'exécution.

Mécanisme de planification des processus :

        Rotation des tranches de temps, changement de contexte.

        Le multitraitement ne signifie pas qu'un processus est exécuté puis un autre processus est exécuté, mais qu'il est exécuté alternativement. Un processus est exécuté pendant une période de temps, puis le processus suivant est exécuté pendant une période de temps, et ainsi activé. Une fois tous les processus exécutés, il revient au premier processus. Continuer l'exécution, et ainsi de suite.

La relation de transition entre les trois états du processus :

 Bloc de contrôle de processus :

        Le bloc de contrôle de processus est une structure utilisée pour sauvegarder les informations d'un processus, également appelée PCB.

        Le système d’exploitation contrôle et gère les processus exécutés simultanément basés sur PCB. Lorsque le système crée un processus, il ouvre un espace mémoire pour stocker la structure de données PCB liée à ce processus.

        PCB est la structure de données de type enregistrement la plus importante du système d'exploitation. PCB enregistre toutes les informations nécessaires pour décrire la progression du processus et contrôler le fonctionnement du processus.

        PCB est le seul signe de l'existence d'un processus. Sous Linux, PCB est stocké dans la structure task_struct.

        /usr/src/linux-heads....generic/include/linux/sched.h

Une partie des données dans la structure PCB :

Données de planification :

        Statut du processus, indicateurs, priorités, stratégies de planification, etc.

Données temporelles :

        L'heure à laquelle le processus a été créé, la durée d'exécution en mode utilisateur, la durée d'exécution en mode noyau, etc.

Données du système de fichiers :

        masque umask, table de descripteurs de fichiers, etc.

Données de mémoire, contexte de processus, identification du processus (numéro de processus)

。 。 。

Contrôle de processus:

Numéro de processus :

        Chaque processus est identifié par un numéro de processus, son type est pid_t et la plage du numéro de processus : 0-32767.

        Les ID de processus sont toujours uniques, mais ils peuvent être réutilisés. Lorsqu'un processus se termine, son ID de processus peut être à nouveau utilisé.

Affichez tous les processus ouverts dans le système actuel dans Ubuntu :

ps ajx

PPID : ID de processus du processus parent du processus actuel.

PID : numéro de processus du processus en cours.

PGID : ID de groupe de processus du groupe où se trouve le processus actuel.

COMMANDE : Le nom du processus en cours

Numéro de processus spécial :

  •         Dans les systèmes Linux, les numéros de processus commencent à 0.
  •         Les processus portant les numéros de processus 0 et 1 sont créés par le noyau.
  •         Le processus portant le numéro de processus 0 est généralement un processus de planification et est souvent appelé échangeur.
  •         Le processus portant le numéro de processus 1 est généralement le processus d'initialisation, et le processus d'initialisation est l'ancêtre de tous les processus.
  •         À l'exception du processus de planification, tous les processus sous Linux sont créés directement ou indirectement par le processus init.

ID de processus (PID)

        Entier non négatif identifiant le processus.

ID de processus parent (PPID)

        Tout processus (à l'exception du processus Init) est créé par un autre processus. Ce processus est appelé processus parent du processus créé et le numéro de processus correspondant est appelé ID de processus parent (PPID).

Numéro de groupe de processus (PGID)

        Un groupe de processus est un ensemble d'un ou plusieurs processus. Ils sont liés les uns aux autres. Le groupe de processus peut recevoir différents signaux du même terminal. Le processus associé possède un numéro de groupe de processus (PGID).

Le système d'exploitation Linux propose trois fonctions pour obtenir l'ID du processus : getpid(), getpgid() et getppid().

#include<sys/types.h>

#include<unistd.h>

pid_t getpid(void);

Fonction : Obtenez le numéro de processus du processus en cours.

pid_t getppid(void);

Fonction : Obtenez le numéro de processus du processus parent du processus actuel.

pid_t getpgid(pid_t pid);

Fonction : Obtenez le numéro de processus du groupe de processus où se trouve le processus actuel.

Exemple de code :

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
    printf("pid = %d\n", getpid());
    printf("ppid = %d\n", getppid());
    printf("pgid = %d\n", getpgid(getpid()));
    while (1);
    return 0;
}

Capture d'écran d'exécution :

1. Créer un processus

1.1 Création du processus : fonction fork

fonction de la fourchette :

#include<unistd.h>

fourchette pid_t (vide);

Fonction : Créer un processus enfant basé sur un processus existant.

paramètre:

        aucun

valeur de retour :

        succès:

                >0 : Le numéro de processus du processus enfant, identifiant la zone de code du processus parent.

              ==0 : Zone de code du processus enfant.

        échouer:

                -1 : Retour au processus parent, le processus enfant ne sera pas créé.

        Le processus enfant obtenu à l'aide de la fonction fork est une copie du processus parent et hérite de l'intégralité de l'espace d'adressage du processus du processus parent.

Espace d'adressage :

        Y compris le contexte du processus, la pile de processus, les descripteurs de fichiers ouverts, les paramètres de contrôle des signaux, la priorité du processus, le numéro de groupe de processus, etc. La seule chose unique au processus enfant est son numéro de processus, sa minuterie, etc. Par conséquent, le coût d’utilisation de la fonction fork est très élevé. 

Le diagramme spatial des processus parent et enfant après l'exécution de la fonction fork :

Créer un processus enfant

Ne pas faire de distinction entre les processus parent et enfant (non recommandé)

Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    //通过fork函数创建一个子进程
    //注意:只要执行了一次fork,就会在原有的进程基础上创建一个新的子进程
    //而且如果fork之后不区分父子进程的代码区,则后面的所有代码都会执行
    fork();
    printf("hadj{\n");
    while (1);
    return 0;
}

Capture d'écran d'exécution :

Distinguer les processus parent et enfant (recommandé)

Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>


int main()
{
    //父子进程是来回交替执行的,谁先谁后不一定。
    pid_t pid;
    pid = fork();
    if (pid < 0)    //创建子进程失败
    {
        perror("fail to fork");
        exit(1);
    }
    else if (pid > 0)   //父进程代码区
    {
        while (1)
        {
            printf("in parent process\n");
            sleep(1);
        }
    }
    else   //子进程代码区(pid == 0)
    {
        while (1)
        {
            printf("in son process\n");
            sleep(1);
        }
    }
    return 0;
}

Capture d'écran d'exécution :

Le processus parent dispose d'un espace d'adressage indépendant,

Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int a = 555;

int main()
{
    pid_t pid;
    pid = fork();
    static int  b = 777;
    int c = 888;
    //子进程会复制父进程fork之前的所有内容
    if (pid < 0)
    {
        perror("fail to fork");
        exit(1);
    }
    else if (pid > 0)
    {
        printf("in partent process\n");
        a++;
        b++;
        c++;
        printf("a = %d, b = %d, c = %d\n", a, b, c);
    }
    else
    {
        sleep(1);
        printf("in son process\n");
        printf("a = %d, b = %d, c = %d\n", a, b, c);
    }
    while (1);

    return 0;
}

Capture d'écran d'exécution :

 Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


int main()
{

    int fd;
    if ((fd = open("file.txt", O_RDONLY)) == -1)
    {
        perror("fail to open");
        exit(1);
    }
    //子进程会继承父进程的一些共有的区域,例如磁盘空间,内核空间。
    //文件描述符的偏移量保存在内核空间中,所以父进程改变偏移量,子进程获取的偏移量是改变之后的。
    pid_t pid;
    pid = fork();

    if (pid < 0)
    {
        perror("fail to fork");
        exit(1);
    }
    else if (pid > 0)
    {
        printf("in parent process\n");
        char  buf[32] = "";
        if (read(fd, buf, 30) == -1)
        {
            perror("fail to read");
            exit(1);
        }
        printf("buf = [%s]\n", buf);
    }
    else
    {
        sleep(1);
        printf("in son process\n");

        char buf[32] = "";
        if (read(fd, buf, 30) == -1)
        {
            perror("fail to read");
            exit(1);
        }
        printf("buf = [%s]\n", buf);

    }
    while (1);
    return 0;
}

Capture d'écran d'exécution :

Le processus enfant hérite de l'espace du processus parent

Suspension du processus :

Lorsqu’un processus n’effectue aucune action pendant un certain temps, on parle de blocage du processus.

#include<unistd.h>

unsigned int sleep(non signé en secondes) ;

Fonction:

        Le processus est suspendu pendant le nombre de secondes spécifié et n'est relâché que lorsque le temps spécifié s'est écoulé ou qu'un signal est reçu.

valeur de retour :

        Si le processus est suspendu pendant la durée spécifiée par sec, 0 est renvoyé, et si le processus est interrompu, les secondes restantes sont renvoyées.

Avis:

        Une fois le processus suspendu pendant le nombre de secondes spécifié, le programme ne sera pas exécuté immédiatement. Le système fera simplement passer le processus à l'état prêt.

Exemple de code :

#include<unistd.h>
#include<stdio.h>

int main()
{
        while(1)
        {
                printf("hello world\n");
                sleep(2);
        }
        return 0;
}

Capture d'écran d'exécution :

 

1.2 Processus en attente : wait(), waitpid()

Les processus parent-enfant nécessitent parfois une simple synchronisation inter-processus, comme le processus parent attendant la fin du processus enfant.

Linux propose deux fonctions d'attente, wait() et waitpid().

fonction d'attente

#include<sys/types.h>

#include<sys/wait.h>

pid_t attendre(int *status);

Fonction:

        Attendez que le processus enfant se termine. Si le processus enfant se termine, cette fonction récupérera les ressources du processus enfant.

        Le processus appelant la fonction d'attente est suspendu jusqu'à ce que l'un de ses processus enfants se termine ou reçoive un signal qui ne peut être ignoré.

        Si le processus appelant n'a pas de processus enfants ou si ses processus enfants sont terminés, cette fonction est renvoyée immédiatement.

paramètre:

        status : lorsque la fonction est renvoyée, le paramètre status contient les informations d'état à la fin du processus enfant.

                        Les informations de sortie du processus enfant contiennent plusieurs champs dans un int.

                        Chaque champ peut être supprimé à l'aide de la définition d'une macro.

                        Le processus enfant peut envoyer l'état de sortie via la fonction exit ou _exit.

                        Voici quelques macros couramment utilisées :

                                WIFEXITED(status): Vérifiez si le processus enfant se termine normalement.

         WEXITSTATUS(status): Obtenez la valeur de l'état de sortie du processus enfant.

         WIFSIGNALED(status): Vérifie si le processus enfant s'est terminé en raison de la réception d'un signal.

         WTERMSIG(status): Obtenez le numéro de signal qui a provoqué la fin du processus enfant.

valeur de retour :

        Succès : numéro de processus du processus enfant.

        Échec : -1

Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>


int main()
{
    pid_t pid;
    pid = fork();

    if (pid < 0)
    {
        perror("fail to fork");
        exit(1);
    }
    if (pid > 0)
    {
        //不接收子进程的退出状态
       // wait(NULL);
        //接收子进程退出状态,子进程中必须用exit或_exit函数退出进程时发送退出状态
        int status = 0;
        wait(&status);
        if (WIFEXITED(status) != 0)
        {
            printf("son process return status:%d\n", WEXITSTATUS(status));
        }
        printf("in pratent proces\n");

    }
    else
    {
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            printf("in son process\n");
            sleep(1);
        }
        exit(4);
    }
    return 0;
}

Capture d'écran d'exécution :

fonction waitpid

#include<sys/types.h>

#include<sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);

Fonction:

        Attendez que le processus enfant se termine. Si le processus enfant se termine, cette fonction récupérera les ressources du processus enfant.

paramètre:

        pid : le processus ou le groupe de processus spécifié.

                pid>0 : Attendez le processus enfant dont l'ID de processus est égal au PID

                pid+0 : attend tout processus enfant dans le même groupe de processus. Si le processus enfant a rejoint un autre groupe de processus, waitpid ne l'attendra pas.

                pid=-1 : Attendre tout processus enfant. À ce stade, waitpid et wait ont le même effet.

                pid<-1 : Attendre tout processus enfant dans le groupe de processus spécifié. L'ID de ce groupe de processus enfant est égal à la valeur absolue de pid.

        status : enregistre les informations d’état à la fin du processus enfant.

        options: options

                0 : identique à attendre, bloquer le processus parent et attendre la fin du processus enfant.

                WNOHANG : si aucun processus enfant n'est terminé, revenez immédiatement.

                WUNTRACED : si le processus enfant est suspendu, cette fonction revient immédiatement et ignore l'état final du processus enfant. (débogage de trace, rarement utilisé)

valeur de retour :

        Succès : renvoie l'ID du processus enfant dont le statut a changé ; si l'option WNOHANG est définie et que le processus spécifié par pid existe, 0 est renvoyé.

        Échec : renvoie -1. Lorsque le processus enfant indiqué par pid n'existe pas, ou que le processus existe mais n'est pas un processus enfant du processus appelant, waitpid renvoie une erreur et errno est défini sur ECHILD.

attendre (statut) <==> waitpid (-1, statut, 0)

Exemple de code :

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<wait.h>


int main()
{

    pid_t pid;
    pid = fork();
    if (pid < 0)
    {
        perror("fail to fork");
        exit(1);
    }
    else if (pid > 0)
    {
        waitpid(pid, NULL, 0);
        printf("in father process\n");
    }
    else
    {
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            printf("in son  process\n");
            sleep(1);
        }
    }
    return 0;
}

 Capture d'écran d'exécution :

1.3 Processus spéciaux : processus zombies, processus orphelins, processus démons

  • Processus Zombie (Processus Zombie) Le processus a terminé son exécution, mais les ressources occupées par le processus n'ont pas été recyclées. Un tel processus est appelé processus zombie. Le processus enfant est terminé et le processus parent n'a pas appelé la fonction wait ou waitpid pour recycler les ressources du processus enfant. C'est la raison pour laquelle le processus enfant devient un processus zombie.
  • Processus orphelin : le processus parent se termine mais le processus enfant ne se termine pas.
  • Processus démon (Processus démon) Le processus démon est un processus orphelin spécial. Ce processus est séparé du terminal et s'exécute en arrière-plan.

1.4 Fin du processus : fonctions exit et _exit

fonction de sortie :

#include<stdlib.h>

sortie vide (valeur int)

paramètre:

        status : paramètres renvoyés au processus parent (les 8 bits inférieurs sont valides).

                        Généralement, l’échec est défini sur non 0 et le succès est défini sur 0.

Fonction _exit :

#include void _exit (valeur int)

paramètre:

        status : paramètres renvoyés au processus parent (les 8 bits inférieurs sont valides).

                Généralement, l’échec est défini sur non 0 et le succès est défini sur 0.

La différence entre les fonctions exit et _exit :

  •         Exit est une fonction de bibliothèque et _exit est un appel système.
  •         exit videra le tampon, mais _exit ne videra pas le tampon
  •         Utiliser généralement la sortie

 Exemple de code :

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

void fun()
{
    printf("nihao hangzhou");
    //测试return是带换行\n
   // printf("nihao hangzhou\n");
    
    //主函数中退出进程,子函数中退出当前函数。
    //      return  ;
    //退出一个进程,刷新缓冲区
    //exit(0);  
    //退出一个进程,不刷新缓冲区    
    _exit(0);
    printf("welcoom to binjiang\n");
}
int main()
{
    printf("hello world\n");
    fun();
    printf("hello kitty\n");
    return 0;
}

Capture d'écran d'exécution :

retour de capture d'écran :

quitter la capture d'écran :

 

_sortie capture d'écran :

 

1.5 Nettoyage de sortie de processus : fonction atexit

Le processus peut utiliser la fonction atexit pour enregistrer une fonction de sortie avant de quitter.

#include<stdlib.h>

int atexit(void (*fonction)(void));

Fonction:

        La fonction appelée avant la fin normale du processus d'enregistrement. La fonction d'enregistrement est exécutée à la fin du processus.

paramètre:

        function : L'adresse d'entrée de la fonction à appeler avant la fin du processus.

        La fonction atexit peut être appelée plusieurs fois dans un processus pour enregistrer la fonction de nettoyage. L'ordre d'appel des fonctions avant la fin normale est l'inverse de l'ordre d'enregistrement. 

Exemple de code :

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>


void clear_fun1(void)
{
    printf("perform clear fun1 \n");
}
void clear_fun2(void)
{
    printf("perform clear fun2 \n");
}
void clear_fun3(void)
{
    printf("perform clear fun3 \n");
}
int main()
{
    //atexit在进程结束时才会执行对应的回调函数
    //注意调用顺序是反的
    atexit(clear_fun1);
    atexit(clear_fun2);
    atexit(clear_fun3);
    printf("process exit 3 sec later!!!\n");
    sleep(3);
    return 0;
}

Capture d'écran d'exécution :

1.6 Création de processus : fonction vfork

fonction vfork

#include<sys/types.h>

#include<unistd.h>

pid_t vfork (vide)

Fonction:

        La fonction vfork et la fonction fork créent toutes deux un nouveau processus dans un processus existant, mais les processus enfants qu'elles créent sont différents.

valeur de retour :

        Si le processus enfant est créé avec succès, 0 est renvoyé dans le processus enfant et l'ID du processus enfant est renvoyé dans le processus parent.

        Renvoie -1 en cas d'erreur.

La différence entre les fonctions fork et vfork :

        vfork garantit que le processus enfant s'exécute en premier. Après avoir appelé exec ou exit, le processus parent peut être planifié pour s'exécuter.

        vfork crée un processus enfant comme fork, mais il ne copie pas complètement l'espace d'adressage du processus parent vers le processus enfant, car le processus enfant appellera immédiatement exec (ou quittera), donc l'espace d'adressage ne sera pas accessible.

        Au lieu de cela, avant d'appeler exec ou exit dans le processus enfant, il s'exécute dans l'espace d'adressage du processus parent, et après exec, le processus enfant aura son propre espace de processus.

Le processus enfant s'exécute avant le processus parent

Exemple de code :

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    //使用vfork,子进程会先执行,直到子进程执行exit或exec后,父进程才会执行。
    pid_t pid;
    pid = vfork();
    if (pid < 0)
    {
        perror("fail to  vfork");
        exit(1);
    }
    else if (pid > 0)
    {
        while (1)
        {
            printf("in father process\n");
            sleep(1);
        }
    }
    else
    {
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            printf("in son process\n");
            sleep(1);
        }
        exit(0);
    }
    return 0;
}

Capture d'écran d'exécution :

 Le processus enfant partage un espace avec le processus parent

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int a = 10;
int main()
{
//父子进程共享一个空间
    pid_t pid;
    int b = 9;
    pid = vfork();
    if (pid < 0)
    {
        perror("fail to vfork");
        exit(1);
    }
    else if (pid > 0)
    {
        printf("in father process a = %d b = %d\n", a, b);
    }
    else
    {
        a++;
        b++;
        printf("in son process a = %d b = %d\n", a, b);
        exit(0);
    }
    return 0;
}

 Capture d'écran d'exécution :

2. Remplacement de processus : famille de fonctions d'exécution

La famille de fonctions exec est composée de six fonctions exec

  1. La famille de fonctions exec propose six méthodes pour démarrer un autre processus au sein d'un processus.
  2. La famille de fonctions exec peut rechercher des fichiers exécutables en fonction du nom de fichier ou du nom de répertoire spécifié.
  3. Le processus qui appelle la fonction exec ne crée pas de nouveau processus, donc le numéro de processus du processus ne change pas avant et après l'appel à exec. Le programme qu'il exécute est complètement remplacé par un nouveau programme, et le nouveau programme commence à s'exécuter à partir de son fonction principale.

La famille de fonctions exec remplace le segment de données, le segment de code et le segment de pile du processus appelant.

 #include<unistd.h>

int execl(const char *chemin, const char *arg, .../*(char *) NULL */);

int execlp(const char *fichier, const char *arg, .../* (char *) NULL */);

int execlv(const char *chemin, char *const argv[]);

int execvp(const char *fichier, char *const argv[]);

int execle(const char *path, const char *arg, .../*, (char *) NULL*/, char *const envp[]);

int execvpe(const char *file, char *const argv[], char *const envp[]);

Fonction:

        Exécuter un autre programme dans un processus, principalement utilisé pour exécuter des commandes.

paramètre:

        path : Le chemin de la commande ou du programme.

        l : S'il s'agit d'une fonction avec l, la commande ou le programme correspondant est passé par chaque paramètre, et le dernier est NULL pour indiquer la fin.

                Par exemple : "ls","-l",NULL

        v : S'il s'agit d'une fonction avec v, la commande ou le programme correspondant est passé via un tableau de pointeurs et le dernier élément du tableau de pointeurs se termine par l'indicateur NULL.

                char *str[] = {"ls", "-l", NULL};

        p : S'il s'agit d'une fonction sans p, le premier paramètre doit transmettre le chemin absolu de la commande ou du programme en cours.

              S'il s'agit d'une fonction avec p, le premier paramètre peut être soit un chemin absolu, soit un chemin relatif.

valeur de retour :

        Échec : -1

Exemple de code :

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>


int main()
{
    pid_t pid;
    pid = fork();
    if (pid < 0)
    {
        perror("fail to fork");
        exit(1);
    }
    else if (pid > 0)
    {
        printf("in father process\n");
        wait(NULL);
        printf("the soon process has quied\n");
    }
    else
    {
        printf("in son process\n");
#if 0
        if (execl("/bin/ls", "ls", "-l", NULL) == -1)
        {
            perror("fail to execl");
            exit(1);
        }
#endif
#if 0
        if (execlp("ls", "ls", "-l", NULL) == -1)
        {
            perror("fail to execlp");
            exit(1);
        }
#endif
#if 0
        char* str[] = { "ls", "-l",NULL };
        if (execv("/bin/ls", str) == -1)
        {
            perror("fail to execv");
            exit(1);
        }
#endif
#if 0
        if (execlp("./myshell.sh", "./myshell.sh", NULL) == -1)
        {
            perror("fail to execlp");
            exit(1);
        }
#endif
#if 1
        if (execlp("./myshell.sh", "./myshell.sh", NULL) == -1)
        {
            perror("fail to execlp");
            exit(1);
        }
#endif
#if 0
        if (execlp("./hello", "./hello", NULL) == -1)
        {
            perror("fail to execl");
            exit(1);
        }
#endif
#if 0
        if (execl("./hello", "./hello", NULL) == -1)
        {
            perror("fail to execl");
            exit(1);
        }
#endif

        printf("hello world\n");
    }
    return 0;
}
80, 1          Bot

Après qu'un processus appelle exec, en plus de l'ID de processus, le processus conserve également les caractéristiques suivantes inchangées :

  • Numéro de processus parent
  • numéro de groupe de processus
  • borne de commande
  • Répertoire racine
  • répertoire de travail actuel
  • Jeu de masques de signaux de processus
  • signal non géré
  • .....

3. fonction du système :

#include<stdlib.h>

int système (const char *commande);

Fonction:

        Le système appellera la fonction fork pour générer un processus enfant. Le processus enfant appelle exec pour démarrer /bin/sh -c string pour exécuter la commande représentée par le paramètre string string. Une fois la commande exécutée, elle retourne au processus appelant. .

paramètre:

        La chaîne de la commande à exécuter.

valeur de retour :

        Si la commande est NULL, la fonction system() renvoie non-0, généralement 1.

        System() renvoie 127 s'il échoue lors de l'appel de /bin/sh, et -1 pour d'autres raisons d'échec.

Avis:

        Une fois l'appel système réussi, la valeur de retour après l'exécution de la commande shell sera renvoyée. La valeur de retour peut être 1, 127 ou -1, il est donc préférable de vérifier à nouveau errno pour confirmer que l'exécution a réussi.

Exemple de code :

#include<stdio.h>
#include<stlib.h>

int main()
{
    system("clear");
    system("ls -l");
    system("./hello");
    system(. / myshell.sh");

        return 0;
}

Résumer:

        Ce chapitre présente le concept, la création et l'utilisation des processus. En comprenant les principes fondamentaux de la gestion des processus, nous pouvons mieux utiliser et contrôler les ressources du système, mettre en œuvre des opérations simultanées et créer des applications efficaces. Une compréhension approfondie des concepts et des technologies des processus nous permettra de concevoir des architectures système plus stables et évolutives et de résoudre les problèmes de communication et de synchronisation entre plusieurs processus.

        J'espère que ce blog vous aidera à mieux comprendre et à comprendre l'importance de la gestion des processus de candidature lors du développement d'applications. Merci d'avoir lu!        

Je suppose que tu aimes

Origine blog.csdn.net/crr411422/article/details/131501849
conseillé
Classement