嵌入式学习——进线程(进程的回收和替换)——day25

1. 进程消亡

1.1 僵尸进程

        进程代码执行结束,空间没有被回收

        当子进程(child process)先于父进程(parent process)退出,但是父进程没有调用wait/waitpid回收子进程的资源,则子进程变成僵尸进程。

1.2 如何避免产生僵尸进程

        1.让父进程先结束,子进程会成为孤儿进程,被系统进程收养,子进程结束系统进程
          回收子进程空间
        2.子进程结束,父进程回收子进程空间,即可避免产生僵尸进程

2. 进程空间回收函数

2.1 wait(阻塞回收)

        1. 定义

               pid_t wait(int *wstatus);

        2. 功能

                阻塞回收子进程空间(随机回收)

        3. 参数

                wstatus:存放子进程结束状态空间首地址

        4. 返回值

                成功返回回收到的子进程的PID
                失败返回-1 

        5. 注意

                wait具有阻塞功能


                WIFEXITED(wstatus)——1正常退出、0异常退出
                检测子进程是否正常退出
                
                WEXITSTATUS(wstatus)——返回子进程的ID号
                检测子进程退出的值
        
                WIFSIGNALED(wstatus)——1子进程被信号杀死、0子进程没被信号杀死
                检测子进程是否被信号杀死
        
                WTERMSIG(wstatus)——返回杀死进程的信号数
                检测子进程被几号信号杀死

        6. 示例程序

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

int main(int argc, char *argv[])
{
    pid_t ret = fork();

    if (ret > 0)
    {
        printf("this father proc pid : %d ppid : %d\n", getpid(), getppid());

        int status;
        pid_t recycleid = wait(&status);
        
        if (WIFEXITED(status))
        {
            printf("terminated normally, exit is %d\n", WEXITSTATUS(status));
        }
        else if (WIFSIGNALED(status))
        {
            printf("terminated by a signal, signal num is %d\n", WTERMSIG(status));
        }

        printf("wait recycle id %d\n", recycleid);
    }
    else if (0 == ret)
    {
        printf("this child proc pid : %d  ppid : %d\n", getpid(), getppid());
        sleep(10);
        exit(50);
    }
    else 
    {
        perror("fork error");
        return -1;
    }

    return 0;
}

2.2 waitpid(非阻塞回收)

        1. 定义

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

        2. 功能

                回收子进程空间 (指定)

        3. 参数

            pid:
                -1          回收任意一个子进程空间
                >0        回收和传入PID值相同的子进程空间
            wstatus:
                存放子进程结束状态空间首地址 
            options:
                WNOHANG        非阻塞回收(子进程没有退出不会阻塞等待)
                0                          阻塞回收

        4. 返回值

            成功返回回收到的子进程的PID
            失败返回-1 
            如果WNOHANG被设置,且没有子进程结束返回0 

        5. 示例程序

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

int main(int argc, char *argv[])
{
    pid_t ret = fork();

    if(ret > 0)
    {
        printf("this father proc pid : %d  ppid : %d\n", getpid(), getppid());

        int status; 
        while(1)
        {
            pid_t recycleid = waitpid(ret ,&status,WNOHANG);
            if(recycleid == ret)
            {
                if(WIFEXITED(status))
                {
                    printf("terminated normally ,exit is %d\n",WEXITSTATUS(status));
                }
                else if (WIFSIGNALED(status))
                {

                    printf("terminated by a signal,signal num is %d\n",WTERMSIG(status));
                }
                printf("wait recycle id %d\n",recycleid);

                break;
            }
            else 
            {
                printf("非阻塞,子进程未结束\n");
            }
            usleep(1000*500);
        }
    }
    else if(0 == ret)
    {
        printf("this child proc pid:%d ppid:%d\n",getpid(),getppid());
        sleep(10);
        exit(50);
    }
    else 
    {
        perror("fork error");
        return -1;
    }

    return 0;
}

3. exec函数族

        利用进程空间执行另一段代码

        用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建
新进程,所以调用exec前后该进程的id并未改变。

3.1  execl

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

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

int main(int argc, char *argv[])
{
    // ls -l -a  
    execl("/bin/ls", "ls", "-l", "-a", NULL);
    printf("看见就错了\n");

    return 0;
}

3.2  execlp

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

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

int main(int argc, char *argv[])
{
    // ls -l -a  
    //echo $PATH 
    execlp("ls", "ls", "-l", "-a", "-h", "--color=auto", NULL);
    printf("看见就错了\n");

    return 0;
}

3.3  execle

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

3.4  execv

             int execv(const char *path, char *const argv[]);

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

int main(int argc, char *argv[])
{
    // ls -l -a  
    char *const arg[] ={"ls", "-l", "-a", "-h", "--color=auto", NULL};
    execv("/bin/ls", arg);
    printf("看见就错了\n");

    return 0;
}

3.5  execvp

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

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

int main(int argc, char *argv[])
{
    // ls -l -a  
    char *const arg[] ={"ls", "-l", "-a", "-h", "--color=auto", NULL};
    execvp(arg[0], arg);
    printf("看见就错了\n");

    return 0;
}

3.6  execvpe

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

      l:执行另一段代码参数以列表形式传递
      v:执行另一段代码参数以指针数组形式传递
      p:执行另一段代码文件在系统环境变量PATH对应的路径下查找
      e:执行另一段代码,更新环境变量

    4.getenv
      char *getenv(const char *name);
      功能:
        获得环境变量name对应的数值
      参数:
        name:环境变量名
      返回值:
        成功返回环境变量的值
        失败返回NULL
    
    5.setenv
      int setenv(const char *name, const char *value, int overwrite);
      功能:
        添加或者修改环境变量的值
      参数:
        name:环境变量名 
        value:环境变量的值
        overwrite:是否覆盖(非0会覆盖)
      返回值:
        成功返回0 
        失败返回-1 
        
    6.system
      int system(const char *command);
      功能:
        加载一条shell命令
      参数:
        command:shell命令字符串空间首地址
      返回值:
        成功返回执行命令的结果
        失败返回-1 

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值