Day 1.进程的基本概念、相关命令、函数结口

进程基本概念

一、进程:

程序:存放在外存中的一段数据组成的文件

进程:是一个程序动态执行的过程,包括进程的创建、进程的调度、进程的消亡

二、进程相关的命令

1.top

动态查看当前系统中所有的进程信息(根据CPU占用率排序)

PID:唯一识别进程的ID号(>0)

优先级:linux系统中数据低,优先级高(-20~19) Windows系统和中数值越高,优先级越高

进程状态:

R 运形态/就绪态

S 睡眠态/可唤醒等待态

D 不可唤醒等待态

T 暂停态

Z 僵尸态

X 结束态

q退出查看进程

2.nice

以指定优先级开运行进程

示例:

nice -n 优先级 要执行的集成任务

renice:重新设定一个正在运行的进程的优先级

示例:

renice -n 优先级 进程PID

3.kill

杀死指定进程任务

示例:

kill -9 进程PID

killall

杀死名对应的所有进程任务

示例:

killall -9 进程名

4.ps -ef

查看当前时刻所有的进程信息

PPID:父进程ID号

示例:

ps -ef | grep a.out

5.pstree

查看进程树关系

6.ps -aux

查看当前时刻的进程信息

7../a.out &

就是将a.out任务放在后台执行

8.jobs

查看一个终端下后台执行的所有任务

9.fg

将后台任务放到前台执行

示例:

fg 编号

三、进程的创建

32bits操作系统下

一个进程在运行时,操作系统会将进程分分配为0-4G虚拟内存空间分为文本段、数据段、系统数据段。

文本段:

也被称呼为文本区,存放代码和指令

数据段:

也称为数据区、可以细分为:

1)字符串常量区

2)为初始化的全局变量/静态变量

3)已初始化的全局白能量/静态变量

系统数据段:包含堆区和栈区

四、进程中虚拟地址和物理地址大的关系

1.0-4G虚拟内存空间只有一个

2.实际物理地址中每个进程空独立

3.通过MMU内存映射单元,单一个进程执行时,将物理地址之中的数据加载到虚拟地址中运行

五、进程的调度

1.常见的的调度算法

1)先来先执行,后来后执行

2)高优先级调度算法

3)时间片轮转调度算法

4)多级队列反馈调度算法

5)负载均衡调度算法

时间片:CPU在一个任务中的运行时间称为一个时间片

2.宏观并行,微观串行

3.进程状态:

R 运行态(CPU正在执行)、就绪态(等待调度)

S 睡眠态/可唤醒等状态

D 不可唤醒等待态(不能被打断/切换的任务)

T 暂停态(程序运行在此停住,需手动执行)

Z 僵尸态(代码已经结束,空间未回收)

X 结束态(代码结束,空间回收)

六、进程相关的函数接口

1.进程的创建:fork

功能:

创建一个子进程,新创建按的进程被称为原来进程的子进程,原来的的进程被称为新进程的父进程

参数:void

返回值:

成功子进程返回0

父进程返回子进程的PID

失败返回-1

解释:父进程调用fork创建子进程,子进程拷贝父进程文本段、数据段、系统数据段

getpid (当前进程)

pid_t getpid(void);

功能:获得调用进程的PID号

getppid (父进程)

pid_t getppid(void);

功能:获得调用进程的PPID

#include "head.h"


int main(void)
{
	pid_t pid;
	pid = fork();

	if (pid == -1)
	{
		perror("fail to fork");
		return -1;
	}
	if (pid == 0)
	{
		printf("子进程 PID=%d,PPID=%d\n",getpid(),getppid());
	}else if (pid > 0)
	{
		printf("父进程 PID=%d,chinl PID=%d\n",getpid(),pid);
	}
	printf("hello world\n");

	while(1)
	{

	}

	return 0;
}
练习:

创建一个父进程的两个子进程,自进程中打印自己的PID和父进程的PID;父进程中打印自己的PID和两个子进程的PID

#include "head.h"

int main(void)
{
	pid_t pid1;
	pid_t pid2;
	pid1 = fork();

	if (pid1 == -1)
	{
		perror("fail to fork");
		return -1;
	}

	if (pid1 == 0)
	{
		printf("子进程1  PID=%d PPID=%d\n",getpid(),getppid());
	}else if (pid1 > 0)
	{
		pid2 = fork();
		if (pid2 == -1)
		{
			perror("fail to fork");
			return -1;
		}

		if (pid2 == 0)
		{
			printf("子进程2  PID1=%d PPID=%d\n",getpid(),getppid());
		}else if (pid2 > 0)
		{
			printf("父进程  PID=%d chinl PID1=%d chinl PID2=%d\n",getpid(),pid1,pid2);
		}
	}


	while(1)
	{

	}

	return 0;
}

linux@ubuntu:~/c/软件编程/进程$ ./a.out
父进程  PID=26204 chinl PID1=26205 chinl PID2=26206
子进程1  PID=26205 PPID=26204
子进程2  PID1=26206 PPID=26204
判断:打印出来Num的值
#include "head.h"

int main(void)
{
	pid_t pid;
	int Num = 0;

	pid = fork();
	if (-1 == pid)
	{
		perror("fail to fork");
		return -1;
	}
	if (0 == pid)
	{
		Num = 100;
	}
	else if (pid > 0)
	{
		sleep(5);
		printf("Num = %d\n", Num);
	}

	return 0;
}
判断:打印数组中的元素
#include "head.h"

char tmpbuff[1024] = {0};

int main(void)
{
	pid_t pid;

	pid = fork();
	if (-1 == pid)
	{
		perror("fail to fork");
		return -1;
	}
	if (0 == pid)
	{
		strcpy(tmpbuff, "hello world");	
	}
	else if (pid > 0)
	{
		sleep(5);
		printf("tmpbuff = %s\n", tmpbuff);
	}

	return 0;
}

结果:都打印不出来

解释:当执行到fork,创建出子进程,此时子进程将父进程的所有的文本段、数据段、系统数据段全部拷贝过来,此时两个进程的实际物理空间独立,所以互不影响。

2.结束进程:exit

void exit(int status);

功能:

让进程结束

参数:

status:进程结束的参数

返回值:缺省

exit在主函数中使用和return效果一致

exit会刷新缓存区

_exit

void _exit(int status);

功能:

让进程直接结束 但是不会刷新缓存区

参数:

status:进程结束的状态

返回值:缺省

#include "head.h"

void Fun(void)
{
	exit(0);
}

int main(void)
{
	printf("hello world");
	Fun();
	printf("how are you");

	return 0;
}

linux@ubuntu:~/c/软件编程/进程$ ./a.out
hello worllinux@ubuntu:~/c/软件编程/进程$ 

3.回收进程空间:wait

pid_t wait(int *wstatus);

功能:

回收子进程空间

参数:

wstatus:存放子进程结束状态空间的首地址

返回值:

成功返回回收到的子进程PID

失败返回-1

1)wait函数具有阻塞功能

2)wait函数具有同步功能

WIFEXITED(wstatus)

进程是否正常退出

WEXITSTATUS(wstatus)

进程结束状态值

WIFSIGNALED(wstatus)

进程是否被信号杀死

WTERMSIG(wstatus)

获得杀死进程的信号编号

#include "head.h"

int main(void)
{
	pid_t pid;
	pid_t ret;
	int wstatus;

	pid = fork();
	if (-1 == pid)
	{
		perror("fail to fork");
		return -1;
	}
	if (0 == pid)
	{
		printf("子进程开始执行: PID:%d PPID:%d\n", getpid(), getppid());
		printf("子进程即将结束!\n");
		sleep(10);
		exit(10);
	}
	else if (pid > 0)
	{
		printf("父进程开始执行: PID:%d\n", getpid());
		ret = wait(&wstatus);
		if (-1 == ret)
		{
			perror("fail to wait");
			return -1;
		}
		
		printf("回收到 %d 子进程空间\n", ret);
	
		if (WIFEXITED(wstatus))
		{
			printf("正常结束,值为 %d\n", WEXITSTATUS(wstatus));
		}
		else if (WIFSIGNALED(wstatus))
		{
			printf("被 %d 号信号杀死\n", WTERMSIG(wstatus));
		}
	}

	return 0;
}

linux@ubuntu:~/c/软件编程/进程$ ./a.out
父进程开始执行: PID:26557
子进程开始执行: PID:26558 PPID:26557
子进程即将结束!
回收到 26558 子进程空间
正常结束,值为 10

七、进程的消亡

1.僵尸态:

进程代码结束,空间 没有被回收,称为僵尸进程

2.如何避免产生僵尸进程?

1)让父进程先结束

2)让父进程回收子进程空间

3.孤儿进程:

进程的父进程先结束,此时该进程成为孤儿进程,被系统进程收养,进程在结束时,会被系统进程回收进程空间

相关推荐
Amor风信子7 分钟前
华为OD机试真题---跳房子II
java·数据结构·算法
码农小白10 分钟前
linux驱动:(22)中断节点和中断函数
linux·运维·服务器
4647的码农历程11 分钟前
Linux网络编程 -- 网络基础
linux·运维·网络
2401_8576100343 分钟前
SpringBoot实现:校园资料分享平台开发指南
服务器·spring boot·php
Ljubim.te1 小时前
软件设计师——数据结构
数据结构·笔记
C++忠实粉丝1 小时前
Linux环境基础开发工具使用(2)
linux·运维·服务器
康熙38bdc2 小时前
Linux 环境变量
linux·运维·服务器
存储服务专家StorageExpert2 小时前
DELL SC compellent存储的四种访问方式
运维·服务器·存储维护·emc存储
_GR2 小时前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
无限大.2 小时前
c语言实例
c语言·数据结构·算法