【Linux】进程查看|fork函数|进程状态

这篇具有很好参考价值的文章主要介绍了【Linux】进程查看|fork函数|进程状态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

🦄 个人主页——🎐开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁

🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁🍁🪁🍁🪁 🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁

感谢点赞和关注 ,每天进步一点点!加油!

目录

一、基本概念

1.1 概念提出

1.2 特征

二、描述进程-PCB

2.1 什么是进程控制块PCB

2.2 task_struct内容分类(成员)

2.3 进程控制块如何对进程进行管理的呢?

三、查看进程

3.1 通过系统目录查看

3.2 通过用户级工具ps查看

四、通过系统调用获取进程标识符(PID)

4.1 使用getpid和getppid

五、通过系统调用创建进程-fork初识

5.1 fork函数

5.2 fork函数创建子进程

六、Linux进程状态

七、两种特殊进程

7.1 僵尸进程

7.2 孤儿进程


一、基本概念


1.1 概念提出


进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体(百度百科)。

1.2 特征


  • 动态性进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
  • 并发性:任何进程都可以同其他进程一起并发执行
  • 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
  • 异步性由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
  • 结构特征:进程由程序、数据和进程控制块三部分组成。

多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。


二、描述进程-PCB


引入一个新概念: 进程控制块PCB(process control block)。PCB就是进程属性的集合(数据结构),里面存储的是进程信息。

2.1 什么是进程控制块PCB


进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,称之为PCB(process control block),Linux操作系统下的PCB是: task_struct。

即task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含进程的信息。

2.2 task_struct内容分类(成员)


  • 标示符(PID): 描述本进程的唯一标示符,用来区别其他进程(每次启动都会变化)。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器(pc): 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  • 上下文数据: 进程执行时处理器的寄存器中的数据。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟总和,时间限制,记账号等。
  • 其他信息

2.3 进程控制块如何对进程进行管理


  • 磁盘中的可执行程序在将要运行时,所有的进程中的数据(并不是程序本身)加载到内存中,此时操作系统会建立起一个PCB来保存每一个程序的信息;
  • 这个时候PCB就会对每一个进程都建立起相应的结构体(即进程控制块)将对应的进程的属性、代码等匹配的传到这个结构体中:(这就是先描述)
  • 此时,操作系统就会将每一个进程控制块都连接起来,形成链表结构,并返回头结点。这样便通过数据结构的形式将进程的信息组织起来。

三、查看进程


3.1 通过系统目录查看


根目录下的proc目录,/proc下存储着进程信息。

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程
目录名为数字的即为进程信息的目录,每个目录内存储着他们对应的进程信息。而这些数字对应着该进程的标识符PID。如下查看标识符PID=18964的进程信息:

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

我们进入进程 18964进程目录

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

3.2 通过用户级工具ps查看


实例:ps ajx/ps aux

该命令可以查看所有系统进程。如下查看PID=18964的进程信息

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

创建如下测试脚本并执行

#!/bin/bash
 
proc_test()
{
	while(true)
	do
		echo "I am a process!"
		sleep 1
	done
}

proc_test

## 执行
sh proc_test_18964.sh

另外通过指令对进程进行检测,检测它是否运行:

ps ajx | head -1 && ps ajx | grep  proc_test  | grep -v grep

这里grep实际也是进程,且该进程内包含有proc_test的信息,所以也显示出来了。-v选项是反向搜索的意思,即过滤掉包含有grep内容的信息。

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

  • PPID (Parent Process ID):代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PID (Process ID): 代表这个进程的代号
  • PGID(Process Group):PGID就是进程所属的Group的Leader的PID,如果PGID=PID,那么该进程是Group Leader
  • SID(Session ID):和PGID非常相似,SID就是进程所属的Session Leader的PID,如果SID==PID,那么该进程是session leader
  • TPGID:终端进程组ID
  • STAT:进程状态

四、通过系统调用获取进程标识符(PID)


4.1 使用getpid和getppid


#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
	pid_t id = getpid();
	while (1)
	{
		printf("I am a process!pid:%d\n", id);
		sleep(1);
	}
	return 0;
}

执行上面可执行程序并运行如下命令进行监控

while :; do   ps ajx | head -1 && ps ajx | grep  proc_test  | grep -v grep ; sleep 1;done

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

函数getppid(获取父进程的进程标识符),一般在Linux中普通进程都有他的父进程。

每一个子进程都是由父进程创建出来的。

子进程只能有一个父进程,父进程可以有多个子进程。每次执行可执行程序,进程标识符会改变,因为每次都会创建新的进程。

编写如下测试代码

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    pid_t id = getpid();
    pid_t fid = getppid();
    while (1)
    {
        printf("I am a process!pid:%d ppid:%d\n", id, fid);
        sleep(1);
    }
    return 0;
}

 执行结果如下图:

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

 多次执行我们发现程序多次执行子进程每次都会创建新的新的进程标识符,父进程标识符没有改变。如下父进程是bash命令行解释器。

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程


五、通过系统调用创建进程-fork初识


5.1 fork函数


pid_t  fork(void);

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程 一个进程包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。

5.2 fork函数创建子进程


创建测试代码: 

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
 
int main()
{
    pid_t pid;
	printf("before fork : pid is : %d, ppid is : %d\n", getpid(), getppid());
 
	pid=fork();
 
	printf("after fork : pid is : %d, ppid is : %d, fork return %d\n", getpid(), getppid(),pid);
	sleep(2);
	return 0;
}

编译后执行【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

fork函数执行后,后面的"after fork"执行了两次,8897作为父进程创建了子进程 8898。也就是说fork之后,代码共享,从一个进程分为两个分支,一为父,一为子。

进程调用fork,当控制转移到内核中的fork代码后,内核会:

  • 分配新的内存块和内核数据结构给子进程;
  • 将父进程部分数据结构内容拷贝至子进程;
  • 添加子进程到系统进程列表当中;
  • fork返回,开始调度器调度;

所以,fork之前父进程独立执行,fork之后父子两个执行流分别执行。注意:fork之后谁先执行完全由调度器决定。【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

fork它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

(1) 在父进程中,fork返回新创建子进程的进程ID;

(2)在子进程中,fork返回0;

(3)如果出现错误,fork返回一个负值;

一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。


六、Linux进程状态


进程状态:

TASK_RUNNING:就绪/可运行状态

TASK_INTERRUPTABLE:进程被挂起(睡眠),直到等待条件为真被唤醒

TASK_UNINTERRUPTABLE:深度睡眠,睡眠期间不响应信号

TASK_STOPPED:进程的执行被暂停

TASK_TRACED:被其它进程跟踪,常用于调试

EXIT_ZOMBIE:僵死状态,进程的执行被终止

EXIT_DEAD:僵死撤销状态,防止wait类系统调用的竞争状态发送【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

可以使用man ps 查看进程状态 Ss、Sl、S+、Z、I 释义

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

具体解释如下:

  • D (TASK_UNINTERRUPTIBLE) 不可中断的睡眠状态
  • R (TASK_RUNNING) 正在运行,或在队列中的进程
  • S (TASK_INTERRUPTIBLE)     可中断的睡眠状态
  • T (TASK_STOPPED)    停止状态
  • t (TASK_TRACED) 被跟踪状态
  • Z (TASK_DEAD - EXIT_ZOMBIE) 退出状态,但没被父进程收尸,成为僵尸状态
  • W            进入内存交换(从内核2.6开始无效)
  • X (TASK_DEAD - EXIT_DEAD)   退出状态,进程即将被销毁
  • <    高优先级
  • N    低优先级
  • L    有些页被锁进内存
  • s    包含子进程
  • 位于前台的进程组;
  • l   多线程,克隆线程  multi-threaded (using CLONE_THREAD, like NPTL pthreads do)

七、两种特殊进程


7.1 僵尸进程


1.僵死状态(Zombies)是一个比较特殊的状态。当子进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程

2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

测试代码 :


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    pid_t id = fork();
    if (id < 0) {
        perror("fork");
        return 1;
    }
    else if (id > 0) { //parent
        while(1)
        {
            printf("parent[%d] is sleeping...,ppid: %d\n", getpid(),getppid());
            sleep(1);
        }
    }
    else {
        printf("child[%d] is begin Z...,ppid: %d\n", getpid(),getppid());
        sleep(5);
        exit(1);
    }
    return 0;
}

fork函数执行后子进程PID:15156 在5 s后exit(1)异常退出 ,父进程15155没有读取到正常的退出代码导致产生僵尸进程。【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

进程PID:15156的名称加上了【】且后面跟着< defunct > (失效的)【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

7.2 孤儿进程


【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

修改代码,让子进程和父进程同时不间断运行

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
	pid_t id = fork();
	if (id < 0) {
		perror("fork");
		return 1;
	}
	else if (id > 0) { //parent
             while(1)
             {
		printf("parent[%d] is sleeping...,ppid: %d\n", getpid(),getppid());
		sleep(1);
             }
	}
	else {
             while(1)
             {
		printf("child[%d] is begin Z...,ppid: %d\n", getpid(),getppid());
		sleep(1);
             }
	}
	return 0;
}

运行

while :; do ps ajx | head -1 && ps ajx | grep pro_test | grep -v grep ; sleep 1;done

监控进程状态

【Linux】进程查看|fork函数|进程状态,Linux,linux,process,PCB,fork函数,getppid,僵尸进程,孤儿进程

杀掉父进程(10552),子进程被编号为1的进程接管,该1号进程就是bash,而bash就是父进程的父进程,父进程被杀死后,bash进程就接管了子进程,这种失去“爸爸”后被接管的进程就被称为孤儿进程。且子进程从前台进程变成了后台进程。


原文链接:fork函数详解-CSDN博客

【Linux】进程周边001之进程概念-CSDN博客

fork()函数详解_fork函数-CSDN博客

原文链接:Linux进程状态_task_interrupt-CSDN博客文章来源地址https://www.toymoban.com/news/detail-761221.html

到了这里,关于【Linux】进程查看|fork函数|进程状态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [入门篇]Linux操作系统fork子进程的创建以及进程的状态 超超超详解!!!我不允许有人错过!!!

    目录 0.前言 1.fork()创建子进程讲解 1.1fork()的简单介绍 1.2 创建子进程详解 1.2.1 如何理解fork创建子进程 1.2.2 子进程的PCB以及子进程的代码和数据 1.2.3为什么要共享写时拷贝 1.2.4 什么时候发生写时拷贝 1.3 fork函数返回值详解 1.3.1引入fork返回值的作用 1.3.2 fork返回执行逻辑剖析

    2024年03月21日
    浏览(45)
  • 2.【Linux】(进程的状态||深入理解fork||底层剖析||task_struct||进程优先级||并行和并发||详解环境变量)

    Linux把所有进程通过双向链表的方式连接起来组成任务队列,操作系统和cpu通过选择一个task_struct执行其代码来调度进程。 1.运行态:pcb结构体在运行或在运行队列中排队。 2.阻塞态:等待非cpu资源就绪(硬盘,网卡等资源) 3.挂起态:一个进程对应的代码和数据被操作系统因

    2024年01月22日
    浏览(37)
  • 《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(26)
  • Linux 查看进程状态

    1、进程描述         Linux 系统中时刻运行着很多进程,如果能够合理的管理进程,我们就可以优化系统的性能。 在Linux系统中,有5中常见的进程状态,运行、中断、不可中断、僵死、停止         ps 命令查看 Linux 查看进程  2、每个进程状态所表示的含义 3、进程状态 4、

    2024年02月12日
    浏览(25)
  • Linux系统调用之fork,getpid,getppid函数(进程相关函数,与G老师的对话,必看!)

    如果,想要深入的学习Linux系统调用中的fork,getpid,getppid函数,还是需要去自己阅读Linux系统中的帮助文档。 具体输入命令: man 2 fork/getpid/getppid 即可查阅到完整的资料信息。 fork() 函数是 UNIX/Linux 系统中的一个系统调用 (system call),它会创建一个新的进程,称为子进程,该

    2024年02月08日
    浏览(36)
  • Linux基础命令-ps查看进程状态

    Linux基础命令-sort内容排序 Linux基础命令-chattr更改文件隐藏属性 文章目录 前言 一 命令的介绍 二 语法及参数 2.1 通过help和man查看命令的语法 2.2 命令参数 2.3 常用参数 三 参数使用与内容含义 3.1 查看系统当中所有的数据 3.1.1 ps aux中状态栏的含义 3.1.2 STAT进程状态各自代表的含

    2024年02月03日
    浏览(35)
  • 操作系统练习:在Linux上创建进程,及查看进程状态

    进程在执行过程中可以创建多个新的进程。创建进程称为“父进程”,新的进程称为“子进程”。每个新的进程可以再创建其他进程,从而形成进程树。 每个进程都有一个唯一的进程标识符(process identifier,pid)。在Linux中,init进程是所有其他进程的根进程。 在Linux中,可以

    2024年02月12日
    浏览(39)
  • Linux——信号处理函数与阻塞状态的进程

    这篇博客记录一下我在编写一个简单的多进程回声服务器的时候出现的问题。 这个问题就在于忽略了几个有关于信号处理函数的基本常识: 用通俗的话讲信号注册函数(signal、sigaction)的功能:进程告诉操作系统,当以后收到向信号注册函数传入的信号时,你帮我调用一下信号

    2024年02月13日
    浏览(29)
  • 【Linux初阶】fork进程创建 & 进程终止 & 进程等待

     🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【Linux初阶】 ✒️✒️本篇内容:fork进程创建,理解fork返回值和常规用法,进程终止(退出码、退出场景、退出方法、exit),进程等待(wait、waitpid),阻塞等待和非阻塞等待 🚢🚢作者简介:本科在读,计算机海洋

    2024年02月06日
    浏览(33)
  • Linux------进程的fork()详解

    目录 前言 一、fork()的使用 二、fork()的返回值 我们为什么要创建子进程? 父进程与子进程的分流 三、fork的一些难理解的问题 1.fork干了什么事情? 2.fork为什么会有两个返回值  3.fork的两个返回值,为什么会给父进程返回子进程pid,给子进程返回0? 4.fork之后,父子进程谁先

    2024年01月18日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包