当前位置: 首页 > article >正文

Linux基础5-进程控制1(fork创建子进程,写时拷贝,进程退出)

上篇文章:Linux基础4-进程5(程序地址空间详解)-CSDN博客

本篇重点:fork,写实拷贝,进程退出

目录

一. fork创建子进程

1.1 fork用法

1.2 fork返回值有两个的理解

 二. 进程退出码

2.1 进程退出码

2.2 进程退出码所对应的退出信息 

三. 进程退出

四. 下篇重点:进程退出和阻塞,非阻塞等待

一. fork创建子进程

1.1 fork用法

上篇文章提到,我们可以使用fork来创建一个子进程,详细用法如下:

//所需头文件
#include <unistd.h>

//函数原型
pid_t fork(void);

//返回值
//成功的情况下,在父进程返回子进程的pid,在子进程中返回0
//失败则会返回-1

//子进程不会执行父进程fork之后的代码

fork常用于:

1 一个父进程希望复制自己,让子进程执行不同的代码段(如父进程等待客户端请求,生成子进程来处理收到的请求)

2 一个进程想要执行一个不同的程序,如创建子进程进行exec(进程替换)

1.2 fork返回值有两个的理解

1 为什么父进程返回子进程的pid,而子进程返回0?

        因为fork之后,各自执行自己的代码。各自获得自己的return值

2 为什么通过if,else可以让父子进程同时执行自己的代码?

        如:上篇文章提到的代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
 
int global_value = 100;
int main()
{
  pid_t id = fork();
  if(id < 0)
  {
    printf("fork error!\n");
    return -1;
  }
  else if(id == 0) //子进程
  {
    int cnt = 0;
    while(1)
    {
      printf("子进程,pid:%d ppid:%d | global_value:%d,&global_value: %p\n",getpid(),getppid(),global_value,&global_value);
      sleep(1);
      cnt++;
      if(cnt == 10)
      {
        global_value = 1234;
        printf("子进程已经修改了全局变量!\n");
      }
    }
  }
  else 
  {
    //父进程
    while(1)
    {
      printf("父进程,pid:%d ppid:%d | global_value:%d,&global_value: %p\n",getpid(),getppid(),global_value,&global_value);
      sleep(2);
    }
  }
  return 0;
}

我们在上篇文章知道了,父子进程一方写入会发生写实拷贝

        当我们调用了fork之后,return pid的时候就会发生写实拷贝,让父子进程有了不同的返回值,这样一来就能够通过if else 来判断各自的p返回值从而达到执行不同的代码

 二. 进程退出码

2.1 进程退出码

我们知道,一个程序结束之后我们会返回0

我们可以使用 下面这个命令获取上一次进程退出的返回值

echo $?

适当修改代码:

这个值我们称为进程退出码,通过进程退出码我们可以知道进程退出的信息!

进程退出后:

代码执行完了,并且返回了0:说明进程正常执行并且退出

代码执行完了,但是没有返回0:这个时候我们通过进程退出码,来获取相关信息

进程崩溃了,退出码就无意义

如:下例代码,正确返回0,计算失败返回1。由于sum我们最后加了100,所以返回值是1

#include <stdio.h>
#include <unistd.h>

int sum(int begin,int end)
{
  int sum = 0;
  for(int i = begin; i <= end; i++)
  {
    sum += i;
  }
  sum += 100;
  return sum;
}

int main()
{
  int ans = sum(1,10);
  if(ans == 55)
    return 0;
  else
    return 1;
}

 

进程退出的时候,会给出进程退出码,用于标定进程是否正确

那么我们如何设定退出码呢?

如果我们不关心进程退出码的话,直接返回0即可!关心进程退出码,我们返回特定的进程退出码即可

一般用0标定正确返回,非0标定错误。我们使用不同的数字标定不同的退出信息!

对于退出信息,系统的一个进程退出码有一个退出信息。

我们可以自定义退出信息,也可以使用系统设置的退出信息

2.2 进程退出码所对应的退出信息 

我们使用 strerror(进程退出码) 即可获取系统标定的信息!(系统共有134个退出码)

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
  //显示进程退出码信息
  for(int i = 0; i <= 134; i++)
  {
    printf("%d -> %s\n", i, strerror(i));
  }
  return 0;
}

运行结果如下:

 

三. 进程退出

让进程正常退出的方法!

1 main函数返回

2 exit()    函数(C语言库函数)

3 _exit()  系统调用

//exit 所需头文件
#include <stdlib.h>

void exit(int status);
//status就是我们想要退出的退出码

//_exit 所需头文件
#include <unistd.h>

//用法和eixt一样
void _exit(int status);

直接 exit(退出码),即可将该进程退出,并且返回对应的退出码

exit 和 _exit 的区别

exit 终止进程会主动刷新C语言的用户级缓冲区

_exit 由于是系统调用,不会刷新该缓冲区

如:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void f()
{
  exit(0);
}

int main()
{
  printf("hello yzc!\n");
  f();
  while(1) sleep(1); //休眠
  return -1;
}

四. 下篇重点:进程退出和阻塞,非阻塞等待


http://www.kler.cn/a/397768.html

相关文章:

  • FFmpeg源码:avio_read_partial函数分析
  • 微服务链路追踪skywalking安装
  • 无效的目标发行版17和无法连接Maven进程问题
  • pytest在conftest.py中实现用例执行失败进行截图并附到allure测试报告
  • C++:基于红黑树封装map和set
  • Docker占用空间太大磁盘空间不足清理妙招
  • nuget 管理全局包、缓存和临时文件夹
  • Zotero 7本地pdf文件名自适应中英文格式
  • stm32使用cJSON_Print返回空
  • Gin 框架入门(GO)-1
  • 正态分布密度函数的基本概念
  • Pandas进行时间选择与过滤
  • vue3设置第三方组件 样式::v-deep
  • 智能化运维与AI/ML辅助决策:实现自动化与预测优化
  • 游戏引擎学习第八天
  • 【Java】异常处理实例解析
  • c# 调用c++ 的dll 出现找不到函数入口点
  • Java 核心技术卷 I 学习记录六
  • Scala中的Array
  • 基于树莓派的边缘端 AI 目标检测、目标跟踪、姿态估计 视频分析推理 加速方案:Hailo with ultralytics YOLOv8 YOLOv11
  • 鸿蒙生态的未来:共融与创新
  • HbuilderX 插件开发-模板创建
  • 将自定义函数添加到MATLAB搜索路径的方法
  • 【视觉SLAM】1-概述
  • java笔试练习题笔记(9)
  • GRE做题笔记(零散的个人经验)