进程基本概念及简单操作1

7 篇文章 0 订阅

进程概念

进程是什么:

  • 进程是系统进行资源分配和调度的基本单位.
  • 简单来理解进程就是系统中正在运行的程序;
    详细来说进程是操作系统对一个运行中程序的描述,通过这个描述信息,实现对程序的调度运行;[例如: 通过描述信息中的内存指针能够找到内存中运行的程序代码及数据,并且通过上下文数据可以保存程序切换调度时正在处理的数据, 以及通过程序计数器保存进程切换时即将执行的下一步命令等等…]

操作系统对进程的控制是通过一个数据结构 PCB(进程控制块 Process Control Block) 来实现的.在Linux下这个保存描述进程信息的数据结构叫做task_struct
task_struct 中包含以下元素:

 - 标识符: 	描述一个进程的唯一标识符,用来区别其它进程
 - 状态:   	描述进程的执行状态(运行/阻塞等)
 - 优先级: 	一个进程对于CPU资源获取的优先权----权级用数字表示
 		  	进程的优先级决定了cpu调度优先权的级别(设置进程优先级的目的是为了让操作系统运行的更加良好,进而提升用户体验)
 - 程序计数器: 	进程下一步执行的指令的地址
 - 内存指针: 	指向程序代码的指针
 - 上下文数据: 	指令执行时寄存器中的数据
 - IO状态信息: 	I/O使用请求等
 - 记账信息: 	处理器的时间总和
 - 其它信息

深入了解请参考 task_struct 源码

进程信息的查看

常用的进程查看指令:

  • ps -ef: 查看所有的进程信息
  • ps -aux: 查看内存中的进程信息
  • ps -l: 列出与本次登录有关的进程详细信息
    ps 指令查看的是进程信息的一个快照,显示的我们执行ps这个命令时进程的信息
    top 指令显示的是进程的动态信息,使用这个命令会看到进程信息的动态变化。
ps指令 常见选项
 a 	显示现行终端机下的所有程序,包括其他用户的程序。
-A 	显示所有程序。
 c 	列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
-e 	此参数的效果和指定"A"参数相同。
 e 	列出程序时,显示每个程序所使用的环境变量。
 f 	用ASCII字符显示树状结构,表达程序间的相互关系。
-H 	显示树状结构,表示程序间的相互关系。
-N 	显示所有的程序,除了执行ps指令终端机下的程序之外。
 s 	采用程序信号的格式显示程序状况。
 S 	列出程序时,包括已中断的子程序资料。
-t	<终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。
 u 	以用户为主的格式来显示程序状况。
 x 	显示所有程序,不以终端机来区分。

常用ps -aux 指令 在结合管道 | 加 grep指令过滤查找指定的进程

进程的创建

在Linux系统中,系统启动后的第一个进程由系统来创建, 叫做根进程.其余的进程都由已经存在的进程来创建,由已创建的进程创建的新进程叫做子进程,而创建子进程的进程叫作父进程,具有同一个父进程的进程叫做兄弟进程.
进程创建过程:
进程创建过程

子进程的创建

在Linux中, 子进程是由父进程以分裂的方式创建的, 创建一个子进程的系统调用fork()
由上文可知:系统是通过PCB来表示进程的,所以创建新进程就是要创建一个新的PCB,而创建一个新的PCB最简单的方法就是复制.但是由于进程的特性,导致不能完全复制,比如每个进程都有唯一的标识符,父子进程的代码共享,数据区和栈区独有.
在Linux下 通过man fork 来认识fork
fork(): 创建子进程(通过复制的方式创建了一个新的进程)
fork 有三种返回值:

  • 小于 0 表示创建子进程失败
  • 等于 0 表示是子进程
  • 大于0 (其实是子进程的pid) 表示是父进程

父子进程 代码共享,数据独有(数据是各自开辟空间保存,使用写时拷贝技术)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
	int ret = fork();
	if(ret < 0){
		perror("fork");
		return 1;
	}
	else if(ret == 0){ //child
		printf("I am child : %d!, ret: %d\n", getpid(), ret);
	}else{ //father
		printf("I am father : %d!, ret: %d\n", getpid(), ret);
	}
	sleep(1);
	return 0;
}

进程的状态

一个进程可以有多个状态,下面是kernel 源码中 进程状态的定义

/*
 - 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 */
};
  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

僵尸进程

处于僵死状态的进程(进程已经退出, 但是资源没有完全释放)
僵尸进程不可恢复
僵尸进程的产生原因:
子进程先于父进程退出 一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程(也就是进程为中止状态,僵死状态)。
僵尸进程的危害:
资源泄露(一个用户所能创建的进程数量是有限的, 并且资源没有完全回收会占据内存资源)
僵尸进程的避免:

  • 进程等待
  • 退出父进程(父进程退出后,子进程的退出原因就没有必要在保存了,因此也就被释放掉了)
    僵尸进程演示:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
	pid_t pid = fork();
    if(pid < 0)
    {
          perror("fork error");
          return -1;
    }
    else if(pid == 0)
    {
           printf("child[%d] is begin Z...\n", getpid());
           sleep(5);//为了方便我们观察子进程退出之前的状态
           exit(0);
    }
    else
    {
           sleep(30);//为了使子进程先于父进程退出
           printf("parent[%d] is sleeping...\n", getpid());
    }
    while(1)
    {
           sleep(1);
    }
    return 0;
}

父子进程都未退出时
在这里插入图片描述
子进程退出,父进程未退出.子进程变为僵尸进程
在这里插入图片描述

孤儿进程

一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作;
特性:

  • 孤儿进程运行在系统后台
  • 孤儿进程是不会成为僵尸进程的, 因为一号进程随时关注子进程退出.
    孤儿进程演示:
[#include<stdio.h>
#include<unistd.h>
 
int main()
{
    pid_t pid = fork();
        if(pid < 0)
        {
                return -1;
        }
        else if(pid == 0)
        {
                sleep(10);//父进程先退出
                printf("this is child\n");
        }
        else
        {
                sleep(5);
                printf("this is parent\n");
        }
        return 0;
}](https://img-blog.csdnimg.cn/20200908224254331.png#pic_center)

父子进程都未退出:
在这里插入图片描述
父进程退出, 子进程未退出,成为孤儿进程,被一号进程收养
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值