Acerca del control de procesos

control de procesos

proceso de creación

tenedor

//创建子进程

pid_t fork(void);

//成功:父进程返回子进程的PID,子进程返回0;失败:返回-1,设置errno值

imagen-20211124121305683

imagen-20211124121458786

Quien tome la porción de tiempo de la CPU primero ejecuta primero el proceso padre-hijo

Las variables globales no se pueden compartir entre procesos padre e hijo, aunque la dirección impresa es la misma, porque es una dirección virtual

Si el proceso padre-hijo solo lee variables globales, el proceso padre-hijo tiene solo una copia en la memoria, que se comparte

Si algún proceso en el proceso padre-hijo modifica la variable, copiará una copia en la memoria, luego la modificará en la copia y la volverá a asignar después de que se complete la modificación.

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

int main()
{
    
    
    printf("before fork,pid:[%d]\n",getpid());
    //创建子进程
    pid_t pid = fork();

    if(pid<0)
    {
    
    
        perror("fork error");
        return -1;
    }
    else if(pid>0)
    {
    
    
        printf("father:pid==[%d]\n",getpid());
        sleep(1);
    }
    else if(pid==0)
    {
    
    
        printf("child:pid==[%d]\n",getpid());
    }
    printf("after fork,pid:[%d]\n",getpid());
    return 0;
}

imagen-20211124122232021

pd y matar

ps aux | grep "xxx"
ps ajx | grep "xxx"

//-a:(all)当前系统所有用户的进程
//-u:查看进程所有者及其他一些信息
//-x:显示没有控制终端的进程 -- 不能与用户进行交互的进程【输入、输出】
//-j: 列出与作业控制相关的信息

kill -l 
//查看系统有哪些信号

kill -9 pid 
//杀死某个线程

obtener y obtener

//得到当前进程的PID
pid_t getpid(void);

//得到当前进程的父进程的PID
pid_t getppid(void);

Crear n procesos secundarios en un bucle

//循环创建n个子进程
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
    
    
    int i=0;
    for(i=0;i<3;i++)
    {
    
    
        //创建子进程
        pid_t pid = fork();

        if(pid<0)
        {
    
    
          perror("fork error");
          return -1;
        }
        else if(pid>0)
        {
    
    
            printf("father:pid==[%d]\n",getpid());
            sleep(1);
        }
        else if(pid==0)
        {
    
    
            printf("第%d个子进程,child:pid==[%d]\n",i+1,getpid());
            break;
        }
    }

    return 0;
}

imagen-20211124125054216

familia de funciones ejecutivas

A veces es necesario ejecutar otros comandos o aplicaciones definidas por el usuario en un proceso.En este momento, se utilizan las funciones de la familia de funciones exec.

El método de uso es generalmente llamar a la bifurcación en el proceso principal para crear un proceso secundario y luego llamar a la función exec en el proceso secundario.

imagen-20211124131059455

excl

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

//path: 要执行的程序的绝对路径
//变参arg: 要执行的程序的需要的参数
//arg:占位,通常写应用程序的名字
//arg后面的: 命令的参数
//参数写完之后: NULL

//若是成功,则不返回,不会再执行exec函数后面的代码;若是失败,会执行execl后面的代码,可以用perror打印错误原因
//execl函数一般执行自己写的程序

exclp

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

//file: 执行命令的名字, 根据PATH环境变量来搜索该命令
//arg:占位
//arg后面的: 命令的参数
//参数写完之后: NULL
//若是成功,则不返回,不会再执行exec函数后面的代码;若是失败,会执行exec后面的代码,可以用perror打印错误原因
//execlp函数一般是执行系统自带的程序或者是命令
//父子进程间能否共享全局变量
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>

int main()
{
    
    
    //创建一个子进程
    pid_t pid=fork();
    
    if(pid<0)
    {
    
    
        perror("fork error");
        return -1;
    }
    else if(pid>0)
    {
    
    
        printf("father\n");
        sleep(2);
    }
    else if(pid==0)
    {
    
    
        printf("child\n");
        execl("./test","test","hello","dd",NULL);
        perror("execl error");
    }
    return 0;s
}

imagen-20211124132211128

proceso de reciclaje

Cuando un proceso finaliza, el proceso puede reclamar los recursos de su propia área de usuario, pero no puede reclamar los recursos de PCB del espacio del núcleo. Su proceso principal debe llamar a la función de espera o espera para completar el reciclaje del proceso secundario para evitar el desperdicio de los recursos del sistema.

proceso huérfano

Si el proceso principal del proceso secundario ha muerto, pero el proceso secundario aún está vivo, el proceso se convierte en un proceso huérfano.

Para asegurar que cada proceso tenga un proceso padre, el proceso huérfano será adoptado por el proceso init, y el proceso init se convierte en el proceso padre adoptivo del proceso huérfano. Cuando el proceso huérfano sale, el proceso init completa el reciclaje de el proceso huérfano

proceso zombi

Si el proceso secundario está muerto y el proceso principal aún está vivo, pero el proceso principal no llama a la función de espera o espera para completar el reciclaje del proceso secundario, el proceso secundario se convierte en un proceso zombi.

Cómo arreglar procesos zombies

  • Dado que el proceso zombie es un proceso muerto, no se puede matar con el comando matar
  • Los procesos zombis se pueden eliminar matando a su proceso principal. Después de eliminar su proceso principal, el proceso zombie será adoptado por el proceso init, y el proceso init completará el reciclaje del proceso zombie.

Función de recuperación de procesos

esperar

pid_t wait(int *status);
//阻塞并等待子进程退出 
//回收子进程残留资源 
//获取子进程结束状态(退出原因)

//成功:清理掉的子进程ID;失败:-1 (没有子进程)

//status参数:子进程的退出状态 -- 传出参数
//WIFEXITED(status):为非0        → 进程正常结束
//WEXITSTATUS(status):获取进程退出状态 
//WIFSIGNALED(status):为非0 → 进程异常终止
//WTERMSIG(status):取得进程终止的信号编号
//父进程调用wait函数完成对子进程的回收
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/wait.h>

int main()
{
    
    
    pid_t pid=fork();
    
    if(pid<0)
    {
    
    
        perror("fork error");
        return -1;
    }
    else if(pid>0)
    {
    
    
        printf("father:pid=[%d],fpid=[%d]\n",getpid(),getppid());
        int status;
        pid_t wpid=wait(&status);
        printf("wpid==[%d]\n",wpid);
        if(WIFEXITED(status))//正常退出
        {
    
    
            printf("child normal exit,status==[%d]\n",WEXITSTATUS(status));
        }
        else if(WIFSIGNALED(status))//被信号杀死
        {
    
    
            printf("child killed by signal,signo==[%d]\n",WTERMSIG(status));
        }
    }
    else if(pid==0)
    {
    
    
        printf("child:pid=[%d],fpid=[%d]\n",getpid(),getppid());
        sleep(5);
        return 9;
    }

    return 0;
}

imagen-20211124144759568

espera

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

//同wait函数

//pid:
//pid = -1 等待任一子进程。与wait等效
//pid > 0 等待其进程PID与pid相等的子进程。
//pid = 0 等待进程组ID与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程
//pid < -1 等待其组ID等于pid的绝对值的任一子进程。(适用于子进程在其他组的情况)
//status: 子进程的退出状态,用法同wait函数
//options:设置为WNOHANG,函数非阻塞,设置为0,函数阻塞

//函数返回值
//>0:返回回收掉的子进程ID;
//-1:无子进程
//=0:参3为WNOHANG,且子进程正在运行

Supongo que te gusta

Origin blog.csdn.net/blll0/article/details/121527071
Recomendado
Clasificación