进程的基本概念、查看、创建

1. 进程的概念

概念:加载到内存的程序/正在运行的程序称为内存
我们在玩电脑的时候是可以启动多个程序的,比如边听歌边写博客,根据上篇文章我们知道肯定要将多个.exe文件加载到内存中,作为操作系统肯定是要管理这多个加载到内存的程序。如何管理呢?六个大字,先描述再组织。

2. 进程的描述

进程的信息被放在一个叫进程控制块(process control block)PCB,可以理解成一个进程属性的集合。
linux描述一个进程的结构体叫task_struct(PCB的一种)。该结构体有非常多的字段,我们挑几个常见的字段。

struct task_struct
{
	标识符:唯一标识符,用于区别其他进程
	状态:任务状态、退出代码、退出信号
	优先级:相对于其他进程的优先级
	程序计算器:程序中即将被执行的指令的地址
	上下文数据:进程执行时处理器的寄存器中的数据
	I/O状态:包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表
	记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
	....
}

3. 进程的组织

将多个进程描述成多个PCB结构体,再将各个PCB链接起来,所以对进程的管理就转化成对PCB结构体的管理。
在这里插入图片描述

所以一个进程等于:可执行程序(.exe)+内核数据结构(PCB)

4. 查看一个进程

使用ps指令来查看一个指令,下面是一个程序的代码,用于测试

int main()
{
    while(1)
    {
   		printf("I am a process!!!\n");
        sleep(1);
    }
    
   return 0;
}

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

在这里插入图片描述

PID就是上面说的标识符,可以使用系统函数getpid()获得,PPID则是父进程的标识符,可以使用getppid()。

int main()
{
    while(1)
    {
   		printf("I am a process!!! pid:%d ppid:%d\n",getpid(),getppid()");
        sleep(1);
    }
    
   return 0;
}

在这里插入图片描述

除了用ps指令查看一个进程,linux还将进程的信息存放在了一个叫proc的文件夹中。

在这里插入图片描述
我们来单独查看一个进程(PID为4630)是什么样的

在这里插入图片描述

5. 创建一个进程

运行一个程序就相当于创建一个进程,那么能用代码的形式创建一个进程吗?fork()函数就可以解决这个问题。
我们先来看一段代码:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     printf("before fork:pid: %d ppid: %d\n",getpid(),getppid());
  8     fork();
  9     printf("after  fork:pid: %d ppid: %d\n",getpid(),getppid());                                                                                                   
 10     return 0;
 11 }

在这里插入图片描述
可以看到fork之后有两个进程了,且它们是父子关系,fork()之后的代码共享。我们在来看看这个函数的原型。
在这里插入图片描述

再来看一段代码

 1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     printf("before fork:pid: %d ppid: %d\n",getpid(),getppid());
  8     pid_t id = fork();
  9     printf("after  fork:pid: %d ppid: %d\n returnid: %d",getpid(),getppid(),id);                                                                                   
 10                                                                                                                                              
 11     sleep(2);                                                                                                                                
 12     return 0;                                                                                                                                
 13 }   

在这里插入图片描述
从结果可以看出,如果是父进程fork的返回值是子进程的pid,而子进程的fork返回值是0,我们可以通过这个特性很好的分流执行代码。

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     printf("before fork:pid: %d ppid: %d\n",getpid(),getppid());
  8     pid_t id = fork();
  9     if(id < 0)
 10         return -1;
 11     if(id == 0)
 12     {
 13         while(1)
 14         {
 15          printf("after  fork, 我是子进程:pid: %d ppid: %d returnid: %d\n",getpid(),getppid(),id);
 16              sleep(2);
 17         }
 18     }
 19     else
 20     {
 21         while(1)
 22         {
 23          printf("after  fork,我是父进程:pid: %d ppid: %d returnid: %d\n",getpid(),getppid(),id);
 24          sleep(2);                                                                                                                                                  
 25         }
 26     }
 27 
 28     sleep(2);
 29     return 0;
 30 }

在这里插入图片描述

看完简单的使用之后,我们再来思考三个问题?

fork为什么给父进程返回子进程的pid,而给子进程返回0?因为父进程有很多子进程,难以找到某个子进程,所以返回子进程的pid,但是子进程只有一个父进程,使用getppid就能得到父进程的pid了。

为什么一个函数会返回两个值?因为在fork这个函数内部,return语句之前的代码执行完之后,已经创建了子进程,所以会共享代码,return语句就执行了两遍。

为什么一个变量会有两个值?这个问题与进程地址空间有关,后面才会理解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值