进程控制——进程终止/程序替换详解

   ●进程终止

一、进程退出场景

1.代码运行完毕,结果正确。

2.代码运行完毕,结果不正确。

3.代码异常终止。

二、进程常见退出方法

  ●正常终止(可以通过 echo $? 查看进程退出码):

1.调用_exit函数

#include <unistd.h>
void _exit(int status);
参数:status 定义了进程的终止状态,父进程通过wait来获取该值

注意:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值是255。

2.调用exit函数

#include <unistd.h>
void exit(int status);

exit最后也会调用exit, 但在调用exit之前,还做了其他工作:
1. 执行用户通过 atexit或on_exit定义的清理函数。
2. 关闭所有打开的流,所有的缓存数据均被写入。
3. 调用_exit。

举例:

int main()
{
 printf("hello");
 _exit(0);
}
什么也不输出

int main()
{
 printf("hello");
 exit(0);
}
输出hello

3.调用return

        return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做exit的参数。

  ●异常退出:

ctrl + c,信号终止

  ●进程程序替换

一、程序替换的原理

1.用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)

2.子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替

换,从新程序的启动例程开始执行。

3.调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

4.把即将运行的程序加载到内存中,那么页表映射的代码段就被改了。

5.调用exec成功没有返回值,失败返回-1。

       调用exec成功,则当前进程的代码和数据已经被替换,以前的堆和栈已经被销毁,返回值也保存在栈中,栈已经被销毁,则返回值不存在。

二、exec系列替换函数

1.六个替换函数

#include<unistd.h>

int execl(const char* path,const char* arg,...);  //后面以NULL结束
int execlp(const char* file,const char* arg,...);
int execle(const char* path,const char* grg,...,char* const  envp[]);
int execv(const char* path,const char* argv);  //argv数组以NULL结束
int execvp(const char* file,const char* argv);
int execve(const char* path,const char* argv,char* const envp[]);  //envp数组以NULL结束

    事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve。

2.函数解释

path:表示对应的文件在哪个目录下(要执行的程序是哪一个)

file:只用填文件名,系统会在PATH下找 

envp[]:表示自己设置的,替换后的程序的环境变量 

l(list):表示参数采用列表形式 

v(vector):参数采用数组形式 

p(path):有p自动搜索环境变量PATH 

e(envp):表示自己设置环境变量(设置的环境变量是什么,则最新程序的环境变量就是什么)

3.使用

1>int execl(const char* path,const char* arg,...)

示例一:

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

int main()
{
    execl("/bin/pwd","pwd",NULL);
    return 0;
}

功能:让进程执行pwd命令。

示例二:

hello.c
int main()
{
    printf("hello\n");
    return 0;
}
exec.c
int main()
{
    execl("./hello","./hello",NULL);
    return 0;
}

功能:让进程执行hello进程

2>int execlp(const char* file,const char* arg,...)

int main()
{
    execlp("ls","ls","-l",NULL);                                                                                                                   
    return 0;
}

3>int execle(const char* path,const char* grg,...,char* const envp[])

hello.c
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 int main()
  5 {
  6     printf("houcong=%s\n",getenv("houcong"));
  7     printf("hello world\n");
  8     return 0;
  9 }
exec.c
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6     char* envp[] = {"houcong=0630",NULL};
  7     execle("./hello","./hello",NULL,envp);
  8     return 0;
  9 }

4>int execv(const char* path,const char* argv)

int main()
{
    char* argv[] = {"ls","-l",NULL};                                                                                                               
    execv("/bin/ls",argv);
    return 0;
}

5>int execvp(const char* file,const char* argv)

#include<stdio.h>
#include<unistd.h>
int main()
{
    char* argv[] = {"ls","-l",NULL};
    execvp("ls",argv);                                                                                                                             
}

功能:让进程执行ls -l命令

6>int execve(const char* path,const char* argv,char* const envp[])

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6     char* argv[] = {"./hello",NULL};
  7     char* envp[] = {"houcong=222",NULL};
  8     execve("./hello",argv,envp);
  9     return 0;
 10 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值