Linux进程入门学习(四)-进程启动退出

本文详细介绍了进程的退出与启动方法,包括exit与_exit的区别、system函数的使用及exec函数族的应用示例,帮助读者掌握进程控制的关键技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 进程的退出

exit 函数用于进程退出
头文件:#include <stdlib.h>
函数原型:void exit(int status);
参数:int status:退出状态值(可以任意写,值规定0 以上的正整数)
返回值:无

_exit 函数用于进程退出
头文件:#include <unistd.h>
函数原型:void _exit(int status);

说明:
1. 如果进程正常退出,则status 一般为0;
2. 如果进程异常退出,则status 一般为非0;
3. 标准C库已经定义两个宏提供使用EXIT_SUCCESS 和 EXIT_FAILURE,正常退出exit(EXIT_SUCCESS ),以及异常退出exit(EXIT_FAILURE)。

exit 与_exit 区别
两者的区别主要是体现在处理过程中,如下图所示:
exit,_exit
_exit()函数会直接调用exit 系统调用退出,其间只是清除其使用的内存空间,并销毁其在内核中的各种数据结构。
exit()函数退出时会先自刷新标准IO 总线上残留数据到内核,如果进程注册了“退出处理函”还自动执行这些函数,最后才调用exit 系统调用。
下面用个实例来说明:
代码一:

     1  /*****************************************************************************
     2  * File Name: exit.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 07:37:27 PM PDT
     6  ******************************************************************************/
     7  
     8  #include <stdlib.h>
     9  #include <stdio.h>
    10  #include <unistd.h>
    11  
    12  int main()
    13  {
    14      printf("Using exit..\n");
    15      printf("This is the end.");
    16      exit(0);
    17  }
    18  

运行结果:
exit
代码二:

     1  /*****************************************************************************
     2  * File Name: exit.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 07:37:27 PM PDT
     6  ******************************************************************************/
     7  
     8  #include <stdlib.h>
     9  #include <stdio.h>
    10  #include <unistd.h>
    11  
    12  int main()
    13  {
    14      printf("Using exit..\n");
    15      printf("This is the end.");
    16      _exit(0);
    17  }
    18

运行结果:
_exit

说明:换行符’\n’又刷新缓冲区的作用,所以在第二段代码中,printf(“This is the end.”);没使用’\n’,而且调用_exit结束进程,所以没有打印第二句话。

2. 进程的启动

system 函数用于启动并执行shell 命令
头文件:#include <stdlib.h>
函数原型:int system(const char *command);
返回值:

成功:非0
失败:0

参数列表: const char *command:执行的命令

示例:
     1  /*******************************************************************************
     2  * File Name: system.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 07:59:07 PM PDT
     6  ********************************************************************************/
     7  
     8  #include <stdio.h>
     9  #include <stdlib.h>
    10  #include <unistd.h>
    11  
    12  int main()
    13  {
    14      system("ls -l");
    15      exit(0);
    16  }

运行结果:
system

Exec 函数族
exec 函数族提供了一种在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完之后,原调用进程的内容除了进程号外,其他全部都被替换了。

以下是exec函数族的标准接口
exec
示例1:execl
下面展示子进程被创建出来之后执行的代码,以及如何加载这个指定程序。被子进程加载的示例代码:

     1  /*******************************************************************************
     2  * File Name: child_elf.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 10:18:22 PM PDT
     6  ********************************************************************************/
     7  
     8  #include <stdio.h>
     9  #include <stdlib.h>
    10  #include <unistd.h>
    11  
    12  int main(int argc, char **argv)
    13  {
    14      printf("[pid:%d]:child_elf\n", (int)getpid());
    15      exit(EXIT_SUCCESS);
    16  }
    17  

下面是使用exec 函数簇中的execl 来让子进程加载上述代码的示例:

     1  /*****************************************************************************
     2  * File Name: exec.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 10:22:45 PM PDT
     6  ******************************************************************************/
     7  
     8  #include <stdio.h>
     9  #include <stdlib.h>
    10  #include <unistd.h>
    11  
    12  int main(int argc, char **argv)
    13  {
    14      pid_t pid;
    15      pid = fork();
    16  
    17      /*父进程*/
    18      if(pid > 0)
    19      {
    20          printf("[pid :%d] parent.\n", (int)getpid());
    21          exit(EXIT_SUCCESS);
    22      }
    23      /*子进程*/
    24      if(pid == 0)
    25      {
    26          printf("[pid:%d]child.\n", (int)getpid());
    27          execl("./child_elf", "./child_elf", NULL);
    28  
    29          /*因为执行execl后,.text代码段中的程序代码已被child_elf替代*/
    30          printf("NEVER be printed\n");/*不执行*/
    31          exit(EXIT_SUCCESS);
    32      }
    33  
    34      return 0;
    35  }
    36  

运行结果:
execl
示例2:execv
用一下两行代码代替execl(“./child_elf”, “./child_elf”, NULL);

char *argv[] = {"./child_elf",NULL);
execv("./child_elf",argv);

示例3:execlp
执行linux 命令ls -l

execlp("ls", "ls", "-l", NULL);

示例4:execve

     1  /*******************************************************************************
     2  * File Name: execlp.c
     3  * Author: 谢保成
     4  * E-mail: 2446603068@qq.com
     5  * Create Time: Fri 18 Aug 2017 10:59:34 PM PDT
     6  ********************************************************************************/
     7  
     8  #include <stdio.h>
     9  #include <stdlib.h>
    10  #include <unistd.h>
    11  
    12  int main()
    13  {
    14      char *argv[] = {"ls", "-l", NULL};
    15      char *envp[] = {"PATH=/bin", 0};
    16      execve("/bin/ls", argv, envp);
    17  
    18      return 0;
    19  }
    20  

运行结果:
execve
示例5:execvp

char * argv[] ={ "ls", "-al", 0};
execvp("ls", argv);

注意:
在使用exec 函数族时,一定要加上错误判断语句常见的错误原因有:
1)找不到文件或路径,此时errno 被设置为ENOEN
2)数组argv 和envp 忘记用NULL 结束,此时errno 被设置为EFAULT
3)没有对应可执行文件的运行权限,此时errno 被设置为EACCESS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值