linux 进程管理

在这里插入图片描述

进程处理机制在这里插入图片描述

在这里插入图片描述

进程属性

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

标识符

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

进程状态

通常进程的状态被划分为五种:初始态、 就绪态、运行态、睡眠态 和终止态。初始态一般不进行讨论,因为当初始化完成后,进程会立刻转化为就绪态。
①就绪态
处于就绪态(Ready)的进程,所需的其它资源已分配到位,此时只等待cpu,当可以使用cpu时,进程会立刻变为运行态。
②运行态
进程处于运行态(Execting)时会占用cpu,处于此状态的进程的数目必定小于等于处理器的数目,即每个cpu上至多能运行一个进程。
③睡眠态
处于睡眼态(Sleeping)的进程会因某种原因而暂时不能占有cpu。睡眠态分为不可中断的睡眠和可中断的睡眠
④终止态
处于终止态的进程已运行完毕,此时进程不会被调度,也不会再占用CPU。
在这里插入图片描述
在这里插入图片描述

寄存器信息

在这里插入图片描述

页表指针

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

进程组和会话

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

进程控制

在这里插入图片描述

fork 创建进程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
案例1:使用fork()函数创建一个进程,进程创建成功后使父进程与子进程分别执行不同的功能

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
	pid_t pid;
	pid = fork();							//调用fork()函数创建子进程
	if (pid == -1)							//创建失败
	{
		perror("fork error");
		exit(1);							//退出进程,指定返回值1
	}
	else if (pid > 0)						//父进程
	{
		printf("parent process,pid=%d,ppid=%d\n", getpid(), getppid());
	}
	else if (pid == 0)						//子进程
	{
		printf("child process,pid=%d,ppid=%d\n", getpid(), getppid());
	}
	printf("........finish..........\n");
	return 0;
}

在这里插入图片描述
案例2:创建多个进程
for循环
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
	pid_t pid;
	int i;
	for (i = 0; i<5; i++){				//循环创建进程
		if ((pid = fork()) == 0)		//若当前进程为子进程,便跳出循环
			break;
	}
	if (pid == -1){
		perror("fork error");
		exit(1);
	}
	else if (pid>0){					//父进程
		printf("parent process:pid=%d\n", getpid());
	}
	else if (pid == 0){					//子进程
		printf("I am child=%d,pid=%d\n", i + 1, getpid());
	}
	return 0;
}

在这里插入图片描述
顺序不递增?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 	#include <stdio.h>
 #include <stdlib.h>
 	#include <unistd.h>
    int main()
 	{
 	    pid_t pid;
 	    int i;
 	    for(i=0;i<5;i++){
 	        if((pid=fork())==0)
	            break;
	    }   
 	    if(pid==-1){
	        perror("fork error");
	        exit(1);
     }   
	    else if(pid>0){
 	        sleep(5);
 	        printf("parent pid=%d\n",getpid());
	    }   
 	    else if(pid==0){
	        sleep(i);
	        printf("I am child%d pid=%d\n",i+1,getpid());
     }   
    return 0;
 	}

在这里插入图片描述

在这里插入图片描述

数据共享机制

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

exec函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
案例6-3:在程序中创建一个子进程,之后使父进程打印自己的pid信息,使子进程通过exec函数族获取系统命令文件,执行ls命令。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
	pid_t pid;
	pid = fork();
	if (pid == -1)
	{
		perror("fork error");
		exit(1);
	}
	else if (pid > 0)
	{
		printf("parent process:pid=%d\n", getpid());
	}
	else if (pid == 0)
	{
		printf("child process:pid=%d\n", getpid());
		//execl("/bin/ls","-a","-l","test_fork.c",NULL);	//①
		//execlp("ls","-a","-l","test_fork.c",NULL);		//②
		char *arg[] = { "-a", "-l", "test_fork.c", NULL };			//③
		execvp("ls", arg);
		perror("error exec\n");
		printf("child process:pid=%d\n", getpid());
	}
	return 0;
}

在这里插入图片描述
这里查询的是test_fork.c的
在这里插入图片描述
在这里插入图片描述

进程退出 exit

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

特殊进程

在这里插入图片描述

进程同步

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

wait()函数

在这里插入图片描述
案例6-4:若子进程p1是其父进程p的先决进程,使用wait()函数使进程同步。

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int main()
{
	pid_t pid, w;
	pid = fork();
	if (pid == -1){
		perror("fork error");
		exit(1);
	}
	else if (pid == 0){
		sleep(3);
		printf("Child process:pid=%d\n", getpid());
	}
	else if (pid > 0){
		w = wait(NULL);
		printf("Catched a child process,pid=%d\n", w);
	}
	return 0;
}

在这里插入图片描述

以上结果在执行程序3秒后输出,因为代码第13行使用sleep()函数使子进程沉睡3秒才执行。观察程序执行情况:子进程在程序执行3秒后完成并输出子进程pid;因为父进程中执行的操作只是回收子进程,所以父进程在子进程终止后立刻输出。由执行情况可知,父进程在子进程结束后才结束,父进程成功捕获了子进程。

当然,wait()函数中的参数可以不为空。若status不为空,wait()函数会获取子进程的退出状态,退出状态被存放在exit()函数参数status的低八位中。使用常规方法读取比较麻烦,因此Linux系统中定义了一组用于判断进程退出状态的宏函数,其中最基础的是WIFEXITED()和WEXITSTATUS(),它们的参数与wait()函数相同,都是一个整型的status。宏函数的功能分别如下:
(1)WIFEXITED(status):用于判断子程序是否正常退出,若是,则返回非0值;否则返回0。

(2)WEXITSTATUS(status):WEXITSTATUS()通常与WIFEXITED()结合使用若WIFEXITED返回非0值(即正常退出),则使用该宏可以提取子进程的返回值。

案例6-5:使用wait()函数同步进程,并使用宏获取子进程的返回值。

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int main()
{
	int status;
	pid_t pid, w;
	pid = fork();
	if (pid == -1){
		perror("fork error");
		exit(1);
	}
	else if (pid == 0){
		sleep(3);
		printf("Child process:pid=%d\n", getpid());
		exit(5);
	}
	else if (pid > 0){
		w = wait(&status);
		if (WIFEXITED(status)){
			printf("Child process pid=%d exit normally.\n", w);
			printf("Return Code:%d\n", WEXITSTATUS(status));
		}
		else
			printf("Child process pid=%d exit abnormally.\n", w);
	}
	return 0;
}

在这里插入图片描述

案例6-5的第6行中定义了一个整型变量status,该变量在wait()函数中获取子进程的退出码。之后通过宏WIFEXITED判断返回码是否为0,当不为0时,使用宏WEXITSTATUS将返回码转换为一个整型数据。

waitpid()函数

wait()函数具有一定局限性,若当前进程有多个子进程,那么该函数就无法确保作为先决条件的子进程在父进程之前执行,此时可使用waitpid()函数实现进程同步。

在这里插入图片描述
waitpid()函数比wait()函数多两个参数:pid和options。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
案例6-6.使父进程等待进程组中某个指定的进程,若该进程不退出,则让父进程一直阻塞。

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
	pid_t pid, p, w;
	pid = fork();							//创建第一个子进程
	if (pid == -1){							//第一个子进程创建后父子进程的执行内容
		perror("fork1 error");
		exit(1);
	}
	else if (pid == 0){						//子进程沉睡
		sleep(5);
		printf("First child process:pid=%d\n", getpid());
	}
	else if (pid > 0){						//父进程继续创建进程
		int i;
		p = pid;
		for (i = 0; i < 3; i++)					//由父进程创建3个子进程
		{
			if ((pid = fork()) == 0)
				break;
		}
		if (pid == -1){						//出错
			perror("fork error");
			exit(2);
		}
		else if (pid == 0){					//子进程
			printf("Child process:pid=%d\n", getpid());
			exit(0);
		}
		else if (pid > 0){					//父进程
			w = waitpid(p, NULL, 0);			//等待第一个子进程执行
			if (w == p)
				printf("Catch a child Process:pid=%d\n", w);
			else
				printf("waitpid error\n");
		}
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
案例6-7:使用waitpid)函数不断获取某进程中子进程的状态。

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
	pid_t pid, w;
	pid = fork();
	if (pid == -1){
		perror("fork error");
		exit(1);
	}
	else if (pid == 0){
		sleep(3);
		printf("Child process:pid=%d\n", getpid());
		exit(0);
	}
	else if (pid > 0){
		do{
			w = waitpid(pid, NULL, WNOHANG);
			if (w == 0){
				printf("No child exited\n");
				sleep(1);
			}
		} while (w == 0);
		if (w == pid)
			printf("Catch a Child process:pid=%d\n", w);
		else
			printf("waitpid error\n");
	}
	return 0;
}

在这里插入图片描述
案例6-7的父进程代码中设置了一个循环,在循环中调用waitpid()函数,并使用sleep()函数控制waitpid(),使其每隔1秒捕捉一次子进程信息;同时使子进程沉睡了3秒,因此父进程会输出3次Nochildexited。3秒后子进程终止,waitpid()成功捕获到子进程的退出信息并使父进程继续运行,从而输出捕提到的子进程id。

在这里插入图片描述

进程管理命令

在这里插入图片描述

ps

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
输出信息包含四项:pid:进程的id; TTY表明启动进程的终端; TIME 表示进程到目前为止真正占用CPU的时间
CMD表示启动该进程的命令

在这里插入图片描述
在这里插入图片描述
比如ps u
在这里插入图片描述
其中USER表示启动进程的用户,pid、TTY、TIME这些选项的含义与ps默认输出的相同,其余各项代表的含义分别如下:

  • %CPU表示进程占用CPU的时间与进程已运行时间的百分比,一般情况下这个数值不会达到100%。
  • ·%MEM表示进程的物理内存集与系统物理内存的百分比。VSZ表示虚拟内存集,即进程占用虚拟内存的大小(1024字节为一个单位)。
  • RSS表示驻留集大小,即进程使用的物理内存的大小(1024字节为一个单位)。
  • STAT表示进程当前的状态。D表示不可中断的睡眠态,R表示运行态,S表示可中断的睡眠态,T表示停止,Z表示低死态(即户进程)。状态之后的表示该进程是会话进程中的首进程。
  • COMMAND即CMD,表示启动该进程的命令

ps与sys风格如下
在这里插入图片描述
其余更多请查询linux系统的man手册

top

ps命令执行后,会显示执行命令那一刻系统中进程的相关信息。若想使信息动态地显示,可以使用命令top。
top命令的格式如下:

tpo -选项

在这里插入图片描述
在这里插入图片描述 图中第1行中显示的是top命令的相关信息,其中各项分别表示:系统当前时间为20:35:42:系统到现在已运行8分:系统中当前有1个用户登录:系统1分钟、5分钟、15分钟内的平均负载分别为0.04、0.23、0.21。

第2行显示与进程相关的信息:系统中共有141个进程,其中2个处于运行态,139个处于睡眠态,0个处于停止状态,0个处于死态。

第3行显示与CPU相关的信息,若系统是单核的,则这个信息只有一行:
若系统是双核或多核的,则每个CPU都会有对应的信息。其中各项分别表示:用户占用CPU的百分比为0.0%,系统占用CPU的百分比为0.0%,优先级被更改过的进程占用CPU的百分比为0.0%,空闲CPU的百分比为99.7%,1/O等待占用CPU的百分比为0.0%,硬中断占用CPU的百分比为0.0%,软中断占用CPU的百分比为0.3%,虚拟机被hypervisior(虚拟机监视器)愉去的时间所古的百分比为0.0%,

第4行显示与内存状态相关的信息:系统的物理内存总量为1867024KB.已经使用的内存总量为287724KB,空闲内存总量为1192408KB,缓存的内存量为386892KB

第5行显示swap交换分区的信息:交换区的总容量为2097148KB,已经使用的容量为0KB,空闲容量为2097148KB,缓冲的交换区容量为1378288kb。

以上几行信息的显示可以通过热键1、t、m来分别控制第6行为一个空行,之后黑色背景行为top命令默认显示的输出项。pid等项不再赞述,其余尚未介绍的输出项代表的含义分别如下;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当使用热键r、k时,第6行会给出相应的提示并等待输人。若要终止进程,在提示信息后输人要操作的进程的pid即可:若要重置优先级,按下热键r,输入pid后,第6行会提示输入nice值。

top的监测界面默认每隔3秒刷新一次,读者可以使用选项d自定义刷新间隔:top显示的内容只有一屏,超出一屏的进程无法查看,若想查看更多进程的状态,可以使用选项-b,该选项使用批处理的模式进行操作,一次显示一屏,3秒滚动一次;若只想观察某段时间内的变化情况,可以使用选项-n来指定循环显示的次数。top的选项还有很多,读者可通过man手册学习更多内容。

pstree

在这里插入图片描述

pgrep 选项 [参数]

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

nice

除了top命令 热键r重置优先级 也可以用这个
在这里插入图片描述
nice常用的选项为-n,n表示优先级,是一个整数。
nice的参数通常为一个进程名。假设进程top的优先级为0,要修改bash的优先级为5,则可以使用以下命令实现:

nice -n 5 bash

修改后可以用top查看bash 的优先级

nice命令不但能修改已存在进程的优在创建进程的同时,通过设置进程的nice值为进程设定优先级。假设当前top命令的此时选行的命令。优先级已被设置为5,那么再次调用t改其优先级为11,则应使用的命令如下所示:

nice -n 6 top

当更改nice值时,优先级PR和nice值NI都会改变,其变化的规律为:新值=原值+n,n为本次命令中指明的nice值

bg和fg

Linux系统中的命令分为前台命令后台命令。所谓前台命令,即在命令执行后,命令执行过程中的输出信息会逐条输出到屏幕,或者命令打开的内容(如i打开vim编辑器)会替代原来的终端命令,如压缩解压命令等:所谓后台命令,即命令执行后,不占用命令提示符,用户可继续在终端中输人命令,执行其他操作的命令

bg:

bg:将进程
bg 参数

也可以在命令后追加符号&,在进程创建时直接调入后台执行,其用法如下:

command &

使用快捷键组合Ctrl+Z也能将进程调人后台,但调入后台的进程会被暂时停止

fg:

在这里插入图片描述

在这里插入图片描述

jobs

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
jobs命令的参数为作业号,用于显示某个作业的信息。该命令一般与bg、fg命令配合使用。

##kill

在这里插入图片描述
可选的有信号

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值