Linux下理解进程,fork()创建子进程

进程初认识

进程的概念(比较抽象):程序运行的实体

                                  作为资源分配的基本单元

 

//hello.c
#include <stdio.h>                                                                                                               
#include <unistd.h>//操作系统头文件 
int main()
{
     printf("change world\n");
      while(1)
      {
          //Windows下sleep();休眠毫秒ms
          sleep(1);//Linux下休眠单位秒s
          //usleep(10000);//Linux下休眠单位微秒us
      }
      return 0;
 }

我们知道运行这个程序后,是进入一个死循环,但我们在另外一个终端查看进程状态时

查看进程状态:ps

Ps aux (以该用户主形式查看所有终端机下所有用户的进程)

ps aux | grep hello

//以下是对ps后各个字段的解释

USER   (所属用户)

PID    (进程PID进程唯一标识)

%CPU  (cpu使用率)

%MEM (物理内存使用率)

VSZ    (虚拟内存使用情况)

RSS    (物理内存使用情况)

TTY    (终端的次要装置号码)

STAT   (进程状态)

START  (进程创建时间)

TIME   (进程执行时间)

COMMAND(进程名)

 

 程序:可执行的二进制文件(磁盘中)

 进程:可执行的二进制文件(内存中)+进程PCB


进程pcb

:task_struct一个描述进程的结构体

1.标识符:描述本进程的唯一标识,用来区别其他进程

2.状态:进程状态,退出代码,

3.优先级:进程相对于其他进程的优先级别

4.程序计数器:程序中即将被执行的的下一条指令的地址,(cpu中的eip寄存器也有一份)

5.内存指针:程序代码和进程相关数据的指针,包括和其他进程共享的内存的指针

6.上下文数据:进程执行时cpu中的寄存器中的数据(保存进程执行的相关状态)

7.I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和进程使用的文件列表

8.记账信息:处理器执行时间总和,时间限制,记账号等,

下面详细介绍以下进程标识符:

pid_t pid;//子进程标识符

pid_t ppid;//父进程标识符

pid_t uid;//用户标识符

pid_t git;//组标识符

pid_t euid;//有效用户标识符

例如:

#include <stdio.h>
#include <unistd.h>                                                                                                                  
 
int main()
{
   pid_t pid=getpid();
   pid_t ppid=getppid();
   printf("%d\n%d\n",pid,ppid);
   printf("hello world");
   while(1)
    {
       //Windows下sleep();休眠毫秒ms
       sleep(1);//Linux下休眠单位秒s
       //usleep(10000);//Linux下休眠单位微秒us
   }   
   return 0;
}


用下面命令进行查看进程的父进程,可以看到其父进程为bash进程(用户命令与操作系统之间的媒介)


下面详细介绍进程的状态:

R  (running)    0就绪状态,包含正在执行或者就绪状态(一切资源就绪只差分配cpu

S  (Sleeping)    1睡眠状态,中断睡眠,可以被唤醒,例如调用sleep();

D  (disksleep)   2 深度睡眠状态,磁盘休眠状态,不可唤醒,不可kill掉,例如,该进程正在密集的进行I/o

T  (stopped)    4 暂停状态,可以通过SIGTOP,将进程由S ,R状态转换为T状态,例如pause,挂起状态

t  (tracingstop)  8 跟踪状态

X (dead)  死亡状态,一般是看不见的

Z (zombie)僵尸进程,当进程退出后,并且父进程没有读取到子进程的返回代码,就会产生僵尸进程。


  

#include <stdio.h>
#include <unistd.h>
int main()
{
   pid_t ret=fork();//创建一个进程,(父进程分裂为两个进程)有两个返回值,
   if(ret==0){
       printf("ret:%d\n",ret);
       printf("this if a child process,the pid id %d\n",getpid());
           sleep(1);    }   
   else
   {if(ret>0){
           printf("ret:%d\n",ret);
           printf("this is a parent process,the pid is %d\n",getpid());
           while(1)
           {;}                                                                                                                       
       }   
       else
           perror("fork");
   }   
return 0;
}


 

 

这里可以看到子进程为Z僵尸状态。

而且,我们发现僵尸进程是不能直接kill掉的




我们可以将僵尸进程的父进程kill


其实这里是,将僵尸进程的父进程kill掉之后,子进程就会成为孤儿进程并且被1号进程领养,

1号进程会接收到该孤儿进程的退出码,这时的僵尸进程正常结束了。

 

 

在这里补充一下:

因为我们在windows下很少看到cpu占用率为100%,因为windows下是这样来计算的,例如,一个5核的处理器,当只有一个被全部使用时,这时可以看到cpu利用率是 20%,两个cpu被全部使用时,这时的cpu利用率为40%,以此类推。

但是在Linux下,同样是5核的处理器,当只有一个被全部使用时,显示cpu的利用率为100%,两个被全部使用时,这时的cpu利用率为200%.以此类推

 

进程优先级:


中的pri一项为进程的优先级,这个数字越小,表示优先级越高,低于80

Ni一项为优先级的修正值,其实我们是没有办法直接修改一个进程的优先级,例如最后一项ni-20 ,其优先级为60 其实就是80-20;

创建进程:

pid_t fork();

两个返回值,一个在父进程中返回,一个在子进程中国返回,会将父进程复制一次,并且进程从fork();后面开始执行(进程上下文数据中包含eip,保存了下一条执行的地址)。

父进程中返回子进程的pid;

子进程返回0:

例如:

#include <stdio.h>                                                                                                                    
#include <unistd.h>
int main()
{
    pid_t ret=fork();//创建一个进程,(父进程分裂为两个进程)有两个返回值,
    if(ret==0){
        printf("ret:%d\n",ret);
        printf("this if a child process,the pid id %d\n",getpid());
    }   
    else
    {   
        if(ret>0){
            printf("ret:%d\n",ret);
            printf("this is a parent process,the pid is %d\n",getpid());
        }   
        else
            printf("fork error\n");
    }   
    return 0;
}

 

fork()的总结:

1.一次调用有两个返回值,父进程返回子进程的pid,子进程返回0

2.父进程和子进程都从fork()结束的下一条开始执行;

3.子进程以父进程为模板(PCB,数据和代码),写实拷贝;

4.父子进程之间时并发执行,顺序不确定,取决去操作系统调度;

5.fork()失败可能的原因是内存不够或者进程数量太多。

 

 

 

猜你喜欢

转载自blog.csdn.net/misszhoudandan/article/details/80032442