fork函数、进程退出、进程等待(2)

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

return退出


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

回值当做 exit的参数。


进程退出返回值的意义:


return以及exit给与的数据其实就是进程的退出码

 作用: 一个程序运行起来肯定是为了完成一个任务,但是这个任务完成的怎么样外界怎么知道呢?因此就必须有这个进程的退出码,来表示当前进程任务处理的结果。不管是return还是exit,都需要我们给出一个进程的返回值exit(0), return 0;给出的返回值,是进程的返回值因为一个进程就是为了调度运行一个程序, 完成一个任务的(但是任务完成有好有坏),就必须得有一种方式能够告诉我们这个任务完成的怎么样? (返回值的作用)


内存管理方式


分段式内存管理:将一个整体的地址空间划分为多个段(代码段,全局数据段,堆区,共享区,栈区,环境变量,运行参数…)


优势/作用:非更加利于编译器对于地址的管理。

重要的两个要素:段表,地址组成 虚拟地址组成:段号,段内的偏移量

段表:是一种数据结构,其中描述的信息,段号:物理内存的一个起始地址 映射:虚拟地址组成+段表

通过段号找到段表项,得到一块物理内存的起始地址

物理内存起始地址+偏移量就是实际数据存储在物理内存中的位置

image.png分页式内存管理:将一个整体的地址空间划分 为大量的小的分页page (当前一般默认都是4096字节为一页)

作用:实现数据的离散存储,提高内存利用率

段页式内存管理:先将地址空间进行分段,然后在每个分段内使用分页进行管理(集合了分段式和分页式的优势) 映射:虚拟地址组成(页号+页内偏移)

页表(页号+物理块地址+访问权限+缺页中断…)

段页式:先对虚拟地址空间进行分段,在每个段内进行分页管理,集合分段与分页各自的优势进行内存管理

好处:

  1. .每个进程都有一个完整独立的虚拟地址空间,则地址可以随便使用,不用担心冲突(地址管理更加方便)
  2. 进过页表映射可以将数据存储在物理内存的任意位置,实现数据的离散式存储,提高内存利用率
  3. 在进行页表映射的之后可以进行访问权限的控制


进程等待


进程等待必要性


wait方法


#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int*status);

返回值: 成功返回被等待进程pid,失败返回-1。

参数: 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

(子进程没有退出会一直等待,子进程退出会直接退出)

waitpid方法

pid_ t waitpid(pid_t pid, int status, int options);

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

Pid=-1,等待任一个子进程。与wait等效。

Pid>0.等待其进程ID与pid相等的子进程。

status:

WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)

WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)


options:

WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。0是默认阻塞


 故:waipid(-1,&status,0)与wait等价,都是没获取到就堵塞,获取任意一个子进程的返回值

注意:

 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。

 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。

 如果不存在该子进程,则立即出错返回。

image.png

获取子进程status


wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。如果传递NULL,表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位,高16位暂时不关心):

低16位中的高8位保存进程退出码,之后有一个coredump标志位占据一个比特位,coredump文件很大,默认情况下是关闭的。

image.png

注意:通过wait获取的返回值,有多个信息,其中进程的退出码保存到高8位中,并且只用一个字节来保存,即(0~255),多了采取截断、


image.png

因此要获取一一个进程的退出码,首先得确定这个进程是否是正常退出的,如果是,才有意义。


代码中关心的问题:

如何判断进程是否是正常退出:取出status中的低7位; status & 0x7f(就是0111 1111)== 0正常退出,否则异常退出

如何从status中取出退出码:取出status中的低1 6位中的高8位 (status >> 8) & 0xff(1111 1111) 向右移动8位


问:exit()和status是怎么链接上的?

image.png

阻塞等待代码演示


int main()
{
 pid_t pid;
 pid = fork();
 if(pid < 0){
   printf("%s fork error\n",__FUNCTION__);
   return 1;
 } else if( pid == 0 ){ //child
   printf("child is run, pid is : %d\n",getpid());
   sleep(5);
   exit(257);
 } else{
   int status = 0;
   pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5S
   printf("this is test for wait\n");
   if( WIFEXITED(status) && ret == pid ){
 printf("wait child 5s success, child return code is 
:%d.\n",WEXITSTATUS(status));
 }else{
 printf("wait child failed, return.\n");
 return 1;
 }
 }
 return 0;
}
运行结果:
[root@localhost linux]# ./a.out
child is run, pid is : 45110
this is test for wait
wait child 5s success, child return code is :1.

进程的非阻塞等待方式:

#include <stdio.h> 
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
   pid_t pid;
   pid = fork();
   if(pid < 0){
       printf("%s fork error\n",__FUNCTION__);
       return 1;
   }else if( pid == 0 ){ //child
       printf("child is run, pid is : %d\n",getpid());
       sleep(5);
       exit(1);
   } else{
       int status = 0;
       pid_t ret = 0;
       do
       {
           ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待
           if( ret == 0 ){
               printf("child is running\n");
           }
           sleep(1);
       }while(ret == 0);
       if( WIFEXITED(status) && ret == pid ){
           printf("wait child 5s success, child return code is 
:%d.\n",WEXITSTATUS(status));
       }else{
           printf("wait child failed, return.\n");
           return 1;
       }
   }
   return 0;
}


目录
相关文章
|
1月前
|
Linux
【Linux】—— 进程等待 wait&&waitpid
【Linux】—— 进程等待 wait&&waitpid
【Linux】—— 进程等待 wait&&waitpid
|
1月前
|
Linux
进程等待(wait和wait函数)【Linux】
进程等待(wait和wait函数)【Linux】
|
3月前
|
存储 Linux C语言
Linux进程等待
Linux进程等待
|
3天前
|
算法 Linux Shell
【linux进程(二)】如何创建子进程?--fork函数深度剖析
【linux进程(二)】如何创建子进程?--fork函数深度剖析
|
1月前
|
Linux 数据安全/隐私保护
进程间通信之共享内存及其shm函数的使用【Linux】
进程间通信之共享内存及其shm函数的使用【Linux】
|
1月前
|
Java Linux Shell
进程的程序替换(exec函数)【Linux】
进程的程序替换(exec函数)【Linux】
|
3月前
|
Linux Shell Windows
『 Linux 』使用fork函数创建进程与进程状态的查看(上)
『 Linux 』使用fork函数创建进程与进程状态的查看(上)
|
3月前
|
存储 缓存 Unix
C语言第四章(进程间的通信,管道通信,pipe()函数)
C语言第四章(进程间的通信,管道通信,pipe()函数)
56 0
|
3月前
|
存储 Unix C语言
C语言进程(第三章,exec函数族,execl,execlp,execle,execv,execvp,execve)
C语言进程(第三章,exec函数族,execl,execlp,execle,execv,execvp,execve)
29 0
|
3月前
|
监控 Unix Linux
C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())
C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())
46 0

相关实验场景

更多