当前位置:   article > 正文

Linux下理解进程,fork()创建子进程_linux创建一个1到100累和的子进程

linux创建一个1到100累和的子进程

进程初认识

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

                                  作为资源分配的基本单元

进程的理解:什么是进程

 

 

  1. //hello.c
  2. #include <stdio.h>
  3. #include <unistd.h>//操作系统头文件
  4. int main()
  5. {
  6. printf("change world\n");
  7. while(1)
  8. {
  9. //Windows下sleep();休眠毫秒ms
  10. sleep(1);//Linux下休眠单位秒s
  11. //usleep(10000);//Linux下休眠单位微秒us
  12. }
  13. return 0;
  14. }

 

 

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

查看进程状态: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.优先级:进程相对于其他进程的优先级别 ,通过修改nice(NI)值,一般为-20到19 40个选项

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;//有效用户标识符

例如:

 

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main()
  4. {
  5. pid_t pid=getpid();
  6. pid_t ppid=getppid();
  7. printf("%d\n%d\n",pid,ppid);
  8. printf("hello world");
  9. while(1)
  10. {
  11. //Windows下sleep();休眠毫秒ms
  12. sleep(1);//Linux下休眠单位秒s
  13. //usleep(10000);//Linux下休眠单位微秒us
  14. }
  15. return 0;
  16. }

 

 

用下面命令进行查看进程的父进程,可以看到其父进程为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)僵尸进程,当进程退出后,并且父进程没有读取到子进程的返回代码,就会产生僵尸进程。

 

  

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main()
  4. {
  5. pid_t ret=fork();//创建一个进程,有两个返回值,
  6. if(ret==0){
  7. printf("ret:%d\n",ret);
  8. printf("this if a child process,the pid id %d\n",getpid());
  9. sleep(1); }
  10. else
  11. {if(ret>0){
  12. printf("ret:%d\n",ret);
  13. printf("this is a parent process,the pid is %d\n",getpid());
  14. while(1)
  15. {;}
  16. }
  17. else
  18. perror("fork");
  19. }
  20. return 0;
  21. }

 


 

 

这里可以看到子进程为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:

例如:

 

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main()
  4. {
  5. pid_t ret=fork();//创建一个进程,有两个返回值,
  6. if(ret==0){
  7. printf("ret:%d\n",ret);
  8. printf("this if a child process,the pid id %d\n",getpid());
  9. }
  10. else
  11. {
  12. if(ret>0){
  13. printf("ret:%d\n",ret);
  14. printf("this is a parent process,the pid is %d\n",getpid());
  15. }
  16. else
  17. printf("fork error\n");
  18. }
  19. return 0;
  20. }

 

 

 

对fork()的总结:

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

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

3.子进程以父进程为模板(PCB,数据各自有一份和代码共享),采用写实拷贝;

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

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

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/635171
推荐阅读
相关标签
  

闽ICP备14008679号