【Linux操作系统】深入探索Linux进程:创建、共享与管理

news2024/11/23 12:31:07

进程的创建是Linux系统编程中的重要概念之一。在本节中,我们将介绍进程的创建、获取进程ID和父进程ID、进程共享、exec函数族、wait和waitpid等相关内容。
在这里插入图片描述

文章目录

    • 1. 进程的创建
      • 1.1 函数原型和返回值
      • 1.2 函数示例
    • 2. 获取进程ID和父进程ID
      • 2.1 函数原型和返回值
      • 2.2 函数示例
    • 3. exec函数族
      • 3.1 `exec()`函数族的常见成员:
      • 3.2 函数示例
    • 4. wait和waitpid
      • 4.1 函数解释
      • 4.2 函数示例
  • 总结


1. 进程的创建

在Linux系统中,进程的创建使用fork()系统调用。fork()系统调用会创建一个与当前进程相同的子进程,子进程会复制父进程的所有资源,包括代码、数据和文件描述符等。


1.1 函数原型和返回值

fork()函数的原型如下:

#include <unistd.h>

pid_t fork(void);

fork()函数 没有任何参数 ,它的返回值是一个pid_t类型的整数。具体解释如下:

  • 如果调用成功,fork()函数会在父进程中返回子进程的PID(子进程ID),在子进程中返回0。
  • 如果调用失败,fork()函数会返回-1,并设置errno来指示错误类型。

1.2 函数示例

代码示例如下:

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

int main() {
    pid_t pid = fork();
    if (pid == -1) {
        printf("Failed to fork a new process.\n");
        return 1;
    } else if (pid == 0) {
        printf("This is the child process.\n");
    } else {
        printf("This is the parent process.\n");
    }
    return 0;
}

上述代码中,fork()系统调用会返回两次,分别在父进程和子进程中返回。通过判断返回值,我们可以区分父进程和子进程,并执行不同的代码逻辑。



2. 获取进程ID和父进程ID

在Linux系统中,可以使用getpid()getppid()系统调用来获取当前进程的ID和父进程的ID。


2.1 函数原型和返回值

getpid()getppid()函数的原型如下:

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

pid_t getpid(void);
pid_t getppid(void);

这两个函数都 没有任何参数 ,它们的返回值都是一个pid_t类型的整数。具体解释如下:

  • getpid()函数返回调用进程的进程ID(PID)。
  • getppid()函数返回调用进程的父进程的进程ID(PPID)。

2.2 函数示例

代码示例如下:

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

int main() {
    pid_t pid = getpid();
    pid_t ppid = getppid();
    printf("Process ID: %d\n", pid);
    printf("Parent Process ID: %d\n", ppid);
    return 0;
}


3. exec函数族

在Linux系统中,exec()函数族可以用于将当前进程替换为新的程序。exec()函数族包括execl()execv()execle()execve()等函数。这些函数可以根据不同的参数形式来执行不同的替换方式。


3.1 exec()函数族的常见成员:

  1. int execl(const char *path, const char *arg, ...);

    • 参数 path 是要执行的新程序的路径。
    • 参数 arg 是一个字符串,表示新程序的第一个参数。
    • 可变参数列表是新程序的其他参数,必须以 NULL 结束。
    • 函数执行成功时不会返回,如果返回则表示执行失败。

  2. int execv(const char *path, char *const argv[]);

    • 参数 path 是要执行的新程序的路径。
    • 参数 argv 是一个字符串数组,表示新程序的参数列表,最后一个元素必须是 NULL
    • 函数执行成功时不会返回,如果返回则表示执行失败。

  3. int execle(const char *path, const char *arg, ..., char *const envp[]);

    • 参数 path 是要执行的新程序的路径。
    • 参数 arg 是一个字符串,表示新程序的第一个参数。
    • 可变参数列表是新程序的其他参数,必须以 NULL 结束。
    • 参数 envp 是一个字符串数组,表示新程序的环境变量列表,最后一个元素必须是 NULL
    • 函数执行成功时不会返回,如果返回则表示执行失败。

  4. int execvp(const char *file, char *const argv[]);

    • 参数 file 是要执行的新程序的文件名。
    • 参数 argv 是一个字符串数组,表示新程序的参数列表,最后一个元素必须是 NULL
    • 函数执行成功时不会返回,如果返回则表示执行失败。

这些函数在执行成功时不会返回,而是直接将当前进程替换为新程序。如果返回,则表示执行失败,可以根据返回值来判断错误类型。

exec()函数族可以用于在当前进程中加载和执行新程序,可以实现程序的动态切换和功能扩展。一般情况下,exec()函数族会在调用fork()函数创建子进程后使用,以替换子进程的代码和数据。


3.2 函数示例

代码示例如下:

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

int main() {
    printf("Before exec()\n");
    execl("/bin/ls", "ls", "-l", NULL);
    printf("After exec()\n");
    return 0;
}

上述代码中,execl()函数会将当前进程替换为ls -l命令。execl()函数的第一个参数是要执行的程序路径,后续参数是传递给新程序的命令行参数。



4. wait和waitpid

在Linux系统中,父进程可以使用wait()waitpid()系统调用等待子进程的结束。这些系统调用会阻塞父进程的执行,直到子进程结束。


4.1 函数解释

wait()waitpid()是用于等待子进程结束并获取子进程的退出状态的函数。

  1. pid_t wait(int *status);

    • 函数会挂起当前进程,直到一个子进程结束。
    • 如果成功等到子进程结束,函数会返回子进程的进程ID。
    • 参数 status 是一个指向整型的指针,用于存储子进程的退出状态信息。
    • 如果调用失败,函数会返回-1。

  2. pid_t waitpid(pid_t pid, int *status, int options);

    • 函数会挂起当前进程,直到指定的子进程结束。
    • 参数 pid 指定要等待的子进程的进程ID。
    • 参数 status 是一个指向整型的指针,用于存储子进程的退出状态信息。
    • 参数 options 是一个整型值,用于指定等待的选项。
    • 如果调用失败,函数会返回-1。

wait()waitpid()函数的返回值是子进程的进程ID,如果调用失败,则返回-1。通过参数 status 可以获取子进程的退出状态信息,包括退出码、终止信号等。

waitpid()函数相比于wait()函数更加灵活,可以通过参数 pidoptions 控制等待的子进程。

其中,pid 的取值可以是:

  • -1:等待任意子进程。
  • 0:等待与当前进程组ID相同的子进程。
  • 具体的子进程ID:等待指定的子进程。

options 参数可以通过位掩码的方式指定多个选项,常用的选项有:

  • WNOHANG:非阻塞方式,如果没有子进程结束,立即返回。
  • WUNTRACED:也会返回已经停止的子进程的状态。
  • WCONTINUED:也会返回已经继续运行的子进程的状态。

wait()waitpid()函数可以用于处理子进程的退出状态,释放子进程的资源,并进行进程间的同步。在使用这两个函数时,需要注意处理错误情况和避免僵尸进程的产生。


4.2 函数示例

代码示例如下:

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

int main() {
    pid_t pid = fork();
    if (pid == -1) {
        printf("Failed to fork a new process.\n");
        return 1;
    } else if (pid == 0) {
        printf("This is the child process.\n");
    } else {
        wait(NULL);
        printf("This is the parent process.\n");
    }
    return 0;
}

上述代码中,父进程使用wait(NULL)系统调用等待子进程的结束。wait()系统调用会阻塞父进程的执行,直到子进程结束。



总结

  1. fork()函数:用于创建子进程,返回值不同表示在不同的进程中执行。
  2. exec()函数族:用于在当前进程中加载和执行新程序,可以实现程序的动态切换和功能扩展。
    • execl():接受可变参数的形式,参数以字符串形式传递。
    • execle():接受可变参数的形式,同时传递环境变量。
    • execvp():接受参数数组的形式,参数以字符串数组形式传递。
  3. wait()waitpid()函数:用于等待子进程结束并获取子进程的退出状态。
    • wait():等待任意子进程结束。
    • waitpid():可以指定等待的子进程。
    • 通过参数 status 可以获取子进程的退出状态信息。
    • 可以通过 options 参数控制等待的选项,如非阻塞方式等。
    • 需要注意处理错误情况和避免僵尸进程的产生。

这些函数和系统调用可以用于进程的创建、执行和等待,实现进程间的同步和协作。通过这些函数,可以实现进程的动态切换、功能扩展和资源释放。同时,需要注意处理错误情况,避免产生僵尸进程和资源泄漏的问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

消息中间件-kafka实战-第六章-kafka加线程池多线程消费

目录 参考架构图延时队列 参考 头条面试&#xff1a;当线上Kafka集群有大量消息积压时&#xff0c;如何利用多线程消费解决消费积压问题 架构图 延时队列

Python查找交作业人数

写在前面&#xff1a; 利用Python实现交作业具体情况&#xff0c;能够高效快捷地收集作业&#xff01; 一、问题&#xff1a;获取test文件夹下的所有文件 二、Python中os.listdir()函数的用法 &#xff08;一&#xff09;os.listdir()函数的基本用法 os.listdir()函数的基本…

linux系统中的中文显示问题

经常遇到这种情况&#xff1a;某些项目的文件中不可避免地包含有中文&#xff0c;在Windows系统中没有任何问题&#xff0c;拷到Linux系统中就出问题了。 1. Linux系统设置 $echo $LANG en_US.iso885915 朋友建议我设置为&#xff1a; export LANGzh_CN.utf8 但我这样设置之…

CSS中的z-index属性有什么作用?如何控制元素在层叠上下文中的显示顺序?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ z-index 属性的作用及控制元素层叠顺序作用 ⭐ 控制元素层叠顺序⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff0…

什么是flexbox布局?它有什么特点和优势?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Flexbox 布局&#xff1f;⭐ 特点和优势⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那…

数据结构,线性表,顺序表基础。

1.线性表 线性表特征&#xff1a; 对非空表&#xff0c;a0是表头&#xff0c;无前驱a(n-1)是表尾&#xff0c;无后继其他的都有ai前驱a(i-1)与后继a(i1)。 2、顺序结构存储方式是线性表存储的一种方式&#xff0c;主要体现形式为数组。 #include<stdio.h> #include<st…

密码学学习笔记(十八):Diffie–Hellman (DH) 密钥交换

DH算法是第一个密钥交换算法&#xff0c;也是第一个得到形式化描述的公钥密码算法。 群论 DH密钥交换算法基于数学中的群论&#xff0c;群论也是当今大多数公钥密码的基础。 要使集合及其运算成为一个群&#xff0c;需要满足以下性质&#xff1a; 封闭性&#xff1a;群中两…

Eureka 的几种主动下线服务的方式

补充&#xff1a;在启动eureka服务的时候发现控制台有以下的输出 由此猜想可以通过改接口下线服务&#xff0c; 于是尝试了一下。 果然能从注册中心中移除该实例。 1. 直接停掉服务。 默认情况下&#xff0c;如果Eureka Server在90秒没有收到Eureka客户的续约&#xff0c;它…

树莓派+WordPress:打造专属博客,内网穿透轻松发布到公网!

概述 在本次教程里&#xff0c;我们将在树莓派上搭建一个Wordpress博客站点&#xff0c;开始博客时代&#xff0c;记录生活点滴。同时做内网穿透将博客发布上线&#xff0c;让互联网用户都可以访问到&#xff0c;无需公网ip&#xff0c;也无需购买云服务器&#xff0c;简单快速…

内网隧道代理技术(十六)之 FRP的使用

FRP的使用和介绍 FRP介绍 FRP (Fast Reverse Proxy) 是一个使用 Go 语言开发的高性能的反向代理应用,可以轻松地进行内网穿透,对外网提供服务。FRP 支持 TCP、UDP、HTTP、HTTPS等协议类型,他支持点对点的转发,还有全流量转发,FRP最大的一个特点是使用SOCKS代理,而SOCKS…

10----超链接

在 Markdown 里可以创建超链接&#xff0c;以链接到其他 Markdown 页面或网站。 一、行内超链接&#xff1a; 行内式超链接是Markdown中创建超链接的一种方式&#xff0c;它的语法相对简单&#xff0c;适合在文本中直接插入链接。 1.链接到网站&#xff1a;[链接文本](链接地…

排序+运算>直接运算的效率的原因分析

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Facebook 应用未启用:这款应用目前无法使用,应用开发者已得知这个问题。

错误&#xff1a;Facebook 应用未启用:这款应用目前无法使用&#xff0c;应用开发者已得知这个问题。应用重新启用后&#xff0c;你便能登录。 「应用未经过审核或未发布」&#xff1a; 如果一个应用还没有经过Facebook的审核或者开发者尚未将应用发布&#xff0c;那么它将无法…

MySQL数据库——图形化界面工具(DataGrip),SQL(2)-DML(插入、修改和删除数据)

目录 图形化界面工具&#xff08;DataGrip&#xff09; 下载及安装 启动及连接 使用 创建数据库 创建表结构 编写SQL DML 插入 更新和删除 1.修改数据 2.删除数据 总结 图形化界面工具&#xff08;DataGrip&#xff09; 下载及安装 DataGrip下载链接&#xff1a;…

如何使用HTML5新增的表单元素来增强表单功能?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 1. <input type"email"> 和 <input type"url">⭐ 2. <input type"tel">⭐ 3. <input type"date">、<input type"time"> 和 <input type"datet…

求解方程sympy.solve

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 求解方程 sympy.solve [太阳]选择题 下列代码最后一次输出的结果是&#xff1f; import sympy x sympy.symbols(x) y x**2 2*x - 3 print("【执行】sympy.solve(y, x)") print(s…

TIA博途中打开全局库al文件以及压缩库zal文件的具体方法示例

TIA博途中打开全局库al文件以及压缩库zal文件的具体方法示例 本例中所有的库文件均以博途V15软件为例进行说明,其他版本的博途软件可能稍有区别,但总体相同。 如下图所示,打开博途软件后,在右侧的“库”—全局库,点击打开图标, 如下图所示,此时在弹出的窗口中找到后缀名…

华为OD机试 - 执行时长 - 回溯(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路1、大概意思就是&#xff1a;2、比如&#xff1a; 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff…

JavaWeb框架:Spring MVC介绍

Spring MVC 概述 概述 MVC&#xff08;Model View Controller&#xff0c;模型-视图-控制器&#xff09;&#xff0c;作为一种设计模式&#xff0c;用于应用程序的分层开发。 Spring MVC&#xff0c;由 Spring 框架提供的基于 MVC 设计模式的一个轻量级 Web 开发框架。Spring…

Android Studio连接逍遥模拟器

1、启动Android Studio&#xff0c;打开和同步好项目。 2、启动逍遥模拟器&#xff0c;会自动连接Android Studio。 3、运行app到模拟器中即可。 4、如果第二步启动后没有自动连接&#xff0c;就需要我们手动连接&#xff0c;进入安装目录&#xff0c;我的是D:\Xiaoyao moniqi\…