第二周---->进程

目录

1、如何查看进程

2、什么是进程

2.1 程序和进程的区别

2.2 进程是程序执行和资源管理的最小单位

2.3 进程分类

2.4 进程的状态

2.5 进程的相关函数

2.5.1 创建进程

2.5.2 进程退出

2.5.3 回收内核资源


1、如何查看进程

Window查看进程

Ctrl+Alt+Del

Linux查看进程

ps -ef 查看所有进程及其PID(进程号),系统时间,命令详细目录,执行者等。

ps aux 除可显示-ef所有内容外,还可显示CPU及内存占用率,进程状态。

top:动态显示系统中运行的程序

pstree 以树形方式显示系统中的进程

kill 输出特定的信号给指定PID(进程号)的进程

kill -l 查看所有可用的信号名称

2、什么是进程

2.1 程序和进程的区别

程序:程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念。

进程:进程是动态的,它是程序执行的过程,正在运行的程序,进程是程序执行和资源管理的最小单位。

2.2 进程是程序执行和资源管理的最小单位

每个进程都有独立的资源空间,当进程创建时,OS会为进程分配4G的进程空间,且每个进程都有1G内核空间和3G用户空间

进程资源主要分为两部分:内核空间资源,用户空间资源

内核空间资源:即PCB相关的信息,这些资源只有通过系统调用才能使用资源,例如PID、PPID、打开的文件描述符等等,这一资源在当前进程退出,只能由另一进程(父进程)来回收,若无回收,会造成僵尸进程,为了更好的管理Linux所访问的资源,在系统内核文件include/linux/sched.h中定义一个结构体struct task_struct专门管理进程的资源。

用户空间资源:进程的代码段,数据段,堆栈以及可以共享访问的库的内存空间,这些资源进程可以直接访问,该资源在进程退出时释放。

2.3 进程分类

1.交互式进程(经常使用),可以在前台运行,也可以在后台运行。

jobs:查看后台进程,只能在同一终端下使用.

fg 作业号 :将后台进程放前台运行.

2.批处理进程,这类进程不必与用户进行交互,因此通常在后台运行。

3.守护进程(重点)。这类进程一直在后台运行,和任何终端都不关联。通常系统启动时开始执行,系统关闭时才结束。

2.4 进程的状态

(1)运行态:R  进程当前正在运行或者正在运行队列中等待调度(就绪态)

(2)等待态

              可中断的等待  S  sleep(1)

              不可中断的等待  D

(3)停止态:T  进程的执行被暂停,当进程收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信号,都会被停止

(4)死亡态:X  这是最终状态

(5)僵尸态:Z  是个错误,需要我们去处理         

进程中的优先级

-20到19,值越大,优先级越低,普通用户设置优先级最大为0

修改优先级

nice 按用户指定的优先级运行进程

renice 改变正在运行进程的优先级

2.5 进程的相关函数

2.5.1 创建进程

pid_t fork

#include<sys/types.h> //提供类型pid_t的定义

#include<unistd.h>

pid_t fork(void);

返回值:0:子进程

              子进程PID(大于0的整数):父进程

              -1:出错

pid_t getpid(void);        获得进程的ID号

pid_t getppid(void);      获得父进程的ID号

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

int main(int argc, const char *argv[])
{
	pid_t pid;
	//创建子进程
	pid=fork();
	if(pid<0)//子进程创建失败
	{
		perror("fork error");
		return -1;
	}else if(pid==0)//返回为0表示该进程是子进程
	{
		printf("i am child process\n");
	}else if(pid>0)//返回0表示该进程是父进程,返回的是子进程
	{
		printf("i am father process\n");
	}
	sleep(10);

	return 0;
}

vfork

       为了提高效率,Unix系统设计者创建了vfork。vfork也是创建新进程,但不产生父进程的副本。

 fork和vfork的区别

1、fork():子进程拷贝父进程的数据段,代码段。

   vfork():子进程与父进程共享数据段。

2、fork():父子进程的执行次序不确定。

   vfork():保证子进程先运行,在调用exec或_exit之前与父进程数据是共享的,在它调用exec或_exit之后父进程才可能被调度运行。

3、vfork()保证子进程先运行,在它调用exec或_exit之后父进程才可能被调用运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。当需要改变共享数据段中变量的值,则拷贝父进程。

2.5.2 进程退出

exit():      #include<stdlib.h>

_exit():    #include<unistd.h>

void exit(int status); //自带清理缓冲区

void _exit(int status); //不清理缓冲区

status:

是一个整型的参数,可以利用这个参数传递进程结束时的状态。通常0表示正常结束;其他的数值表示出现了错误,进程非正常结束。在实际编程时,可以用wait系统调用接收子进程的返回值,进行相应的处理。

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

int main(int argc, const char *argv[])
{
	printf("helloworld");
	//exit(0);//0一般表示正常结束  exit()自带清理缓冲区  
	fflush(stdout);//stdin 输入(2) stdout(1) 输出 stderr标准出错(2)
					//刷新缓冲区
	_exit(0);	//不清理缓冲区  
	printf("hellobeijing");
	return 0;
}

2.5.3 回收内核资源

wait()  阻塞等待子进程结束回收资源

#include<sys/types.h>

#include<sys/wait.h>

                                                                       

pid_t wait(int *status)

参数:

 返回值:成功:子进程的进程号

              失败:-1

waitpid()回收子进程资源

#include<sys/types.h>

#include<sys/wait.h>

pid_t waitpid(pid_t pid,int *status,int options)

参数1:pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去

              pid=0:等待其组ID等于调用进程的组ID的任一子进程

               pid<1:等待其组ID等于pid的绝对值的任一子进程

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

int main(int argc, const char *argv[])
{
	pid_t pid;
	//创建子进程
	pid=fork();
	if(pid<0)//子进程创建失败
	{
		perror("fork error");
		return -1;
	}else if(pid==0)//返回为0表示该进程是子进程
	{
		int j = 0;
		while(1)
		{
			if(j>=15) //当j>=15时,让子进程退出,可以把j当时的值返回
			{
				exit(j);
			}
			printf("recv cam\n");
			printf("i am child process,PID=%d PPID=%d\n",getpid(),getppid());
			sleep(1);
			j++;
		}
	}else if(pid>0)//返回0表示该进程是父进程,返回的是子进程
	{
		//阻塞等待子进程退出
		//弊端:子进程不结束,父进程永远没法进行
		//wait(NULL); //参数若为空,忽略子进程退出的状态
		//				参数若不为空,表示保存子进程退出时的状态
		while(1)
		{
			//回收子进程资源    需要轮询(写在while(1)内)
			//参数1 -1表示等待任意一个子进程退出
			//参数2 NULL表示忽略进程退出的状态
			//		不为空可以保存子进程退出时的状态
			//参数3 0表示阻塞等待 WNOHANG表示非阻塞等待,
			//					  若无子进程退出,返回值为0
			//					  若有子进程退出,返回值为退出的子进程号
			//waitpid(-1,NULL,0)  <--等价-->  wait(NULL)
			//waitpid(-1,NULL,WNOHANG);//非阻塞等待任意一个子进程退出
			//判断子进程是正常结束还是异常结束
			int status;//子进程退出的状态保存在status的低8位到低16位
			int id = waitpid(-1,&status,WNOHANG);
			if(id>0) //id>0表示子进程退出
			{
				if(WIFEXITED(status))
				{
					printf("正常退出的状态值:%d\n",WEXITSTATUS(status));
				}else if(WIFSIGNALED(status))
				{
					printf("信号值为:%d\n",WTERMSIG(status));
				}
				printf("send data\n");
				printf("i am father process,PID=%d\n",getpid());
				sleep(1);
			}
		}
	}
	sleep(10);

	return 0;
}

2.5.4 父子进程

(1)fork成功之后,分为父进程(pid>0)和子进程(pid==0),子进程几乎是父进程的完全复制,子进程独有进程号、资源使用和计时器等。

(2)父子进程谁先运行?看内核调度,不确定。

(3)能否多次调用fork()?可以,每调用一次,创建一个子进程。

(4)父进程先退出,子进程未结束,子进程成为孤儿进程,被systemd的进程收养,后台运行。

(5)子进程先退出,父进程未结束,并父进程没有回收子进程的资源,子进程成为僵尸进程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值