Linux——进程(2)

ops/2024/9/20 4:00:48/ 标签: linux, 服务器, 运维

一、父子进程的关系

  •     子进程是父进程的副本。
  •     子进程获得父进程数据段,堆,栈,正文段共享。
  •     在fork之后,一般情况哪个会先运行,是不确定的。
  •     如果非要确定那个要先运行,需要IPC机制。

    1、区别


    1)fork的返回值
    2)pid不同


二、创建进程(fork())


  注意:
           1.创建之后,父子进程各自拥有4g独立的内存空间 
           2.各自拥有自己的相关的程序的各个段 数据段,所以,各自之间对数据的改变,不会相互                  影响 
           3.子进程会继承父进程已打开的文件描述符 
             若,fork之前打开文件,父子进程操作同一个文件,相互间有影响
             若,fork之后打开文件,父子进程操作同一个文件,但是,因为各自拥有自己的 "文件表                 项",所以,各自按照自己的逻辑改变文件。


三、进程的终止(8种情况)


    1)main 中 return
    2)exit() //库函数 
       c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。注册清理函数               (atexit)。
    3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。 //系统调用 
    4) 主线程退出  
    5)主线程调用pthread_exit 
    
    异常终止:
    6)abort()
    7)signal   kill pid
    8) 最后一个线程被pthread_cancle

     
四、进程的退出

1、僵尸进程和孤儿进程    


    孤儿进程:
      特点:
           子进程还在,但父进程已经结束了。此时,避免子进程将来没有人收尸,
           由init进程来收养子进程。
    
    僵尸进程:
      特点:
          父进程还在,子进程先结束了。父进程没有做收尸操作。
          此时,子进程进入僵尸态。(wait/waitpid --- 查看子进程的退出状态)

五、僵尸进程


            进程执行结束但空间未被回收变成僵尸进程

    1.exit(库函数)


            退出状态,终止的进程会通知父进程,自己使如何终止的。    
            如果是正常结束(终止),则由exit传入的参数。
            如果是异常终止,则有内核通知异常终止原因的状态。
            任何情况下,父进程都能使用wait,waitpid获得这个状态,以及资源的回收。
    void exit(int status) 
    exit(1);
    功能:
        让进程退出,并刷新缓存区
    参数:
        status:进程退出的状态
    返回值:
        缺省

    return  当该关键字出现在main函数中时候可以结束进程
            如果在其他函数中则表示结束该函数。


2._exit(系统调用)


    void _exit(int status);
    功能:
        让进程退出,不刷新缓存区
    参数:
        status:进程退出状态
    返回值:
        缺省


3.atexit


    int atexit(void (*function)(void));
    功能:
        注册进程退出前执行的函数
    参数:
        function:函数指针
            指向void返回值void参数的函数指针
    返回值:
        成功返回0
        失败返回非0

    当程序调用exit或者由main函数执行return时,所有用atexit
    注册的退出函数,将会由注册时顺序倒序被调用

注意:
   a. 是exit函数调用时,会调atexit函数 
      _exit函数调用时,不会调到atexit
   b. atexit 程序正常结束
      (1).main 返回 //exit 
      (2).exit()        
   c.atexit函数 可以多次注册 
   d.最后"退出清理函数"的调用顺序,与注册顺序相反。

六.进程空间的回收


1、void exit(int status);


    wait/waitpid
    exit(EXIT_SUCCESS);// EXIT_SUCCESS ---退出状态值 
    pid_t wait(int *status);//wait 来获取到 
功能:该函数可以阻塞等待任意子进程退出
           并回收该进程的状态。
           一般用于父进程回收子进程状态。

参数:status 进程退出时候的状态
           如果不关心其退出状态一般用NULL表示
          如果要回收进程退出状态,则用WEXITSTATUS回收。

返回值:成功 回收的子进程pid
              失败 -1;
WIFEXITED(status)   是不是正常结束
WEXITSTATUS(status) 使用这个宏去那返回值
WIFSIGNALED(status) 是不是收到了信号而终止的
WTERMSIG(status)    如果是信号终止的,那么是几号信号。

2、pid_t wait(int *status);

    1)如果所有的子进程都在运行,在阻塞
    2)如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返                回。
    3)如果没有子进程,则立即出错退出。

    waitpid(-1,status,0)=wait(status);
    pid_t waitpid(pid_t pid, int *status, int options);
    
    <-1 回收指定进程组内的任意子进程
     -1 回收任意子进程,组内外
      0 回收和当前调用waitpid一个组的所有子进程,组内
     >0 回收指定ID的子进程
     
     @pid 的值 
       
       < -1   meaning wait for any child process whose  process  group  ID  is
              equal to the absolute value of pid.

       -1     meaning wait for any child process.

       0      meaning  wait  for  any  child process whose process group ID is
              equal to that of the calling process.

       > 0    meaning wait for the child whose process  ID  is  equal  to  the
              value of pid.


3、waitpid (-1,a,0)  == wait(a);


     参数:
     status 子进程退出时候的状态,
              如果不关注退出状态用NULL;
     options 选项:
                  0       表示回收过程会阻塞等待
                WNOHANG 表示非阻塞模式回收资源。
                
    返回值:成功 返回接收资源的子进程pid
                   失败  -1
        wait(); 
        waitpid(-1,&status,0); <=> wait
        waitpid(pid,&status,0); //默认的当时,默认就是阻塞方式 
        waitpid(pid,&status,WNOHANG);// 非阻塞的方式 
        wait(&status) <=> waitpid(-1,&status,0); //阻塞 形式
        waitpid(-1,&status,WNOHANG);//非阻塞形式     


4、wait 和waitpid的比较


功能:
    都是来等待子进程状态改变的 
wait    ---阻塞的版本,子进程的结束状态 
waitpid --- 可以实现一个非阻塞版本的等待,其实还可以检测子进程的其他的状态改变。
注意: 
   waitpid 实现一个非阻塞版本的 回收操作,但是,要想能够实现收尸操作,必须,要使用轮询(while)
收尸操作:
   1.wait 
   2.waitpid 
   3.孤儿进程 
     fork 
       |
     父进程 exit()


七、exec族


        用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建
新进程,所以调用exec前后该进程的id并未改变。

1、exec函数


        其实有六种以exec开头的函数,统称exec函数:
vector
ls -l -i list 
execl("/bin/ls","-l","-i",NULL);
execlp("ls","-l","-i",NULL);

#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);

key=value
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execle(const char *path, const char *arg, ..., char *const envp[]);

int execve(const char*path,char*const argv[],char*const evnp[]);
int execlp(const char *file, const char *arg, ...);

2、这些函数的区别


    1),前4个使用路径名作为参数,后面两个使用文件名做参数
    当filename中,含有/时视为路径名,否则就按PATH变量,在指定目录下查找可执行文件。
    2)相关的参数表传递
    l表示list,v表示vector
    execl,execlp,execle,需要将参数一个一个列出,并以NULL结尾。
    execv,execvp,execve,需要构造一个参数指针数组,然后将数组的地址传入。

    3)以e结尾的函数,可以传入一个指向环境字符串的指针数组的指针。其他未指定环境变量,使用父进程继承过来的。
        execve 是真正的系统调用
        这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。


注意:
路径加文件名
1.excle 
  带l的默认会搜索,当前路径下。
2.带p的只搜索 PATH系统环境变量


(1).带l  vs 带 v 


    int execl  (const char *path, const char *arg, ...); //list 
    int execv  (const char *path, char *const argv[]);//vector 
功能:
    执行一个文件 (可执行文件 a.out / 1.sh )
参数:
  @path   要执行的文件的路径(包含可执行文件的名字)
  @arg   表示 可执行文件的文件名 
 execl("/bin/ls","ls","-l","/",NULL);

区别:
    在于,参数传递的方式不同,
    l --- list ---参数逐个列举 
    v ---vector --- 参数组织成 指针数组的形式 


(2). p和e的区别

        带p 表示可执行文件的寻找方式,是从系统的环境变量PATH中的路径下面去找
        带e 表示的是可以给要执行的 新程序 传递需要的 环境变量 

        extern char **environ; //系统的环境变量信息 的指针数组的首地址 

真正的系统调用:
execve  


http://www.ppmy.cn/ops/93852.html

相关文章

ZAN与Mysten Labs合作推进Web3基础设施开发

Mysten Labs是一家Web3基础设施公司&#xff0c;也是Sui区块链的开发公司&#xff0c;今天宣布与蚂蚁数字科技的技术品牌ZAN建立合作伙伴关系。 通过整合Sui&#xff0c;ZAN旨在加速其Web3应用程序的开发和采用。该合作将专注于为Mysten Labs在两个关键领域提供技术支持&#…

oracle 数据中lsnrctl 是干啥的

突然发现lsnrctl stop 之后&#xff0c;依然可以启动数据库 就感觉怪怪的&#xff0c;一直以为这个是数据库的守护进程&#xff0c;原来不是。。。。 lsnrctl 是 Oracle 监听器控制实用程序的命令行界面工具&#xff0c;用于管理 Oracle Net 服务监听器。监听器是 Oracle 网络…

Python爬虫——爬取bilibili中的视频

爬取bilibili中的视频 本次爬取&#xff0c;还是运用的是requests方法 首先进入bilibili官网中&#xff0c;选取你想要爬取的视频&#xff0c;进入视频播放页面&#xff0c;按F12&#xff0c;将网络中的名称栏向上拉找到第一个并点击&#xff0c;可以在标头中&#xff0c;找到…

汽车精密设计、无人机外形优化总是遇难题?CFD参数优化详解2来袭

数值仿真的参数优化 在上期文章中&#xff0c;我们给大家带来了机翼多学科优化、拟合试验曲线、一维CFD模型参数的DOE和回归分析三个参数优化案例&#xff0c;本期文章将继续为各位讲解多个 Altair CFD 参数优化案例&#xff0c;一起来看看吧。 案例&#xff1a;汽车排气管形状…

7.2 我们机房断网了!--图文解析

7.2 我们机房断网了&#xff01;–图文解析 原文链接&#xff1a;https://juejin.cn/post/7399569706183049250 原文作者&#xff1a;哔哩哔哩技术团队 1、背景 原文&#xff1a; 2024 年 7 月 2 日 10:04&#xff0c;我站机房 A 公网物理光缆中断&#xff0c;导致机房 A …

Electron 开发桌面应用程序用于对接USB Audio Class协议

开发用于对接USB Audio Class协议的Electron桌面应用程序是一个复杂的任务&#xff0c;可能涉及多个开源库和项目的组合。以下是一些开源项目和库&#xff0c;它们可以帮助你实现这个目标&#xff1a; 1. Electron Electron 是一个用于构建跨平台桌面应用程序的框架。你可以使…

go语言后端开发学习(五)——如何在项目中使用Viper来配置环境

前言 在之前的文章中我们就介绍过用go-ini来读取配置文件,但是当时我们在介绍时说了他只能读取.ini格式的配置文件所以局限性较大,这里我们介绍一个适用范围更大的配置管理第三方库——Viper。 什么是Viper Viper是适用于Go应用程序&#xff08;包括Twelve-Factor App&#…

Ubuntu系统的基础操作和使用|Linux|安装|网络连接|更新与升级系统|系统维护|故障排除|监控|桌面环境|虚拟机|快捷键

目录 1. Ubuntu系统的安装与初步设置 1.1 下载与安装Ubuntu 1.2 创建用户和设置密码 1.3 配置网络连接 1.4 更新与升级系统 2. Ubuntu的基本操作 2.1 文件与目录管理 2.2 系统进程管理 2.3 软件安装与管理 2.4 权限与用户管理 3. 系统维护与故障排除 3.1 系统日志查…

HarmonyOS鸿蒙开发岗位面试中关于组件的问题总结

文章目录 1. 鸿蒙组件的基本概念2. 组件的使用3. 布局管理4. 组件间通信5. 组件化开发6. 性能优化7. 实战应用 鸿蒙应用开发岗位面试中关于鸿蒙组件的问题&#xff0c;通常会涉及多个关键知识点&#xff0c;这些知识点涵盖了鸿蒙组件的基本概念、使用、布局管理、性能优化、组件…

Go语言并发编程实战:掌握并发模型,提升应用性能

1. 引言 1.1 并发编程的重要性 在现代软件开发中&#xff0c;并发编程已经成为了一种不可或缺的技术。随着多核处理器的普及和云计算的兴起&#xff0c;应用程序需要能够有效地利用并发处理能力&#xff0c;以提高性能和用户体验。并发编程使得程序能够在同一时间内处理多个任…

Qt Xlsx使用教程、Qt操作Excel、Qt生成Excel图表、跨平台不依赖Office 直接使用源码

1.Qt Xlsx库简介 官方文档&#xff1a;Qt Xlsx | QtXlsx 0.3 (debao.me) 下载地址&#xff1a;dbzhang800/QtXlsxWriter: .xlsx file reader and writer for Qt5 (github.com) CSDN下载地址&#xff1a;QtXlsxWriter-master源码资源-CSDN文库 2.源码取出 3.目录结构 再根目…

股指期货套期保值中的展期管理有哪些?

在复杂的金融市场环境中&#xff0c;展期作为一种重要的风险管理工具&#xff0c;被广泛应用于期货交易中&#xff0c;特别是当投资者需要对长期资产进行套期保值时。展期的核心思想在于&#xff0c;通过连续替换高流动性的近月期货合约来替代流动性较差的远月合约&#xff0c;…

JS【详解】对象的内部属性 vs 内部方法

每个JS 对象都有很多内部属性和方法&#xff0c;仅供 JS 引擎管理和操作对象使用&#xff0c;对开发者不可见&#xff0c;只能用特殊的方法访问和修改&#xff08;不建议修改&#xff09; 了解它们可以帮助我们更好的理解对象的行为&#xff0c;无需深究其具体实现 下文中&am…

力扣:496. 下一个更大元素 I、503. 下一个更大元素 II

496. 下一个更大元素 I 这里我们采用单调栈来写这道题。 首先遍历nums2,并新开一个数组ant&#xff0c;存储对应nums2的下一个更大元素&#xff0c;这里采用单调栈&#xff0c;从栈顶到栈底是递增序列。 然后我们遍历a,再遍历b找到对应nums1nums2&#xff0c;然后nums1存储a…

*算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿

刷题记录 101. 孤岛的总面积DFSBFS 102. 沉没孤岛DFSBFS *103. 水流问题*104. 建造最大岛屿 101. 孤岛的总面积 题目地址 本题要求不与矩阵边缘相连的孤岛的总面积。先将与四个边缘相连的岛屿变为海洋&#xff0c;再统计剩余的孤岛的总面积。无需再标识访问过的结点&#xff…

利用Python轻松从视频中抽取帧

利用Python轻松从视频中抽取帧 安装依赖示例代码参数说明使用示例 在做CV项目的时候&#xff0c;有时候可能需要从视频中抽取一些有价值的图片&#xff0c;可以使用 Python 的 opencv 库来从视频中抽取帧。以下是一个示例程序&#xff0c;展示了如何从视频中抽取帧&#xff0c;…

单调栈(算法篇)

算法之单调栈 注意&#xff1a;单调栈是一种数据结构&#xff0c;并非是一种算法&#xff0c;但是我们做一些算法题的时候&#xff0c;这种单调性结构有妙用&#xff0c;所以我姑且放在算法篇进行讲解 单调栈 概念&#xff1a; 单调栈是一种数据结构&#xff0c;但是因为经…

面试实战题-数据结构与算法

数据结构与算法 求TopK 大根堆 解题思路&#xff1a;保持堆的大小为K&#xff0c;然后遍历数组中的数字&#xff0c;遍历的时候做如下判断&#xff1a; * 1. 若目前堆的大小小于K&#xff0c;将当前数字放入堆中。 * 2. 否则判断当前数字与大根堆堆顶元素的大小关系&#xf…

Unity动画模块 之 2D IK(反向动力学)

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正​ 1.什么是IK 反向动力学 IK&#xff08;Inverse Kinematics&#xff09;是一种方法&#xff0c;可以根据某些子关节的最…

[upload]-[GXYCTF2019]BabyUpload1-笔记

尝试上传.htaccess和图片和一句话木马提示 php文件提示 响应头可以看到 构造一句话图片木马如下&#xff1a; <script languagephp>eval($_POST[cmd]);</script> 上传成功 必须增加文件夹下jpg后缀解析php .htaccess如下 <FilesMatch "jpg">Set…