5 Estudio preliminar del proceso de Linux


Prefacio (incluido el índice)


Creación de procesos simples

/**
 * @author IYATT-yx
 * @brief 创建进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    
    
    // fork创建子进程,子进程的虚拟地址空间和父进程一样(pid不一样)
    // 不可确定父进程和子进程谁先执行
    pid_t pid = fork();
    // 父进程中fork的返回值为子进程的pid
    if (pid > 0)
    {
    
    
        printf("我是父进程,我的pid为: %d ,我的儿子的pid为: %d\n", getpid(), pid);
    }
    // 子进程中fork的返回值为0
    else if (pid == 0)
    {
    
    
        printf("我是子进程,我的pid是: %d ,我父亲的pid是: %d\n", getpid(), getppid());
    }
    else
    {
    
    
        perror("fork");
    }
    
}
/**
 * @author IYATT-yx
 * @brief 创建多进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    
    
    int i;
    for (i = 0; i < 3; ++i)
    {
    
    
        pid_t pid = fork();
        // 防止子进程再创建子进程
        if (pid == 0)
        {
    
    
            break;
        }
    }

    // 每次循环创建一个子进程对应一个循环次数
    if (i == 0)
    {
    
    
        printf("我是子进程1: pid = %d\tppid = %d\n", getpid(), getppid());
    }
    else if (i == 1)
    {
    
    
        printf("我是子进程2: pid = %d\tppid = %d\n", getpid(), getppid());
    }
    else if (i == 2)
    {
    
    
        printf("我是子进程3: pid = %d\tppid = %d\n", getpid(), getppid());
    }
    // 最后一次循环后,再次对i自增,不再满足循环条件,停止创建子进程,此时对应的是父进程
    else if (i == 3)
    {
    
    
    	// 可能出现父进程比子进程先执行完,而终端在父进程结束后可能认为程序结束了,就会切回终端
    	// 然后出现切回终端后继续执行子进程并将要打印输出的内容显示到切回后的命令提示符后
    	// 所以让父进程sleep 1秒,最后执行
    	sleep(1);
        printf("我是父进程: pid = %d\n", getpid());
    }
}

familia de funciones ejecutivas información de función
específica disponible manconsulta de comando

       int execl(const char *pathname, const char *arg, ... (char  *) NULL */);
       int execlp(const char *file, const char *arg, ... (char  *) NULL */);
       int execle(const char *pathname, const char *arg, ... (char *) NULL, char *const envp[] */);
       int execv(const char *pathname, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[], *const envp[]);
  • Reemplace el contenido de .text en el proceso hijo, deje que el proceso padre y el hijo realicen operaciones irrelevantes
  • Llamar a otro programa en un programa
/**
 * @author IYATT-yx
 * @brief exec族函数实践示例
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    
    
    pid_t pid = fork();
    if (pid > 0)
    {
    
    
        sleep(1);
        // 常用于执行系统命令
        execlp("pwd", "", NULL);
        // execlp执行成功,则后面的代码替换掉,不执行
        // 如果执行失败,则继续往下,不需要去判断返回值
        perror("execlp");
        return -1;
    }
    if (pid == 0)
    {
    
    
        // 常用于执行自己的程序,和 execlp 参数差不多
        /**
         * @param 执行程序的绝对路径
         * @param 占位参数任意设定内容
         * @param 指定执行程序的参数
         * @param 以NULL结尾
         */
        execl("/bin/ls", "", "-lh", ".", NULL);
        perror("execl");
        return -1;
    }
}

Reciclaje de procesos

  • Proceso huérfano: el proceso padre ha terminado, mientras que el proceso hijo aún se está ejecutando. El proceso de inicio heredará el proceso padre del proceso hijo (un proceso finaliza para liberar los recursos del sistema que ocupaba, y la PCB del proceso hijo puede solo ser liberado por el proceso padre, por lo que hay un mecanismo para que init tenga éxito en el proceso padre)
  • Proceso zombi: el proceso hijo ha terminado y el proceso padre todavía se está ejecutando, pero el proceso padre no ha liberado el PCB del proceso hijo, este proceso hijo ahora es un proceso zombie.
/**
 * @author IYATT-yx
 * @brief 孤儿进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    
    
    pid_t pid = fork();
    if (pid > 0)
    {
    
    
        printf("我是父进程 pid = %d\n", getpid());
    }
    if (pid == 0)
    {
    
    
        sleep(1);
        printf("我是子进程,原父进程已死,当前父进程 pid = %d\n", getppid());
    }
}

Resultado de la ejecución:
Inserte la descripción de la imagen aquí
mire el proceso con pid 8 es init
Inserte la descripción de la imagen aquí

/**
 * @author IYATT-yx
 * @brief 僵尸进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>

int main(void)
{
    
    
    pid_t pid = fork();
    if (pid > 0)
    {
    
    
        while (true)
        {
    
    
            printf("我是父进程 pid = %d\n", getpid());
            sleep(1);
        }
    }
    else if (pid == 0)
    {
    
    
        printf("我是子进程,父进程的pid = %d\n", getppid());
    }
}

Después de ejecutar este programa, abra otra terminal para consultar el nombre del programa. El primero es el proceso padre en ejecución y el segundo es el proceso hijo muerto (muerto muerto), pero los recursos no se han reciclado (el proceso padre está ocupado , El proceso hijo no se puede reciclar)
Inserte la descripción de la imagen aquí

/**
 * @author IYATT-yx
 * @brief wait回收进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdbool.h>

int main(void)
{
    
    
    pid_t pid = fork();
    if (pid > 0)
    {
    
    
        printf("我是父进程\n");

        int status;
        pid_t wPid = wait(&status);
        // return/exit结束
        // w if exited
        if (WIFEXITED(status))
        {
    
    
            // w exit status
            printf("exit code: %d\n", WEXITSTATUS(status));
        }
        // kill信号终止
        // w if signaled
        else if (WIFSIGNALED(status))
        {
    
    
            // w term sig
            printf("signal: %d\n", WTERMSIG(status));
        }
        printf("父: pid = %d,回收进程的pid = %d\n", getpid(), wPid);
        
    }
    else if (pid == 0)
    {
    
    
        // // 测试使用 kill 命令杀死进程
        // while (true)
        // {
    
    
        //     printf("子: pid = %d\tppid = %d\n", getpid(), getppid());
        //     sleep(1);
        // }

        sleep(3);
        printf("子: pid = %d\tppid = %d\n", getpid(), getppid());
        exit(66);
    }
}

Use waitel proceso de niño reciclado, una recuperación solo se puede llamar una vez, y no se puede especificar el proceso de recuperación de un niño, la muerte de uno solo puede recuperar un. Espere bloqueando el camino, hemos estado esperando que el niño muera, mientras el niño muriera, se recuperó de inmediato.

/**
 * @author IYATT-yx
 * @brief waitpid回收进程
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdbool.h>

int main(void)
{
    
    
    pid_t pid = fork();
    if (pid > 0)
    {
    
    
        printf("我是父进程\n");

        int status;
        /**
         * @brief 
         *       返回值:
         *              > 0: 被回收进程的pid
         *              -1: 无子进程
         *              == 0: 第三个参数为 WNOHANG, 且子进程正在运行
         * @param . 要回收的进程的pid
         * @param . 回收进程的结束方式
         * @param . 设置为0则阻塞, WNOHANG就是非阻塞
         */ 
        pid_t wPid = waitpid(pid, &status, 0);
        // return/exit结束
        // w if exited
        if (WIFEXITED(status))
        {
    
    
            // w exit status
            printf("exit code: %d\n", WEXITSTATUS(status));
        }
        // kill信号终止
        // w if signaled
        else if (WIFSIGNALED(status))
        {
    
    
            // w term sig
            printf("signal: %d\n", WTERMSIG(status));
        }
        printf("父: pid = %d,回收进程的pid = %d\n", getpid(), wPid);
        
    }
    else if (pid == 0)
    {
    
    
        // // 测试使用 kill 命令杀死进程
        // while (true)
        // {
    
    
        //     printf("子: pid = %d\tppid = %d\n", getpid(), getppid());
        //     sleep(1);
        // }

        sleep(3);
        printf("子: pid = %d\tppid = %d\n", getpid(), getppid());
        exit(66);
    }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45579994/article/details/112777564
Recomendado
Clasificación