初始Linux中的进程--PCB

进程概念:

在普通的用户理解
进程或许就是运行中的程序,这样的理解也不算错但是只是太片面,理解的还不够充分。
而对于操作系统而言
因为cpu分时机制:操作系统调度每一个程序只在cpu上处理一段很短的时间(这个时间被称之为:时间片)然后就切换到另一个程序


进程:实际上就是一个运行中程序的描述(pcb process control block 进程控制块),一个程序运行中的状态 ,通过这个描述就可以实现一个程序的运行调度管理,而 linux 下这个pcb就是一个task_struct 结构体

这个pcb中含有非常多的信息,例如:

1.进程控制块PCB中的描述信息:
描述信息:
1.内存指针:指向要调度运行程序代码以及数据在内存中的位置
2.程序计数器:cpu要执行任何指令,都需要将指令加载到寄存器;承租计数器用于保存在cpu上即将执行的下一步指令的地址
3.上下文数据:保存cpu上正在处理的数据
4.进程标识符:进程id -- pid processid(进程唯一标识符)
5.进程状态:不同的状态敢不同的事情
6.进程优先级:决定获取cpu资源的优先权 -- 为了让程序运行的更加良好
7.IO信息:
8.记账信息
2.进程的创建以及查看进程
创建进程

pid_t fork(void);

在这里插入图片描述
可以看到 fork 这个函数是用来创建一个子进程的,这个函数包含在 <unistd.h> 里面,因此需要引入头文件 <unistd.h>
对 fork 函数的描述解释是:
通过复制调用进程创建新进程。新的进程(称为子进程)与调用完全相同进程,称为父进程。

这里我们写一个简单的 fork.c 程序来演示一下进程创建的过程。

#include<stdio.h>
#include<unistd.h>
int main()
{
        printf("hello\n");
        pid_t process1=fork();
        printf("world\n");
        return 0;
}

打印结果:
在这里插入图片描述
可以看到当我们创建了一个子进程之后,在上面的打印完成之后又打印了一遍 world ,同理我们在一开始就创建子进程的话就会打印两遍;
在这里插入图片描述
在这里插入图片描述
为了可以看到我们刚才创建的进程的相关信息,我们让他循环运行:
在这里插入图片描述
那么如何看到这个进程的相关信息呢?

查看进程信息指令

ps -ef
在这里插入图片描述
这里可以看到非常多的信息:

注:这里的:
UID 指的是用户的id 
PID 指的是进程的ID 进程的唯一标识符
PPID表示的是父进程的进程ID parent pid
STIME 表示什么时候开始运行的
TTY 表示在哪个终端上运行的
TIME 已经在cpu上运行了多长时间
CMD 表示在执行程序时使用了一个什么样的命令
例如正在执行的fork1进程使用了 ./fork1 
最后一个使用了 我们的 ps -ef 查询进程信息指令

在这里插入图片描述
例如:我们刚创建的fork1程序 ,创建了一个进程还创建了一个子进程,父进程的PID 是 4352 子进程的PPID也是 4352 因此可以说明子进程与父进程的关系。

在这里可以通过查看父子进程的PID 和PPID来进行父子进程的区分,但是在代码中如何区分呢?

获取进程ID/父进程ID

getpid/getppid
在这里插入图片描述可以看到 getpid()getppid() 这两个函数
getpid()返回调用进程的进程ID。(这通常由生成唯一临时文件名的例程使用。)
getppid()返回调用进程的父进程的进程ID。
显而易见这两个函数在代码中就可以获取进程的id
演示:

fork 函数的返回值比较特殊:
对于父进程来说:返回的是子进程的pid ;是大于0的 对于子进程来说返回的是0
通过这个返回值的不同,进行判断,就可以实现父子进程代码分流
子进程与父进程干同样的事情可以分摊压力;
父进程可以让子进程干其他的事情,让子进程背锅
代码演示:

#include<stdio.h>
#include<unistd.h>
int main()
{
        pid_t pid=fork();
        if(pid==0)
        {
                printf("this child-process ,pid==%d\n",pid);
        }
        if(pid>0)
        {
                printf("this parent-process,pid==%d\n",pid);
        }
        printf("hello\n");
        printf("world\n");
        return 0;
}

在这里插入图片描述
再使用getpid()和getppid()进行验证:

#include<stdio.h>
#include<unistd.h>
        int main()
{       while(1)
        {
                pid_t process=fork();
                pid_t Pid1=getpid();
                pid_t PPid1=getppid();
                usleep(10000000);
                printf("%d,%d,helloworld\n",Pid1,PPid1);
        }
        return 0;
}


在这里插入图片描述
在这里插入图片描述
可以看到这里可以获取到进程的 id 以及 该进程的父进程 id

2.进程状态
进程状态:就绪/运行/阻塞 三种概括性的状态

而在linux 下呢进程状态分为以下:

inux下进程状态:
1.运行状态(Running):正在运行/只要拿到时间片就能运行--- 这种进程调度到cpu上进行处理
2.可中断休眠状态(Sleep):当前处于休眠状态,但是这种休眠可以被打断;-- 不被cpu调度的
3.不可中断休眠状态(Disk Sleep):当前处于休眠状态,但是这种休眠不会被打断 
4.停止状态(Stop:什么都不干)
5,死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态
进程状态查看

指令:ps aux / ps axj
示例:
在这里插入图片描述
相关解释:

USER 进程的所有者;
PID 进程的ID;
PPID 父进程id;
%CPU 进程占用的CPU百分比;
%MEM 占用内存的百分比;
NI 进程的NICE值,数值大,表示较少占用CPU时间;
VSZ 该进程使用的虚拟內存量(KB);
RSS 该进程占用的固定內存量(KB)(驻留中页的数量);
TTY 该进程在那個終端上運行(登陸者的終端位置),若与终端无关,则显示(?)。若为pts/0等,则表示由网路连接主机程
START 该进程被触发启动时间;
TIME 该进程实际使用CPU运行的时间;
COMMAND 命令的名称和参数;

另外:

STAT 中的参数意义如下:
   D 不可中断 Uninterruptible(usually IO)
   R 正在运行,或在队列中的进程
   S 处于休眠状态
   T 停止或被追踪
   Z 僵尸进程
   W 进入内存交换(从内核2.6开始无效)
   X 死掉的进程

   < 高优先级
   n   低优先级
   s   包含子进程
   +   位于后台的进程组
几种比较特殊的进程

僵尸进程: 处于僵死状态的进程 : 一类 已经退出了但是资源没有被完全释放的进程
如何产生:子进程先于父进程退出,父进程没有关注子进程的退出状态(子进程为了保存自己的退出原因,因此没有完全释放资源)
如何避免:进程等待(等待子进程退出,然后并且收回子进程的资源,避免产生僵尸进程)
示例:

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

在这里插入图片描述
在这里插入图片描述
可以看到,这里使父进程厨艺一段时间的休眠状态使用 ps -aux 可以在相应的进程 ID 后面的 STAT 信息看到父进程处于 一个 S+ 后台休眠状态 ,而因为子进程 先退出了 造成了僵尸进程的出现 STAT显示为Z+ 僵尸进程。
孤儿进程:父进程先于子进程退出,子进程就会成为孤儿进程
特点:运行在后台,父进程成为1号进程
守护进程:就是一种特殊的孤儿进程,运行在后台,脱离终端与会话的影响,也叫daemon精灵进程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值