Linux---进程终止和进程等待

进程终止

进程终止场景

  • 代码运行正常,结果正确
  • 代码运行完毕,运行不正确
  • 代码异常终止

Linux下,我们可以通过echo $?命令查看进程退出状态,命令的实际作用是查看离它最近的一条命令的退出码

#include <stdio.h>                                                                                                                    
int main()
{
    return 1;
}

这里写图片描述

进程常见退出方法

  1. 从main返回
  2. 调用exit
  3. 调用_exit

exit与_exit

_exit原型

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

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

exit原型

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

两者相同点和不同点
这里写图片描述

exit函数做的事情
1.exit会执行用户通过atexit()或on_exit()定义的清理函数,这两个函数也很简单,这里不做赘述
2.关闭所有打开的流,所有的缓存数据均被写入,即清空缓冲区,这个下面有演示
调用exit系统调用(在内核中执行),不同于exit()函数,不要搞混了

如果想深入了解atexit()和on_exit(),请戳这里->atexit和on_exit

代码演示

  #include <stdio.h>
  #include <unistd.h>
  int main()
  {
      printf("hello");
        exit(0);                                                                                                                        
  }

运行结果:
[wh@localhost os_work]$ ./a.out

hello[wh@localhost os_work]$ vim test.c

#include <stdio.h>                                                                                                                    
#include <unistd.h>
int main()
{
    printf("hello");
    _exit(0);
}

运行结果:
[wh@localhost os_work]$ ./a.out

[wh@localhost os_work]$

证明exit清空了缓冲区,而_exit并没有,而是直接释放内存,终止程序。

return 退出

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


进程等待

进程等待必要性

  • 父进程调用wait或waitpid获得子进程退出信息,回收子进程资源,避免资源浪费
  • 如果父进程不等待子进程,也就是子进程退出,父进程对其不管不顾,或者父进程先退出,子进程就会变为僵尸进程,即使是 kill -9 命令也杀不死僵尸进程,造成不必要的资源浪费

wait方法

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
返回值:成功返回子进程pid,失败返回-1。
参数:输出型参数,获取子进程退出状态,不关心则可以设置为NULL

子进程如果没有退出,则父进程会一直阻塞式等待。
而且wait会默认等待任意子进程,这点不同于waitpid,但是waitpid中也可以通过传入参数的不同设置为等待任意子进程

waitpid方法

#include <sys/types.h>
#include <sys/wait.h>

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

返回值:
    当正常返回的时候waitpid返回收集到的子进程的进程ID;
    如果设置了选项`WNOHANG`,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    如果调用中出错,则返回-1,这时error会被设置成相应的值以指示错误所在;

参数:
    pid:
        pid = -1,等待任意一个子进程,与wait等效。
        pid > 0, 等待其进程ID与pid相同的子进程。
    status:
        WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
        WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
    options:
        WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

获取子进程status

  • waitpid和wait都有一个输出型参数status,如果传的是NULL,表示不关心子进程的退出状态
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程
  • status不是一个简单的整形,它其中是用特定的比特位来表示退出信息的,可以当做位图看待(我们这里只研究status地16比特位)

这里写图片描述

测试代码:
#include <stdio.h>                                                                                                                    
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {   
        //子进程
        sleep(50);
        exit(2);
    }   
    //父进程
    int ret,status;
    ret = waitpid(pid,&status,0);
    if(ret > 0 && (status&0x7F) == 0)//正常退出
    {   
        printf("Child exit code:%d\n",(status>>8)&0xFF);//提取子进程退出码
    }else//异常退出
    {   
        printf("Child exit code:%d\n",status&0xFF);
    }   
    return 0;
}

正常退出
这里写图片描述
异常退出(在其他终端通过kill -9 命令杀死该进程)
这里写图片描述

猜你喜欢

转载自blog.csdn.net/it_xiaoye/article/details/80407900