【linux】 进程(二)

 文章继续上次的展开讲解


 


3. 进程

a. 描述进程 -- PCB

概念:

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合

注意:

操作系统内核都是由 C语言 编写的,PCB 相当于 C语言 里面的结构体

(一) task_struct 结构体

  • task_struct 是一种特殊的 PCB ,它是属于 linux操作系统的
  • task_struct 是 Linux内核 的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息

(二) task_ struct内容分类 (包含各种属性)

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程
  • 状态: 任务状态,退出代码,退出信号等
  • 优先级: 相对于其他进程的优先级 (决定 CPU 先执行哪个程序 , 数值越低,优先级越高)
  • 程序计数器: 程序中即将被执行的下一条指令的地址
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据(方便后续恢复寄存器中存储的数据)
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
  • 其他信息

b. 组织进程

进程是通过数据结构一个个组织起来的(linux内核是采用链表)

c. 查询进程

  • ls /proc

查询进程

d. stack_struct 各种属性

(一)标识符

  • PID 进程id
  • PPID 父进程id

(通过系统调用获得标识符)代码举例

#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
        cout << "PID: " << getpid() << " PPID: " << getppid() << endl;
        return 0;
}

通过指令获得标识符

(二)进程状态

  • R 运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列

  • S 睡眠状态(sleeping): 意味着进程在等待事件完成,相当于堵塞状态(这里的睡眠有时候也叫做可中断睡眠 )【比如是等待键盘的输入,等到有数据的时候,又可以回到运行队列里】

注意:

遇到 挂起状态时(内存空间不够的时候),操作系统可能会处理 S状态的进程,把它们的数据和代码存到磁盘里面,再从 PCB 里面删除 (D状态下的不会动)

  • D 磁盘休眠状态(Disk sleep)(有时候也叫不可中断睡眠状态),在这个状态的进程通常会等待IO的结束
  • T 停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行
  • X 死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态(数据,代码都会清理,并且进程从 PCB 里面移除)
  • Z 僵死状态 (zombie)-- 僵尸进程:

一般来说,要经历 X 状态,就要先经历 Z 状态(当进程退出且父进程没有接收到子进程退出时返回的代码时,就会产生僵尸进程)

注意:

  1. 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

    2. 如果父进程先结束运行,它的子进程的 PPID 就要发生更改(即父进程发生更改,为了新的父进程可以得到子进程退出时返回的代码,一般来说,它的新的父进程就是操作系统)

     3.  孤儿进程

父进程先退出,子进程就称之为“孤儿进程”

孤儿进程被1号init进程领养(即操作系统)

(三) 优先级

优先级决定进程的调度先后顺序

PRI 越高,优先级越低

注意:

  1. UID : 使用者身份信息
  2. PRI :优先级
  3. NI :优先级修正数值
  4. 优先级 PRI(new) = PRI (old) 【默认80】 + nice (NI)
  5. nice值的范围 : -20 ~ 19

查看进程优先级的命令

  1. top
  2. 进入top后按“r”–>输入进程PID–>输入nice值

e. 通过系统调用创建进程 -- fork

代码举例

#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
        pid_t id = fork();
        if(id == 0)
        {
                while(1)
                {

                sleep(1);
                //子进程
               printf("我是子进程 : 我的 PID : %d , 我的 PPID : %d\n ",getpid(),getppid());
                }
        }
        else if(id > 0)
        {
                while(1)
                {
                sleep(1);
                //父进程
               printf("我是父进程 : 我的 PID : %d , 我的 PPID : %d\n ",getpid(),getppid());
                }
        }
        else
        {
                printf("创建进程失败\n");
        }
                return 0;
}

注意:

父进程和子进程的代码和数据是共享的,但是它们俩又是独立的个体,所以如果子进程修改了父进程的数据,此时会发生写实拷贝,同一个变量存两个不同的值

如:

返回得到的 id 就发生了写实拷贝

(id > 0 , 走父进程执行的代码 ; id = 0 ,走子进程执行的代码 ; id < 0 ,则创建子进程失败)

f. 其它概念

  1. 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  2. 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  3. 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  4. 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进

注意:

  1. 进程切换是基于时间片,时间一到,进程没有结束,通过运行队列维护的两个指针数组使每个进程一段时间切换(如果第一个进程时间到了,将它从running数组移到waiting数组)

  1. 程序计数器pc,eip,记录当前进程正在执行指令的一行指令的地址
  2. CPU 里面的寄存器保存的是进程相关数据,又可以叫做进程的上下文
  3. 进程从 CPU 上离开的时候,需要保存好自己的上下文,甚至带走
  4. 进程被切换:保存上下文(临时数据储存到PCB里面),回复上下文
  • 101
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 79
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值