【Linux】进程

1.进程是什么?

在这里插入图片描述

  1. 可执行程序在运行之前需要加载到内存中。在同一时刻,内存中可能会加载多个可执行程序。
  2. 在没有加载任何软件时,有一款软件就已经加载到内存中了,就是"操作系统"。在电脑开机的时候就是在启动操作系统。
  3. 随着时间流逝,可执行程序可能会:执行完成要释放空间、停止运行、空间不够需要扩容。所以需要管理这些程序,谁管理?操作系统。但是由于可执行程序可能有多个,操作系统不知道可执行程序的具体信息,无法管理。
  4. 操作系统必然要对加载到内存的可执行程序进行管理的办法:先描述,再组织
  5. 先描述:对每一个可执行程序构建结构体对象:代码地址、数据地址、id、优先级、状态、下一个结构体类型的指针。
  6. 进程 = 操作系统内核数据结构对象 + 自己的代码和数据。
  7. 在操作系统中该数据结构叫做:进程控制块 PCB(process control block),在具体的 Linux 操作系统叫做:task_struct。进程的所有属性,都可以直接或间接通过 task_struct 对象找到。
  8. 进程 = PCB(task_struct)对象 + 自己的代码和数据。甚至可以将 task_struct 视为进程。任何一个进程,除了将代码和数据加载到内存中,还要在操作系统内部为该代码和数据,创建对应的 task_struct 结构体对象,该结构体对象含有代码和数据的地址,可以找到代码和数据。
  9. 再组织:在操作系统内可以使用链表(也叫:进程列表)的形式,把所有的 task_struct 管理起来。操作系统管理所有的进程,最后转化成对进程列表的 “增删查改”。例如新增一个进程:先将可执行程序(代码和数据)加载到内存中,再在操作系统内部创建对应的 PCB 数据结构对象,PCB 可以找到自己的代码和数据,最后将 PCB 对象链接到进程列表中。
  10. CPU 调度进程:将进程列表想象成队列,先进先出。先取出第一个 PCB 对象,通过地址找到对应的代码和数据,进行调度。进程的删除:代码运行结束后,在内存中将代码和数据释放掉,再在进程列表中将该节点释放掉。

为什么进程加载的时候,操作系统要为其创建 PCB 结构体对象?因为要管理进程,必须要先描述,再组织。先描述:有描述进程属性的 PCB 对象;再组织:对进程列表的管理,变成对 “进程列表” 的 “增删查改”。

进程列表:双链表

在这里插入图片描述

2.task_struct 的内容分类

  1. 标示符:描述本进程的唯一标示符,用来区别其他进程。
  2. 状态:任务、运行、死亡、僵尸、等待、暂停状态、退出代码、退出信号等。
  3. 优先级:相对于其他进程的优先级。
  4. 程序计数器:程序中即将被执行的下一条指令的地址。
  5. 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  6. 上下文数据:进程执行时处理器的寄存器中的数据。
  7. I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  8. 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  9. 其他信息。

3.查看进程

使用 Makefile 文件,搭配 make 命令:

在这里插入图片描述

第一种:ps axj
在这里插入图片描述

  1. 我们历史上执行的所有指令,工具、自己的程序,运行起来,全部都是进程。某些指令一启动,就退出了,不好观察。
  2. 整个操作系统能执行某个任务,都是通过进程来执行的。进程也叫做任务,PCB 在 Linux 中叫做 task_struct。
  3. 在 Linux 中,用户是通过进程的方式访问操作系统的。

第二种:ls /proc

在这里插入图片描述

进程中的两个重要文件:exe与cwd

在这里插入图片描述
exe文件说明

在这里插入图片描述

cwd文件说明

在这里插入图片描述

在这里插入图片描述

扩展:cd 命令就是以 chdir() 系统调用,来切换路径的。

4.杀死进程

第一种:Ctrl + c
在这里插入图片描述
第二种:在另一个终端中输入:kill -9 进程ID
在这里插入图片描述

5.父进程

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
	printf("pid: %d\n", getpid());    //进程id 
	printf("ppid: %d\n", getppid());  //父进程id
	
	return 0;
}

在这里插入图片描述

在这里插入图片描述

操作系统会给每一个登入用户,分配一个 bash。再开一个终端,可以通过以下命令:看到两个bash。

while : ; do ps axj | head -1 && ps axj | grep 'bash' | grep -v grep ; sleep 1; done

在这里插入图片描述

问题:进程是如何创建子进程?答案:以代码的方式创建子进程

6.创建进程:fork

pid_t fork(void);

  1. pid_t:就是 int。
  2. 函数参数:没有参数。
  3. 返回值:创建进程成功时:将子进程 pid 返回给父进程,将 0 返回给子进程。创建进程失败时:将 -1 返回给父进程。

在这里插入图片描述
在这里插入图片描述

通过返回值让父子进程执行不同的代码逻辑:

//myprocess.c源文件
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
	printf("父进程开始运行。我的pid:%d\n", getpid());
	pid_t id = fork();
	if (id < 0)
	{
		printf("创建进程失败\n");
		return 1;
	}
	else if (id == 0)
	{
		//子进程                                                                               
		while (1)
		{
			sleep(1);
			printf("我是子进程。我的pid:%d, 我的ppid:%d\n", getpid(), getppid());
		}
	}
	else
	{
		//父进程
		while (1)
		{
			sleep(1);
			printf("我是父进程。我的pid:%d, 我的ppid:%d\n", getpid(), getppid());
		}
	}

	return 0;
}

在这里插入图片描述

问题一:为什么 fork 函数给父子进程,返回各自的不同返回值?子进程返回0,父进程返回子进程的 pid

  1. 父进程 :子进程 = 1 :n(任何一个子进程只有一个父进程,但一个父进程可以有多个子进程)
  2. 父进程要通过不同的子进程的 pid,来区分不同的子进程,方便对子进程做管理。

问题二:为什么 fork 函数会返回两次?

在这里插入图片描述

问题三:为什么变量会,即等于0,又大于0。导致 if 和 else if 同时成立?

进程具有独立性:一个进程挂了,不会影响另一个进程!即便是父子进程同样如此。

在这里插入图片描述

//myprocess.c源文件
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int gval = 100;

int main()
{
	printf("父进程开始运行。我的pid:%d\n", getpid());
	pid_t id = fork();
	if (id < 0)
	{
		printf("创建进程失败\n");
		return 1;
	}
	else if (id == 0)
	{
		//子进程
		printf("我是子进程。我的pid:%d, 我的ppid:%d,gval:%d\n", getpid(), getppid(), gval);
		sleep(2);
		                                                       
		while (1)
		{
			sleep(1);
			printf("子进程修改变量:%d->%d。", gval, gval + 10);
			gval += 10;
			printf("我是子进程。我的pid:%d, 我的ppid:%d\n", getpid(), getppid());
		}
	}
	else
	{
		//父进程
		while (1)
		{
			sleep(1);
			printf("我是父进程。我的pid:%d, 我的ppid:%d,gval:%d\n", getpid(), getppid(), gval);
		}
	}

	return 0;
}

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值