2022-1-13牛客网C++项目—— 第二章 Linux 多进程开发(一)

复习用的问题
进程和程序之间的关系是什么?
进程包含了哪些信息?

一、程序当中包含了一系列的信息,这些信息用于描述如何创建一个进程。
1)二进制格式标识:描述文件的格式,内核根据这个信息来解释文件中的其他的信息。(复习时候的补充:包括文件的创建信息和原信息啥的)(我猜测,文件的格式是和操作系统的类型适配的,必须使得内核能够读懂,)
2)机器语言指令:(这个是不是编译好了直接拿来就可以执行的?没懂,再听一次)(是哒,可以直接交由 CPU 来执行)
3)程序入口地址:程序开始执行的地方(和汇编语言当中需要用.start 和 C/C++ 、Java当中的main函数作为程序的接口是一个道理。)
4)数据:程序初始化的时候使用的数值和字符串字面量。(想想计算机的开机启动,需要一大堆数据的初始化)
5)符号表以及重定位表(这个不太懂,和 C/C++中的虚函数表格类似?是为了方便运行中的动态链接吗?)(复习时补充:描述了程序中的函数和变量的名称。这些信息可以用于调试)
6)共享库和动态连接信息:需要的共享库和加载共享库的动态连接器的路径名称。(后面不懂,我理解的动态连接器的路径是由环境的变量决定的,这个想法错在哪里?)
(复习时候的补充:动态库只在运行时后加载进来,因此要指明动态库的位置,和动态链接时候的路径)

二、关于进程的定义
进程是操作系统资源分配的基本单元,线程是调度的基本单元。进程是程序在一个特定的数据集上面的一个实例。

内核视角:
进程 = 用户内存空间 + 内核数据
用户内存空间 :程序代码 + 用户数据
内核数据 :进程标识号,打开文件的列表,信号传递以及处理的有关信息、资源的使用和限制、当前的工作目录。(猜测也记录了进程的状态)。

三、单道程序和多道程序
单道程序 —— 内存中只存在一个程序。
多道程序 —— 内存中放置多个独立的程序,使得一个程序陷入阻塞的时候可以运行另外的程序,来提高 CPU 的利用率。

四、时间片
为每个程序分配固定的运行时间,可以交替轮流运行。
时间片耗尽之后再由操作系统重新计算。

五、并发和并行
并发:单处理器,多个程序交替运行。
并行:多处理器,多个程序同时运行。

六、进程控制块 PCB
通过 PCB 来维护每一进程的信息。Linux 的内核进程控制块是 task_struct 结构体
需要掌握的内容有:
1)进程id
2)进程的状态
3)进程切换时需要保存的 CPU寄存器里面的一些内容
4)描述虚拟地址空间的一些信息
5)描述终端的控制信息(这个我不理解)
(每个进程会对应到一个终端,在程序运行的过程中需要通过终端去录入信息,并且需要通过终端去输出信息)
6)当前的工作目录(要通过当前的工作目录来获取环境变量啥的,这个不太理解)
7)umask 掩码(这是干啥用的?)
8)文件描述符,包含很多指向file结构体的指针(这个是啥)
9)和信号相关的信息
10)用户id 和 组id(一般同一个父进程下的子进程为一组)
11)会话和进程组(这个有些不记得了等下回看视频)
12)进程可以使用的资源上限

使用 ulimited 来查看资源的上限。
在这里插入图片描述

七、进程的状态
三态模型
运行态 —— 程序占有处理器运行
阻塞态 —— 不满足运行的条件,正在等待某个事件的完成。
就绪态 —— 分配到除了CPU之外的所有的必要资源。一般会有多个这个样的进程,会放置在就绪队列当中。
在这里插入图片描述
在这里插入图片描述
新建:进程刚被创建,尚未进入就绪队列当中
终止:由于发生了未知的错误而导致进程终止
1)程序正常运行完成
2)发生了无法克服的错误导致了异常的终止
3)被操作系统和其所有权的程序终止
此时进程仍在操作系统中含有遗留的信息,需要操作系统来善后

其他
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进程号 pid :用来标识进程,进程号的范围:0 ~ 32767
(进程号具有范围意味着,在一个系统中有进程个数的限制,但是考虑到资源分配的问题,进程的上限应该比这个要小)
除了 init 进程,其他的进程是由父进程创建的(真的会有爸爸),对应的进程号为父进程号 ppid。
进程组是一个或者多个进程的集合,用来接受来自同一个终端的信号。默认情况下当前的进程号会被当做进程组号。(如果没有分组就自成一组)。
在这里插入图片描述
八、进程的创建
如何创建一个子进程?
使用 fork 函数
fork 函数的参数和返回值是什么?
如何区分父进程和子进程?父子进程有啥区别?父子进程有啥共同点?
得到的返回值存放在哪里?
什么情况下进程会创建失败?这个时候返回值和 erron 又该如何设置?
父子进程是如何调度的?
父子进程是如何共享数据和做数据区隔的?(八字真言)

/*
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
函数的作用是创建子进程。
返回值:fork创建成功会返回两次,返回给父进程的是子进程的pid(>0),返回给子进程的是0,
如果创建失败,返回给父进程的是-1,没有数据返回给子进程
并且会设置erron
老师的补充:因此,可以通过fork的返回值来区分父进程和子进程
失败的主要原因:1)进程的数目已经达到上限,
这个时候erron会被设置为EAGAIN
2)内存不足,erron = ENOMEN

父子进程的区别:
1)得到的fork()返回值 pid:
parent > 0
child == 0
2)在内核空间里面的区别
·各自的pid,ppid
·信号集

共同点
1)在子进程刚刚创建尚未进行任何操作的时候
进程pcb里面的部分数据相同
·文件描述符(之后子进程对文件描述符的操作互相没有影响)
·共享内存当中的部分数据,也就是用户数据到内存地址的映射是一致的

父子进程是否共享数据?
1)刚开始创建的时候是共享的,写的时候是人手一份
2)读时共享(没有给子进程分配单独的地址空间,只有写的时候才
会给写进程分配单独的地址空间,写时拷贝。

*/
#include <sys/types.h>
#include <unistd.h>
#include<stdio.h>
int main(void){
   // pid_t fork(void);
   int num = 10;
   pid_t pid = fork();
   if(pid > 0){
       printf("pid :%d\n",pid);
       printf("i am parent process, pid :%d, ppid : %d\n",getpid(),getppid());
       printf("parent num = %d\n",num);
       num += 10;
       printf("parent num += 10:%d\n",num);
   }
   else if(pid == 0){
       printf("i am child process,pid : %d,ppid : %d\n",getpid(),getppid());
        printf("child num = %d\n",num);
       num += 100;
       printf("child num += 100:%d\n",num);
   }
   //由于fork的作用是拷贝地址空间,地址空间里面的变量也会被拷贝一份,
   //结果为父子进程会独有一份。
   //所以子进程和父进程当中的值的变化是互不干扰的
   for(int i = 0;i < 5;++i){
       printf("i = %d , pid : %d\n",i,getpid());
       sleep(1);
   }
   return 0;
}

     //为什么每次的运行结果都不一样?
     //  估计是每次的调度具有偶然性

由下图可知,fork 函数拷贝一份父进程的地址空间里面的内容给子进程,再改改 pid 里面的内容。
说白了就是一个克隆函数。
在这里插入图片描述
但是上面的那张图片不够准确。具体来说,子进程创建的时候只拷贝父进程的内核空间,读取数据的时候和父进程共享一个地址空间,只有子进程需要写入数据的时候才会读取分配物理地址空间。

在这里插入图片描述
由下面这张图片可知,父子进程共享地址空间的数据不会被更改的,若父进程或子进程需要修改数据,会另外开辟新的地址空间。
在下面图片中,子进程刚刚创建的时候,num 的值为 10,这个时候父子进程的地址映射是一致的。
当父进程将num 改成 11 和子进程将 num 改成 12 的时候,都各自开辟了新的地址空间,地址映射关系就发生了改变。
但是原来的数据依然被保留了下来(可是这样不浪费空间嘛?)
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值