Linux的学习之路:12、地址空间(续)与进程的创建、终止和等待

简介: Linux的学习之路:12、地址空间(续)与进程的创建、终止和等待

一、地址空间(续)

上篇文章中介绍了地址空间,但是没有说为什么会有地址空间,那么为什为会有地址空间呢?

这里我是总结了三点:

1、凡是非法的访问或者映射,OS都会识别到,并终止你这个进程,那么有效的保护了物理内存吗?

因为地址空间和页表是OS创建并维护的,是不是也就意味着凡是想使用地址空间和页表进行映射,也一定要在OS的监管之下看来进行访问,也便保护了物理内存中的所有的合法数据包括各个进程以及内核相关的有效数据

2、因为有地址空间的存在,因为有页表的映射的存在我们的物理内存中,是哦不是可以对未来的数据进行任意位置的加载呢?

当然可以,物理内存的分配就可以和进程的管理,就可以做到没有关系,内存管理模块和进程管理模块就完成了解耦合,所以我们在c、c++的语言上new、malloc空间的时候,本质上是在哪申请的呢?答案是虚拟空间

这时又出现一个问题如果我申请了物理空间,但是如果我不立马使用,是不是造成空间的浪费?

答案是确实浪费了,因为有地址空间的存在,所以上层申请空间,其实是在地址空间上申请的,物理内存可以甚至一个字节都不给你,而当你真正进行堆物理地址空间的访问的时候,才执行内存相关管理,帮你申请内存,构建页表的映射关系,然后在进行内存访问。

3、因为在物理内存中理论上可以在任意位置加载,那么是不是物理内存中的所有数据和代码是乱序的,但是以为页表的存在,它可以将地址空间上的虚拟地址和物理地址进行映射,那么是不是在进程视角所有内存分布都可以是有序的,地址空间说白了就是OS给进程画的大饼,结合第二条进程要访问物理内存中的数据和代码,可能目前并没有在物理内存中,同样的,也可以让不同的进程映射到不同的物理内存,是不是变得很容易做到,就这样实现了进程的独立性

进程的独立性,可以通过地址空间+页表的方式实现,所以地址空间+页表的存在就可以将内存进行有序化

二、创建

在之前文章中说过fork函数的用法,这里将继续用进程进行讲解。

在fork的使用我知道它是有分流功能的,并且在子进程中更改变量后会,父进程不会更改,在上篇文章说了是因为页表的存在,那么,fork创建子进程,操作系统都做了什么呢?我这里总结了下面六点

1、分配新的内存块和内核数据结构:操作系统首先为子进程分配新的内存块和内核数据结构,这些结构用于存储子进程的相关信息。

2、复制父进程的数据结构:操作系统将父进程的部分数据结构内容拷贝至子进程。这些数据结构包含了进程的状态、环境变量、打开的文件描述符等信息。

3、添加子进程到系统进程列表:操作系统将新创建的子进程添加到系统的进程列表中,以便进行管理和调度。

4、设置子进程的PID:每个进程都有一个唯一的进程标识符(PID)。操作系统为新创建的子进程分配一个唯一的PID。

5、复制父进程的代码和数据:虽然子进程在创建时复制了父进程的数据结构,但通常并不会复制父进程的代码和数据段。相反,子进程和父进程共享相同的代码段,而数据段则采用写时拷贝(Copy-on-Write, COW)技术。这意味着在子进程实际修改数据之前,父子进程共享相同的数据。当子进程尝试修改数据时,操作系统会为该数据创建一份副本,并允许子进程修改其自己的数据副本,而父进程的数据保持不变。

6、返回进程ID:fork函数在父进程中返回新创建的子进程的PID,而在子进程中返回0。这样,通过检查fork的返回值,进程可以判断自己是父进程还是子进程。

所以fork创建子进程后,系统是不是又多了一个进程,这个肯定是的,进程=内核数据结构+进程代码和数据,这个数据一般是从磁盘中来,也就是c/c++的程序,加载之后的结果。

然后在上篇文章中说的创建进程后,系统会不会直接拷贝一份数据吗?也就是深拷贝,这个当然不是,因为就算拷贝了数据用可能用不到,所以就会造成浪费,那么OS怎么做才会不浪费,也可以进行不同的修改是怎么造成的?一般来说即使是OS也无法提前知道那些空间可能会被写入,所以OS选择使用了写时拷贝,将父子进程未来的数据进行分离。

三、终止

进程终止有下面三种情况

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

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

3、代码异常终止

进程终止前两种我知道是因为运行的结果,可是第三个有哪些呢?进程常见退出方法有正常终止和异常退出return退出有下面几种情况

1、从main返回

2、调用exit

3、_exit

异常退出:ctrl + c,信号终止

如下图我这里是用echo $?这个命令进行查看最近一条获得返回值,因为这里是利用ctrl+c进行停止,所以不是0,错误码表如下方代码

 

EPERM       1    /* Operation not permitted*/
ENOENT        2    /* No such file or directory*/
ESRCH       3    /* No such process*/
EINTR       4    /* Interrupted system call*/
EIO         5    /* I/O error*/
ENXIO       6    /* No such device or address*/
E2BIG         7    /* Argument list too long*/
ENOEXEC       8    /* Exec format error*/
EBADF       9    /* Bad file number*/
ECHILD        10   /* No child processes*/
EAGAIN          11   /* Try again*/
ENOMEM        12   /* Out of memory*/
EACCES        13   /* Permission denied*/
EFAULT          14   /* Bad address*/
ENOTBLK         15   /* Block device required*/
EBUSY           16   /* Device or resource busy*/
EEXIST          17   /* File exists*/
EXDEV           18   /* Cross-device link*/
ENODEV          19   /* No such device*/
ENOTDIR         20   /* Not a directory*/
EISDIR          21   /* Is a directory*/
EINVAL          22   /* Invalid argument*/
ENFILE          23   /* File table overflow*/
EMFILE          24   /* Too many open files*/
ENOTTY          25   /* Not a typewriter*/
ETXTBSY         26   /* Text file busy*/
EFBIG           27   /* File too large*/
ENOSPC          28   /* No space left on device*/
ESPIPE          29   /* Illegal seek*/
EROFS           30   /* Read-only file system*/
EMLINK          31   /* Too many links*/
EPIPE           32   /* Broken pipe*/
EDOM            33   /* Math argument out of domainof func */
ERANGE          34   /* Math result notrepresentable */
EDEADLK         35   /* Resource deadlock wouldoccur */
ENAMETOOLONG    36   /* File name too long */
ENOLCK          37   /* No record locks available*/
ENOSYS          38   /* Function not implemented*/
ENOTEMPTY       39   /*Directory not empty */
ELOOP           40   /* Too many symbolic linksencountered */
EWOULDBLOCK   EAGAIN /*Operation would block */
ENOMSG          42   /* No message of desired type*/
EIDRM           43   /* Identifier removed*/
ECHRNG          44   /* Channel number out of range*/
EL2NSYNC        45   /* Level2 not synchronized */
EL3HLT          46   /* Level 3 halted*/
EL3RST          47   /* Level 3 reset*/
ELNRNG          48   /* Link number out of range*/
EUNATCH         49   /* Protocol driver notattached */
ENOCSI          50   /* No CSI structure available*/
EL2HLT          51   /* Level 2 halted*/
EBADE           52   /* Invalid exchange*/
EBADR           53   /* Invalid request descriptor*/
EXFULL          54   /* Exchange full*/
ENOANO          55   /* No anode*/
EBADRQC         56   /* Invalid request code*/
EBADSLT         57   /* Invalid slot*/
EDEADLOCK       EDEADLK
EBFONT          59   /* Bad font file format*/
ENOSTR          60   /* Device not a stream*/
ENODATA         61   /* No data available*/
ETIME           62   /* Timer expired*/
ENOSR           63   /* Out of streams resources*/
ENONET          64   /* Machine is not on thenetwork */
ENOPKG          65   /* Package not installed*/
EREMOTE         66   /* Object is remote*/
ENOLINK         67   /* Link has been severed*/
EADV            68   /* Advertise error*/
ESRMNT          69   /* Srmount error*/
ECOMM           70   /* Communication error on send*/
EPROTO          71   /* Protocol error*/
EMULTIHOP       72    /*Multihop attempted */
EDOTDOT         73   /* RFS specific error*/
EBADMSG         74   /* Not a data message*/
EOVERFLOW       75    /* Valuetoo large for defined data type */
ENOTUNIQ        76    /* Namenot unique on network */
EBADFD          77   /* File descriptor in badstate */
EREMCHG         78   /* Remote address changed*/
ELIBACC         79   /* Can not access a neededshared library */
ELIBBAD         80   /* Accessing a corruptedshared library */
ELIBSCN         81   /* .lib section in a.outcorrupted */
ELIBMAX         82   /* Attempting to link in toomany shared libraries */
ELIBEXEC        83   /* Cannotexec a shared library directly */
EILSEQ          84   /* Illegal byte sequence*/
ERESTART        85   /*Interrupted system call should be restarted */
ESTRPIPE        86   /*Streams pipe error */
EUSERS          87   /* Too many users*/
ENOTSOCK        88   /* Socketoperation on non-socket */
EDESTADDRREQ    89   /* Destination address required*/
EMSGSIZE        90   /*Message too long */
EPROTOTYPE      91   /*Protocol wrong type for socket */
ENOPROTOOPT     92   /*Protocol not available */
EPROTONOSUPPORT 93   /* Protocol not supported */
ESOCKTNOSUPPORT 94   /* Socket type not supported*/
EOPNOTSUPP      95   /*Operation not supported on transport endpoint*/
EPFNOSUPPORT    96   /* Protocol family not supported*/
EAFNOSUPPORT    97   /* Address family not supported by protocol*/
EADDRINUSE      98   /*Address already in use */
EADDRNOTAVAIL   99   /* Cannot assign requested address*/
ENETDOWN        100  /*Network is down */
ENETUNREACH     101  /*Network is unreachable */
ENETRESET       102  /*Network dropped connection because of reset */
ECONNABORTED    103  /* Software caused connection abort*/
ECONNRESET      104  /*Connection reset by peer */
ENOBUFS         105  /* No buffer space available*/
EISCONN         106  /* Transport endpoint isalready connected */
ENOTCONN        107  /*Transport endpoint is not connected */
ESHUTDOWN       108  /*Cannot send after transport endpoint shutdown*/
ETOOMANYREFS    109  /* Too many references: cannot splice*/
ETIMEDOUT       110  /*Connection timed out */
ECONNREFUSED    111  /* Connection refused */
EHOSTDOWN       112  /* Hostis down */
EHOSTUNREACH    113  /* No route to host */
EALREADY        114  /*Operation already in progress */
EINPROGRESS     115  /*Operation now in progress */
ESTALE          116  /* Stale NFS file handle*/
EUCLEAN         117  /* Structure needs cleaning*/
ENOTNAM         118  /* Not a XENIX named type file*/
ENAVAIL         119  /* No XENIX semaphoresavailable */
EISNAM          120  /* Is a named type file*/
EREMOTEIO       121  /*Remote I/O error */
EDQUOT          122  /* Quota exceeded*/
ENOMEDIUM       123  /* Nomedium found */
EMEDIUMTYPE     124  /* Wrongmedium type */
ECANCELED       125  /*Operation Canceled */
ENOKEY          126  /* Required key not available*/
EKEYEXPIRED     127  /* Keyhas expired */
EKEYREVOKED     128  /* Keyhas been revoked */
EKEYREJECTED    129  /* Key was rejected by service*/

四、等待

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

这里将讲述wait和waitpid两个函数进行演示。

wait函数如下:

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。

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。如果不存在该子进程,则立即出错返回

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

测试如下

8 #include <sys/wait.h>
 29 #include <stdio.h>
 30 #include <stdlib.h>
 31 #include <string.h>
 32 #include <errno.h>
 33 #include <unistd.h>
 34 int main()
 35 {
 36     pid_t pid=fork();                                                                                                                                                                                         
 37     if(pid<0)
 38     {
 39         perror("fork");
 40     }
 41     else if(pid==0)
 42     {
 43         sleep(20);
 44         exit(10);
 45     }
 46     else
 47     {
 48         int st;
 49         int ret=wait(&st);
 50         if(ret>0&&(st&0X7F)==0)
 51         {
 52             printf("子错误码:%d\n",(st>8)&0XFFF);
 53         }
 54 
 55         else if(ret>0)
 56         {
 57             printf("信号码:%d\n",st&0x7F);
 58         }
 59     }
 60 }


五、思维导图



目录
相关文章
|
6天前
|
消息中间件 算法 Linux
【Linux】详解如何利用共享内存实现进程间通信
【Linux】详解如何利用共享内存实现进程间通信
|
6天前
|
Linux
【Linux】命名管道的创建方法&&基于命名管道的两个进程通信的实现
【Linux】命名管道的创建方法&&基于命名管道的两个进程通信的实现
|
6天前
|
Linux 程序员 计算机视觉
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
18 0
|
6天前
|
Linux 数据库
linux守护进程介绍 | Linux的热拔插UDEV机制
linux守护进程介绍 | Linux的热拔插UDEV机制
linux守护进程介绍 | Linux的热拔插UDEV机制
|
6天前
|
Unix Linux 调度
linux线程与进程的区别及线程的优势
linux线程与进程的区别及线程的优势
|
6天前
|
Linux 调度 C语言
|
6天前
|
存储 算法 Linux
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
|
6天前
|
存储 安全 Linux
【Linux】详解进程通信中信号量的本质&&同步和互斥的概念&&临界资源和临界区的概念
【Linux】详解进程通信中信号量的本质&&同步和互斥的概念&&临界资源和临界区的概念