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

来源:互联网 发布:b超数据算胎儿体重公式 编辑:程序博客网 时间:2024/05/18 01:53

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

原创粉丝点击