【项目 进程3】2.6 exce函数族 2.7 进程退出、孤儿进程、僵尸进程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

    • 2.6 exec函数族介绍(execute 执行)
      • exec函数族
    • 2.7 进程退出、孤儿进程、僵尸进程
      • 进程退出
      • 孤儿进程
      • 僵尸进程


2.6 exec函数族介绍(execute 执行)

有点像C++的函数重载,是一系列功能相似的函数

  • exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,在调用进程内部执行一个可执行文件。

  • exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段、数据段和堆栈都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,“三十六计”中的“金蝉脱壳”。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回-1,从原程序的调用点接着往下执行。

exec函数族

前6个为标准C库函数,最后一个为Linux系统函数
在这里插入图片描述
注:第二章是linux系统函数,第三章才是标准c库函数,所以使用 man 3 execl 来查看该函数说明。

  • l(list) 参数地址列表,以空指针结尾

  • v(vector) 存有各参数地址的指针数组的地址

  • p(path) 按PATH环境变量指定的目录搜索可执行的文件

  • e(environment) 存有环境变量字符串地址的指针数组的地址

hello.c

#include <stdio.h>

int main() {    

    printf("hello, world\n");

    return 0;
}

execl.c

/*  
    #include <unistd.h>
    int execl(const char *path, const char *arg, ...);
        - 参数:
            - path:需要指定的执行的文件的路径或者名称
                a. out /home/nowcoder/a.out 推荐使用绝对路径
                ./a.out hello world

            - arg:是执行可执行文件所需要的参数列表
                第一个参数一般没有什么作用,为了方便,一般写的是执行的程序的名称
                从第二个参数开始往后,就是程序执行所需要的的参数列表。
                参数最后需要以NULL结束(哨兵)

        - 返回值:
            只有当调用失败,才会有返回值,返回-1,并且设置errno
            如果调用成功,没有返回值。

*/
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main() {


    // 创建一个子进程,在子进程中执行exec函数族中的函数
    pid_t pid = fork();

    if(pid > 0) {
        // 父进程
        printf("i am parent process, pid : %d\n",getpid());
        sleep(1);
    }else if(pid == 0) {
        // 子进程
        // execl("hello","hello",NULL);

        //执行操作系统的shell命令
        execl("/bin/ps", "ps", "aux", NULL);
        perror("execl");
        printf("i am child process, pid : %d\n", getpid());//若execl执行成功,该语句不会被执行

    }

    //若execl执行成功,下面循环只执行父进程的部分,不会执行子进程的部分
    for(int i = 0; i < 3; i++) {
        printf("i = %d, pid = %d\n", i, getpid());
    }


    return 0;
}

execlp.c
输入env,找path,后面跟的就是存 在环境变量下的路径们。execlp只需要可执行程序的名字,然后会自动去环境变量有的目录下找对应文件
在这里插入图片描述

/*  
    #include <unistd.h>
    int execlp(const char *file, const char *arg, ... );
        - 与execl的不同之处:会到环境变量中查找指定的可执行文件,如果找到了就执行,找不到就执行不成功。
        - 参数:
            - file:需要执行的可执行文件的文件名
                a.out
                ps

            - arg:是执行可执行文件所需要的参数列表
                第一个参数一般没有什么作用,为了方便,一般写的是执行的程序的名称
                从第二个参数开始往后,就是程序执行所需要的的参数列表。
                参数最后需要以NULL结束(哨兵)

        - 返回值:
            只有当调用失败,才会有返回值,返回-1,并且设置errno
            如果调用成功,没有返回值。


        int execv(const char *path, char *const argv[]);
        argv是需要的参数的一个字符串数组
        char * argv[] = {"ps", "aux", NULL};
        execv("/bin/ps", argv);

        int execve(const char *filename, char *const argv[], char *const envp[]);
        char * envp[] = {"/home/nowcoder", "/home/bbb", "/home/aaa"};


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

int main() {


    // 创建一个子进程,在子进程中执行exec函数族中的函数
    pid_t pid = fork();

    if(pid > 0) {
        // 父进程
        printf("i am parent process, pid : %d\n",getpid());
        sleep(1);
    }else if(pid == 0) {
        // 子进程
        //execl若没有写具体的路径,则找不到,但execlp可以不写具体路径,可从环境变量中查找指定的可执行文件
        //若执行hello.c,没有配置环境变量路径则会报错
        execlp("ps", "ps", "aux", NULL);

        printf("i am child process, pid : %d\n", getpid());

    }

    for(int i = 0; i < 3; i++) {
        printf("i = %d, pid = %d\n", i, getpid());
    }


    return 0;
}

2.7 进程退出、孤儿进程、僵尸进程

关于进程:创建子进程的时候,子进程会拥有一份虚拟地址空间,但是除了内核区,在读数据的时候和父进程共用一份物理空间。只有写的时候,或者调用exec的时候,物理空间才会被复制一份出来给新的程序使用

进程退出

在这里插入图片描述
status参数为退出的状态,记录进程是什么原因退出的。这个值会被父进程接收,父进程通过这个状态判断是不是要内存回收或者做其他操作

exit()比_exit()多做了几件事情,调用退出处理函数、刷新I/O缓冲、关闭文件描述符等等,exit()底层也是调用_exit()函数。

/*
    #include <stdlib.h>
    void exit(int status);

    #include <unistd.h>
    void _exit(int status);

    status参数:是进程退出时的一个状态信息。父进程回收子进程资源的时候可以获取到。
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {

    printf("hello\n");//\n自动刷新IO缓冲区
    printf("world");//写入缓冲区里

    // exit(0);//一般使用标准C库的函数,它做的事情更多一些,打印hello world(刷新IO缓冲,将缓冲区数据输出到终端)
    _exit(0);//若执行成功,return 0将不会被执行,只打印hello
    
    return 0;
}

孤儿进程

在这里插入图片描述
init进程pid为1
但是子进程不一定就是init接管。像目前使用的版本就是1765,upstart接管了init的部分工作,领养子进程

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main() {

    // 创建子进程
    pid_t pid = fork();

    // 判断是父进程还是子进程
    if(pid > 0) {

        printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());
        //程序运行时在后台
        //父进程退出后,切换到前台
    } else if(pid == 0) {
        sleep(1);
        // 当前是子进程
        printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());
       
    }

    // for循环
    for(int i = 0; i < 3; i++) {
        printf("i : %d , pid : %d\n", i , getpid());
    }

    return 0;
}

在一开始,是前台,执行orphan的时候切换到后台。有内容输出的时候,输出到前台让用户看到。当ppid(终端)检测到pid(父进程)死亡,就会认为这个程序执行完毕。就会回到前台。但是此时子进程还有内容输出。于是就会显示出子进程紧跟前台输出
在这里插入图片描述子进程继承了父进程的所有打开的文件描述符,包括标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)。这就意味着,如果父进程的标准输出连接到了当前终端,那么子进程的标准输出也会连接到同一个终端。

僵尸进程

在这里插入图片描述
释放僵尸进程的另一种方法:杀死父进程,子进程由init进程收养并回收。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main() {

    // 创建子进程
    pid_t pid = fork();

    // 判断是父进程还是子进程
    if(pid > 0) {
        while(1) {
            printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());
            sleep(1);
        }

    } else if(pid == 0) {
        // 当前是子进程
        printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());
       
    }

    // for循环
    for(int i = 0; i < 3; i++) {
        printf("i : %d , pid : %d\n", i , getpid());
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/38553.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端做excel的录入解析,将excel的数据传给后端,显示在页面上。

具体的流程如图所示&#xff1a; 1.点击excel录入按钮 2.打开弹框 3.点击上传按钮&#xff0c;会自动打开计算机本地文件&#xff0c;选择想上传的文件&#xff0c;点击打开 4.会将excel的数据解析成一个表格&#xff0c;可以在表格中做删除操作&#xff0c;点击确定 5.将exc…

Web3的2048,Sui 8192能否打开全链游戏的大门?

作者&#xff1a;Peng SUN&#xff0c;Foresight News Sui 8192&#xff1a;一局游戏就是一个NFT Sui 8192智能合约基于Move语言编写&#xff0c;构成非常简单&#xff0c;包括游戏、Game Board与排行榜&#xff08;Leaderboard&#xff09;三部分&#xff0c;覆盖方块移动、…

IOS与Android APP开发的差异性

iPhone和 Android是全球最流行的两种移动平台&#xff0c;有许多不同的开发者开发了应用程序&#xff0c;并将它们发布到市场上。虽然大多数开发者都使用了这两个平台&#xff0c;但您仍然需要了解它们的差异。 虽然 iOS和 Android两个平台都是基于 Linux&#xff0c;但它们却…

SOPC之NiosⅡ系统(五)

NIOS Ⅱ系统实例 目录 2.创建BSP工程 2.1 创建BSP工程 2.2 BSP Editor 2.3 创建C代码文件 3.Nios Ⅱ实例 3.1 Hello NIOS Ⅱ 3.2 System ID与Timestamp 3.3 蜂鸣器定时鸣叫 3.4 拨码开关输入GIO控制 4.FPGA器件的代码固化 4.1 嵌入式软件HEX文件生成 4.2 程序存储…

Linux进程控制(一)---进程创建和终止(写时拷贝,exit与_exit等)

目录 进程创建 fork()函数 子进程如何继承父进程的数据 1.创建时拷贝分离 2.写时拷贝★ 进程终止 进程终止时&#xff0c;操作系统做了什么&#xff1f; 进程终止的常见方式 代码运行完毕&#xff0c;结果正确 退出码★ 代码运行完毕&#xff0c;结果不正确 代码异…

自学网络安全(黑客)

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 行为&#xff1a;从编程开始掌握&#xff0c;前端后端、通信协议、什么都学。 缺点&#xff1a;花费时间太长、实际向安全过渡后可用到的关键知识并不多。…

字体反爬破解

1、通过 f12 查看网页相关信息① 搜索“python”相关岗位&#xff0c;想爬取下来作为分析&#xff0c;但是看到html源码为特殊字符&#xff0c;而不是页面上直观能看到的文字信息②点击对应的css样式查看css源码&#xff0c;通过源码解析字体加密过程 2、通过 DomainURI 获取到…

北邮国院物联网 Microprocessor 微处理器笔记

Introduction-随便聊 嵌入式系统是什么&#xff1f;专用的计算机系统。为专门功能可能对计算机架构&#xff0c;外设等做出一些取舍。 通常的限制&#xff1a;Cost&#xff08;比如大量部署传感器节点&#xff09;&#xff0c;Size and weight limits&#xff08;特定应用场景…

【网关】ShenYu Gateway入门Demo体验,ShenYu网关2.6.0直接调用Dubbo服务

本次为新开源框架接入ShenYu网关做基础学习指导&#xff0c;特地来下载官网的demo体验一把&#xff0c;具体是想通过网关泛化调用dubbo服务。本次使用的是最新版本2.6.0。 官网文档&#xff1a; 如何通过 Apache ShenYu 网关代理 Dubbo 服务 | Apache Dubbo 环境准备 第一步&a…

git下载源码及环境搭建下载源码之后端(一)

学习目标&#xff1a; git下载源码 步骤&#xff1a; 下载源码 使用 windows R 使用cmd调用命令框下载gitee云上面的 源码文件 输入命令&#xff1a; Git clone &#xff08;此处拼接gitee源代码 地址&#xff09; 若使用 git 命令 clone 项目时 我们需要在系统变量中进行…

vue生命周期四个阶段(created和mount)

1.四个阶段 1&#xff09;必经阶段 2&#xff09;非必经阶段 提示&#xff1a;主动调用 vm.$destroy() 函数销毁后&#xff0c;可用 vm.$mount("#app") 将断开的 new Vue() 和页面重新建立虚拟 DOM 树&#xff0c;重新绑定起来挂载界面。 2. 生命周期钩子函数&…

【Unity 实用插件篇】| ReferenceFinder 引用查找插件,提高引擎查找使用效率

前言 【Unity 实用插件篇】| ReferenceFinder 引用查找插件&#xff0c;提高引擎查找使用效率一、ReferenceFinder 介绍二、使用示例三、实现方案3.1 方案选择3.2 查找及缓存3.3 界面实现 总结 前言 ReferenceFinder 是一个比较小众的插件&#xff0c;主要用来查找资源引用和…

【Java】Java实现微信小程序发送服务通知

文章目录 前言一、文档来源二、JAR包引入三、后端工作四、编写配置文件配置一&#xff1a;WxConfig配置二&#xff1a;WxProperties 五、代码编写 前言 在上个月接到一个需求&#xff0c;大概是需要计算一条数据的最大办理时间从而发送任务超期的微信小程序服务通知&#xff0…

IDDR和ODDR

IDDR D&#xff1a;输入双倍速率数据&#xff08;IOB输入&#xff0c;且数据在时钟的上升沿和下降沿都会发生切换&#xff0c;即一个时钟周期发送2bit数据&#xff09; CE&#xff1a;时钟使能信号&#xff08;高有效&#xff09; C&#xff1a;时钟信号 S&#xff0c;R&#x…

黑马大数据学习笔记2-HDFS基本操作

目录 进程启停管理一键启停脚本单进程启停 文件系统操作命令HDFS文件系统基本信息介绍创建文件夹查看指定目录下内容上传文件到HDFS指定目录查看HDFS文件内容下载HDFS文件拷贝HDFS文件追加数据到HDFS文件HDFS数据移动HDFS数据删除其他命令HDFS WEB浏览 HDFS权限修改权限 https:…

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树、Pipeline、交叉验证

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树案例 除了scikit-learn外&#xff0c;在spark中也提供了机器学习库&#xff0c;即Spark MLlib。 在Spark MLlib机器学习库提供两套算法实现的API&#xff1a;基于RDD API和基于DataFrame API。今天&#xff0c;主要介绍下Data…

FPGA实验四:交通灯控制器设计

目录 一、实验目的 二、设计要求 三、实验代码 1.design source文件代码 2.仿真文件代码 3.代码原理分析 四、实验结果及分析 1、引脚锁定 2、仿真波形及分析 3、下载测试结果及分析 五、实验心得 1.解决实验中遇见的问题及解决 2.实验完成的心得 一、实验目的 &a…

Linux使用HTTP隧道代理代码示例模版

下面是一个在Linux上使用HTTP隧道代理的代码示例模板&#xff0c;可以根据自己的实际情况进行修改和配置&#xff1a; #!/bin/bash# 配置代理服务器信息 proxy_server"代理服务器IP或域名" proxy_port"代理服务器端口号" proxy_username"代理服务器用…

《动手学深度学习》——线性神经网络

参考资料&#xff1a; 《动手学深度学习》 3.1 线性回归 3.1.1 线性回归的基本元素 样本&#xff1a; n n n 表示样本数&#xff0c; x ( i ) [ x 1 ( i ) , x 2 ( i ) , ⋯ , x d ( i ) ] x^{(i)}[x^{(i)}_1,x^{(i)}_2,\cdots,x^{(i)}_d] x(i)[x1(i)​,x2(i)​,⋯,xd(i)​…

《实战AI低代码》:普元智能化低代码开发平台发布,结合专有模型大幅提升软件生产力

在7月6日举办的“低代码+AI”产品战略发布会上,普元智能化低代码开发平台正式发布。该平台融合了普元自主研发的专有模型,同时也接入了多款AI大模型的功能。它提供了一系列低代码产品,包括中间件、业务分析、应用开发、数据中台和业务流程自动化等,旨在简化企业的复杂软件生…