11.OS操作系统学习_进程

11.OS操作系统学习:进程

引入:我们可以回顾一下杨老师在课上所讲进程~

进程是一个活动的实体,具有指定下一条指令以及执行一组相关资源的程序计数器

一,冯诺依曼体系结构

image

注意这里的存储器内存

体系规定程序的运行必须加载到内存中,cpu执行的代码访问内存中的数据。

IO就是从内存的角度来说的,

比如从键盘这个输入设备到内存叫做input

从内存这个Memory Unit到屏幕这个输出设备叫做outputimage

二,操作系统

image

image

什么是系统调用?

image

image

操作系统的职能分为四大板块

  • 内存管理

  • 进程管理

  • 文件管理

  • 驱动管理

本文讨论进程,故具体讲解进程管理模块的知识

三,进程

**课本观点:**活动的实体,具有指定下一条指令以及执行一组相关资源的程序计数器(A program counter)

PC是cpu的一个寄存器,存放着下一条要执行指令的内存地址

**内核观点:**担当分配系统资源(cpu时间,内存)的实体

image

进一步讲:进程应该有两个部分:

数据(例如c语言包含着二进制代码和创建修改时间等)和信息(为了方便进行管理)

1.代码与数据

stat xx//来查看文件信息

image

2.PCB(process control block)

ps ajx//查看进程块包含的信息

PCB包含的内容

image

3.practice1关于pid

前置知识:通过getpid()函数来获得当前进程的pid值(进程的唯一编号)

image

注意getppid()就是获得父进程

#include<stdio.h>
#include<unistd.h>  //Linux中睡眠函数的头文件
#include<sys/types.h>

int main()
{
  int sec = 0;
  while(1)
  {
    printf("这是一个进程,已经运行了%d秒 当前进程的PID为:%zu\n", sec, getpid());
    sleep(1); //单位是秒,睡眠一秒
    sec++;
  }
  return 0;
}

程序运行结果:image

我们使用下面这串代码查找这个进程

ps ajx | head -1 && ps ajx | grep a.out | grep -v grep

image

提高:可以使用makefile简化我们的过程

image

4.top指令查看所有的进程

top

5.fork创建子进程

这个函数有两个返回值
进程创建成功时,给父进程返回子进程的PID,给子进程返回0
创建失败时,返回 -1

int fork(void)

0.原理

image

1.practice1:子进程引入

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
	//pid_t是数据类型,实际上是一个整型
	//通过typedef重新定义了一个名字,用于存储进行ID
	pid_t pid; //parent pid
	pid_t cid; //child pid

	// getpid()函数返回当前进程的ID号	
	printf("Before fork Process id:%d\n", getpid());


	/*
	fork()函数用于创建一个新的进程,该进程为当前进程的子进程,创建的方法是:
	将当前进程的内存内容完整拷贝一份到内存的另一个区域,两个进程为父子关系,他们会同时(并发)执行fork()语句后面的所有语句
	fork()的返回值是:
		如果成功创建子进程,对于父子进程fork会返回不同的值,对于父进程它的返回值是子进程的进程id值,对于子进程它的返回值是0.
		如果创建失败,返回值为-1.
	*/

	fork();

	printf("After fork Process id:%d\n", getpid());

	pause();

	return 0;
}

image

会发现执行了两次

2.practice2:交替执行

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

int main(int argc, char const *argv[])
{
	pid_t cid; //child pid

	printf("Before fork Process id:%d\n", getpid());

	cid = fork();

	if (cid == 0){
		printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());
		for(int i = 0; i < 30; i++){
			printf("hello\n");
		}
	}else{
		printf("Parent Process id: %d\n",getpid());
		for(int i = 0; i < 30; i++){
			printf("world\n");
		}

		wait(NULL);
	}

	return 0;
}

3.fork()函数工作原理

image

fork 创建子进程时,会新建一个属于 子进程 的 PCB ,然后把 父进程 PCB 的大部分数据拷贝过来使用,两者共享一份代码和数据。

四,进程状态

在杨老师课程中进程状态就是三个基本状态

  1. 运行态          2.就绪态         3.等待态

今天我们就要更进一步:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

1.阻塞

阻塞就是进程因等待某种条件就绪,而导致的一种不推进状态。

进程的阻塞就是不被调度

2.挂起

CPU资源紧张是,将进程交换至磁盘挂起,此时内存中只有PCB

**挂起**可以看作一种特殊的阻塞状态

3.运行R

新建,就绪,运行都可以看作运行R这个状态

#include<iostream>
using namespace std;

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

int main()
{
  while(1)
  {
    cout << "I'm a process, my PID is:" << getpid() << endl;
    sleep(1);
  }
  return 0;
}


myProcess:test.cpp
	g++ -o myProcess test.cpp

.PHONY:catPI
catPI:
	ps ajx | head -1 && ps ajx | grep myProcess | grep -v grep 

.PHONY:clean
clean:
	rm -r myProcess

利用catPI查看当前进程的状态

image

会发现处在睡眠 S+S+表示当前进程在前台运行

为什么不显示运行?

  1. 我们回顾一下,内部事件(启动IO设备)导致进程离开CPU。

  2. 我们把打印语句和睡眠语句屏蔽好,就会显示R+

4.睡眠S

睡眠的本质就是进程阻塞,表示进程因某种资源而暂停运行。

  1. 可以手动关闭 ctrl+c

  2. kill -9 PID

image

image

5.休眠D(disk sleep)

休眠被称为不可中断休眠,无法被kill指令和操作系统杀死,只能默默等待进程阻塞结束,当拿到资源的时候,进程才会中止休眠D状态。

6.暂停T(stopped)

kill -19 PID 暂停进程
kill -18 PID 恢复进程

回复后的进程在后台运行,此时只能通过kill来终止

备注:在gdb调试代码时,打断点实际上就是使进程在指定行暂停运行,此时进程处于追踪暂停状态

7.死亡X(dead)

当进程被终止以后,就处于死亡X状态

无法在任务列表观察到,知识一个返回状态

8.僵尸Z (zombie)

8.1理论

image

僵尸进程如果不被回收,将会导致内存泄漏问题标识符占用问题

子进程被终止,没有被父进程回收的时候就会变成僵尸进程

8.2practice

#include<iostream>
using namespace std;

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

int main()
{
  pid_t ret = fork();
  if(ret == 0)
  {
    while(1)
    {
      cout << "I'm son process, my PID: " << getpid() << " PPID: " << getppid() << endl;
      sleep(1);
    }
  }
  else if(ret > 0)
  {
    while(1)
    {
      cout << "I'm father process, my PID: " << getpid() << " PPID: " << getppid() << endl;
      sleep(1);
    }
  }
  else
  {
    while(1)
    {
      cout << "Make son process fail!" << endl;
      sleep(1);
    }
  }

  return 0;
}

image

kill子进程之后

image

image

9.孤儿进程

9.1理论

image

image

如果子进程不被1号进程领养,

子进程退出时无人收回,称为游离的僵尸

僵尸进程有内存泄露的风险,因此子进程会被OS领养

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值