进程的退出与等待

目录

进程的退出

exit 与_exit 的区别

exit

_exit

总结

进程的等待

wait

waitpid

总结

进程替换

exec函数族


进程的退出

在进程结束时,需要释放分配给进程的地址空间以及内核中产生的各种数据结构

资源的释放需要通过 exit 函数或者 _exit 函数来完成

在程序结束时,会自动调用 exit 函数

exit 与_exit 的区别

exit

函数头文件 #include <stdlib.h>

函数功能
结束进程,并刷新缓冲区

在系统中定义了两个状态值 : EXIT_SUCCESS 正常退出,EXIT_FAILURE 异常退出,具体定义在 stdlib.h 中

#define EXIT_FAILURE   1   /* Failing exit status. */
#define EXIT_SUCCESS   0   /* Successful exit status. */

说说 exit 的特点

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
        pid_t pid = fork();
        if(pid == -1)
       {
                perror("fork");
                exit(EXIT_FAILURE);
       }
        else if(pid==0)
       {
                printf("child process <%d> is running.....\n",getpid());
                sleep(2);
                exit(EXIT_SUCCESS);
                printf("child process <%d> ready to exit.\n",getpid());

       }
        else
       {
                sleep(5);
       }
        return 0;
}

说明exit函数会刷新缓冲区

_exit

 _exit 函数终止进程,但不会刷新缓冲区;

其用法与exit一样

总结

_exit()属于系统调用,能够使进程停止运行,并释放空间以及销毁内核中的各种数据结构
exit()基于_exit()函数实现,属于库函数, 会自动刷新I/O缓冲区

进程的等待

在子进程运行结束后(调用exit或_exit),进程进入僵死状态,并释放资源,子进程在内核中的数据结构依然保留。可以理解为,你把一只螃蟹吃了,还剩下螃蟹壳

父进程调用wait() 与waitpid() 函数等待子进程退出后,释放子进程遗留的资源 (task_struct)

wait

函数头文件
#include <sys/types.h>
#include <sys/wait.h>
函数原型
pid_t wait(int *wstatus);

函数功能
让函数调用者进程进入到睡眠状态,等待子进程进入僵死状态后,释放相关资源并返回
函数参数
wstatus:保存子进程退出状态值变量的指针
*****获取具体值需要使用宏定义*****

返回值:

成功:返回退出子进程的pid
失败:返回-1

int main()
{
        pid_t pid = fork();
        if(pid == -1)
       {
                perror("fork");
                exit(EXIT_FAILURE);
       }
         else if(pid==0)
       {
                printf("child process <%d> is running.....",getpid());
                sleep(2);
                //exit(EXIT_SUCCESS);
                // 自定义状态值
                exit(1000);
       }
        else
       {
                int status = 0;
                pid_t cpid = wait(&status);
                printf("The process <%d> has exit, status code:%d\n",cpid,WEXITSTATUS(status));
       }
        return 0;
}

wait 总结:

会阻塞调用者进程(一般为父进程)
在子进程状态变为僵死态时,回收资源,并释放资源后返回

waitpid

waitpid函数的功能与wait函数一样,但比wait()函数功能更强大,可以理解成 wait() 底层调用waitpid()函

函数头文件
#include <sys/types.h>
#include <sys/wait.h>
函数原型
pid_t waitpid(pid_t pid, int *wstatus, int options);
函数参数
pid:进程id
   -1 可以等待任意子进程
   >0 等待id为pid的进程
wstatus:保存子进程退出状态值的指针
options:选项
   WNOHANG 非阻塞选项
   0   阻塞式与wait等同
函数返回值
成功
   >0   退出进程的pid
   =0   在非阻塞模式下,没有进程退出

失败:
   -1,并设置errno

总结

waitpid使用阻塞的方式等待任意子进程退出 : waitpid(-1,&status,0);

waitpid使用非阻塞的方式等待子进程退出 :while((cpid=waitpid(-1,&status,WNOHANG))==0);

如果不关心状态值,子进程退出状态值的指针为NULL;

wait(NULL);
waitpid(-1,NULL,0);

进程替换

创建一个进程后,pid 以及在内核中的信息保持不变,但进程所执行的代码进行替换。

就理解为在进程里干其他进程的事

应用场景:
Linux 终端应用程序,在执行命令时,通过创建一个进程,然后替换成对应命令的可执行程序,在
执行。

exec函数族

在 Linux 系统中提供了一组用于进程替换的函数,共有6个

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[],char *const envp[]);

path:可执行文件的路径名
file:可执行文件名,可以通过PATH环境变量指定的路径
arg:参数列表,以NULL结尾
argv[]:参数数组
envp[]:环境变量数组

1.execl函数执行 ls -l 命令

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
       int ret;
       ret = execl("/bin/ls","ls","-l",NULL);
       if(ret == -1)
       {
               perror("execl");
               return -1;
       }
       return 0;
}

2.通过 execlp函数执行 ls -l 命令

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
        int ret;
        ret = execlp("ls","ls","-l",NULL);
        if(ret == -1)
       {
                perror("execl");
                return -1;
       }
        printf("process replace.\n");
        return 0;
}

3. 通过 execv函数执行 ls -l 命令

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
        int ret;
        char* params[]={"ls","-l",NULL};
        ret = execv("/bin/ls",params);
        if(ret == -1)
       {
                perror("execl");
                return -1;
       }
        printf("process replace.\n");
        return 0;
}

注意 :如果使用的是可执行文件的名称时,必须是PATH环境变量包含的路径

 4. 通过 exec族函数执行另外一个程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
       int ret;
       char* params[]={"./waitassignment",NULL};
       //第一个参数是 可执行程序的路径 parmas中的"./waitassignment"是执行形式 
       ret = execv("./waitassignment",params);
       if(ret == -1)
       {
               perror("execl");
               return -1;
       }
       printf("process replace.\n");
       return 0;
}

exec函数族 形式差不多,掌握一两个其他都差不多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值