其他分享
首页 > 其他分享> > UC成长之路9

UC成长之路9

作者:互联网

回顾:
UC成长之路1
UC成长之路2
UC成长之路3
UC成长之路4
UC成长之路5
UC成长之路6
UC成长之路7
UC成长之路8

一、遗言函数的注册

#include <stdlib.h>
int on_exit(void (*function)(int , void *), void *arg);
//功能:给进程注册遗言函数
//参数
//function:遗言函数的入口地址
//arg:传递给function函数的第二个参数
//返回值:成功返回0,失败返回非0

eg:

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

//遺言函數
void doit(int status, void* arg)
{
    printf("n=%d\targ=%s\n", status, (char *)arg);
    return;
}
int main(void)
{
    //向進程注冊遺言函數
    on_exit(doit, "hello");
    getchar();
    return 0;
}

在这里插入图片描述
注意: 遗言函数的三个注意点:

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

//遺言函數
void doit(int status, void* arg)
{
    printf("status=%d\targ=%s\n", status, (char *)arg);
    return;
}

void dou(int status, void* arg)
{
    printf("stutus%d\targ=%s\n", status, (char *)arg);
    return;
}

int main(void)
{
    //向進程注冊遺言函數
    on_exit(doit, "hello");
    on_exit(doit, "hello");
    on_exit(dou, "world");
    getchar();
    return 0;
}

在这里插入图片描述

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

//遺言函數
void doit(int status, void* arg)
{
    printf("status=%d\targ=%s\n", status, (char *)arg);
    printf("pid=%d\n", getpid());
    return;
}

void dou(int status, void* arg)
{
    printf("stutus%d\targ=%s\n", status, (char *)arg);
    printf("pid=%d\n", getpid());
    return;
}

int main(void)
{
    //向進程注冊遺言函數
    on_exit(doit, "hello");
    on_exit(dou, "world");
    //on_exit(doit, "hello");
    pid_t pfork = fork();
    if(pfork==-1){
        perror("fork");
        return -1;
    }
    if(pfork==0){
        exit(0);
    }
    else{

    }
    getchar();
    return 0;
}

在这里插入图片描述

二、进程资源的回收

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
//功能:等待子进程的结束,子进程结束以后,回收子进程的资源
//参数
//status:
//1.WIFEXITED(status):检测子进程是否正常终止,正常终止返回真。
//2.WEXITSTATUS(status):在子进程正常终止时使用,即WIFEXITED(status)返回真时使用,检测子进程的退出状态。
//3.WIFSIGNALED(status):如果子进程被信号终止,返回真
//4.WTERMSIG(status):只有在WIFSIGNALED(status)为真时使用,返回终止子进程的信号的编号
//返回值:成功返回终止子进程的pid;错误返回-1

pid_t waitpid(pid_t pid, int *status, int options);
//功能:等待指定子进程的结束,子进程结束以后,回收子进程的资源
//参数
//pid:可以指定具体一个pid
//pid的取值:1)<-1:pid的绝对值是要等待的子进程的组id
//2)-1:等待任意子进程
//3)0:等待子进程,这些进程被等待的子进程的组id和父进程的组id必须一致
//4)>0:等待指定的进程id

//status:和wait()的status一样
//options:1.WNOHANG:如果没有子进程终止,立即返回;2.0为阻塞
//返回值:成功:返回被终止的子进程的pid,如果WNOHANG被指定,没有子进程终止,返回0;错误返回-1

waitpid(-1, &status, 0);
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

int main(void)
{
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        exit(0);//馬上退出
    }   
    else{//父進程執行的代碼
        getchar();
    }   
    return 0;
}

在这里插入图片描述

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

int main(void)
{
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getppid());
        sleep(2);//確保父進程已經終止
        printf("child processing...%d\n", getppid());
    }   
    else{//父進程執行的代碼
        sleep(1);//父進程睡眠1s
    }   
    return 0;
}

在这里插入图片描述
eg: wait.c使用wait(2)

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

int main(void)
{
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1;
    }
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        getchar();
        exit(0);
    }
    else{//父進程執行的代碼
        wait(NULL);
        printf("parent processing...%d\n", getpid());
    }
    return 0;
}

在这里插入图片描述

eg:waitt.c检测子进程终止原因

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

int main(void)
{
    int status;
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1;
    }
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        //getchar();
        exit(0);
    }
    else{//父進程執行的代碼
        wait(&status);//等待子進程終止,將子進程的推出狀態存儲到s變量空間裏
        printf("parent processing...%d\n", getpid());
        //檢測子進程是否正常終止
        if(WIFEXITED(status))
            printf("exit code %d\n", WEXITSTATUS(status));
    }
    return 0;
}

在这里插入图片描述eg:进程被信号终止

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

int main(void)
{
    int status;
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1;
    }
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        getchar();
        exit(0);
    }
    else{//父進程執行的代碼
        wait(&status);//等待子進程終止,將子進程的推出狀態存儲到s變量空間裏
        printf("parent processing...%d\n", getpid());
        //檢測子進程是否正常終止
        if(WIFEXITED(status))
            printf("exit code %d\n", WEXITSTATUS(status));
        //檢測子進程是否被信號終止
        if(WIFSIGNALED(status))
            printf("signal num %d\n", WTERMSIG(status));
    }
    return 0;
}

在这里插入图片描述补充:如何给指定的进程发送信号?
kill -信号编号 pid

eg: waitpid.c举例说明waitpid(2)

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

int main(void)
{
    //int status;
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        getchar();
        exit(0);
    }   
    else{//父進程執行的代碼
        waitpid(-1, NULL, 0);//等價與wait(NULL);
        printf("parent processing...%d\n", getpid());
    }   
    return 0;
}

在这里插入图片描述

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

int main(void)
{
    //int status;
    //創建子進程
    pid_t pid=fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        printf("child processing...%d\n", getpid());
        getchar();
        exit(0);
    }   
    else{//父進程執行的代碼
        int w=waitpid(-1, NULL, WNOHANG);//非阻塞,沒有子進程終止的時候,返回0
        printf("parent processing...%d\n", getpid());
        printf("w=%d\n",w);
    }   
    return 0;
}

在这里插入图片描述

三、更换进程的映像

#include <unistd.h>
int execve(const char *filename, char *const argv[],
                  char *const envp[]);
//功能:执行程序
//参数
//filename:指定了要执行的程序的文件名
//argv:字符串列表,按照惯例,第一个字符串是filename
//envp:通过这个参数给进程传递环境变量。形式是key=value
//返回值:成功不返回;失败返回-1,errno被设置
#include <unistd.h>

extern char **environ;
int execl(const char *path, const char *arg, ...
                       /* (char  *) NULL */);
int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);
int execle(const char *path, const char *arg, ...
                       /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
 int execvpe(const char *file, char *const argv[],
                       char *const envp[]);

执行命令:ps -o pid,ppid,pgrp,session,comm

day09$ps -o pid,ppid,pgrp,session,comm
   PID   PPID   PGRP   SESS COMMAND
  2429   2424   2429   2429 bash
  2914   2429   2914   2429 ps

eg:使用exec家族的函数执行上面的命令ps -o pid,ppid,pgrp,session,comm
execvp.c

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

int main(void)
{
    char *const p_argv[]={"ps", "-o", "pid,ppid,pgrp,session,comm",NULL};

    //創建子進程
    pid_t pid = fork();
    if(pid==-1){
        perror("fork");
        return -1;
    }
    if(pid==0){//子進程執行的代碼
        //使用ps命令的映像替換父進程繼承來的進程映像
        execvp("ps", p_argv);
        //以下代碼只有在上面的execp()函數執行出錯才會執行
        perror("execl");
        exit(1);
    }
    else{//父進程執行的代碼
        wait(NULL);//阻塞等待子進程的結束
    }
    return 0;
}

在这里插入图片描述
execv.c

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

int main(void)
{
    char *const p_argv[]={"ps", "-o", "pid,ppid,pgrp,session,comm",NULL};

    //創建子進程
    pid_t pid = fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        //使用ps命令的映像替換父進程繼承來的進程映像
        //execvp("ps", p_argv);
        execv("/bin/ps", p_argv);
        //以下代碼只有在上面的execp()函數執行出錯才會執行
        perror("execl");
        exit(1);
    }   
    else{//父進程執行的代碼
        wait(NULL);//阻塞等待子進程的結束
    }   
    return 0;
}

在这里插入图片描述
execlp.c

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

int main(void)
{
    //char *const p_argv[]={"ps", "-o", "pid,ppid,pgrp,session,comm",NULL};

    //創建子進程
    pid_t pid = fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        //使用ps命令的映像替換父進程繼承來的進程映像
        execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,comm",NULL);
        //以下代碼只有在上面的execp()函數執行出錯才會執行
        perror("execl");
        exit(1);
    }   
    else{//父進程執行的代碼
        wait(NULL);//阻塞等待子進程的結束
    }   
    return 0;
}

execl.c

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

int main(void)
{
    //char *const p_argv[]={"ps", "-o", "pid,ppid,pgrp,session,comm",NULL};

    //創建子進程
    pid_t pid = fork();
    if(pid==-1){
        perror("fork");
        return -1; 
    }   
    if(pid==0){//子進程執行的代碼
        //使用ps命令的映像替換父進程繼承來的進程映像
        execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,comm",NULL);
        //以下代碼只有在上面的execp()函數執行出錯才會執行
        perror("execl");
        exit(1);
    }   
    else{//父進程執行的代碼
        wait(NULL);//阻塞等待子進程的結束
    }   
    return 0;
}

#include <unistd.h>

int main(void)
{
    execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,comm", NULL);
    return 0;
}

在这里插入图片描述

标签:status,int,之路,pid,成长,进程,include,UC,進程
来源: https://blog.csdn.net/weixin_42284219/article/details/115757752