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

这篇具有很好参考价值的文章主要介绍了【Linux操作系统】深入探索Linux进程:创建、共享与管理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进程的创建是Linux系统编程中的重要概念之一。在本节中,我们将介绍进程的创建、获取进程ID和父进程ID、进程共享、exec函数族、wait和waitpid等相关内容。
【Linux操作系统】深入探索Linux进程:创建、共享与管理,操作系统,linux,运维,服务器


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 参数控制等待的选项,如非阻塞方式等。
    • 需要注意处理错误情况和避免僵尸进程的产生。

这些函数和系统调用可以用于进程的创建、执行和等待,实现进程间的同步和协作。通过这些函数,可以实现进程的动态切换、功能扩展和资源释放。同时,需要注意处理错误情况,避免产生僵尸进程和资源泄漏的问题。文章来源地址https://www.toymoban.com/news/detail-654743.html

到了这里,关于【Linux操作系统】深入探索Linux进程:创建、共享与管理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解操作系统中进程与线程的区别及切换机制(下)

    上一篇文章中我们了解了进程的执行方式,包括早期单核处理器上的顺序执行以及引入多任务概念实现的伪并行。我们还探讨了进程的状态模型。进程可以处于就绪、运行、阻塞和结束等不同的状态。 在本篇文章中,我将探讨研究进程的状态模型、控制结构和切换机制。希望

    2024年02月11日
    浏览(43)
  • 头歌操作系统-课堂练习3.2:进程的创建

    第1关:进程创建前后TR寄存器值的分析 编程要求 根据相关知识,回答问题: (将答案填写在 /data/workspace/myshixun/第一关.txt 中) 0 号进程的 fork 系统调用(main.c:147)中的陷入指令的地址是多少? 0 号进程执行 fork 系统调用之前,TR 寄存器的值为多少? 0 号进程刚执行完 for

    2023年04月26日
    浏览(52)
  • 头歌操作系统 课堂练习3.2:进程的创建

    本实训需要设置内核版本 1 为调试分析的对象,用 gdb 调试内核,内核版本 1 的压缩文件存放在 /data/workspace/myshixun/exp1 中。 环境配置详情请移步前几关~头歌操作系统 课后作业3.1:进程的描述与状态 编程要求 根据相关知识,回答问题: (将答案填写在 /data/workspace/myshixun/第

    2024年02月04日
    浏览(54)
  • 【Linux】操作系统&&进程概念

    冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构 。数学家冯·诺依曼提出了计算机制造的三个基本原则,即采用二进制逻辑、程序存储执行以及计算机由五个部分组成( 运算器、控制器、存储器、输入设备、输出设备 ),这

    2024年01月16日
    浏览(48)
  • Linux操作系统篇:进程

    我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么计算机要采用冯诺依曼体系呢? 在计算机出现之前有很多人都提出过计算机体系结构,但最终选择冯诺依曼是因为用比较少的钱就可以做出效率不错的计算机 截至目前,我们

    2024年03月18日
    浏览(47)
  • Linux--操作系统进程的状态

    【Linux】进程概念 —— 进程状态_linux d状态进程_Hello_World_213的博客-CSDN博客 新建: 字面意思,将你的task_struct创建出来并且还未入队列 运行: task_struct结构体在运行队列中排队,就叫做运行态 阻塞: 等待非CPU资源就绪,阻塞状态   挂起: 当内存不足的时候,OS通过适当的

    2024年02月15日
    浏览(52)
  • 操作系统课程设计-Linux 进程控制

    目录 前言 1 实验题目 2 实验目的 3 实验内容 3.1 进程的创建 3.1.1 步骤 3.1.2 关键代码 3.2 子进程执行新任务 3.2.1 步骤 3.2.2 关键代码 4 实验结果与分析 4.1 进程的创建 4.2 子进程执行新任务 5 代码 5.1 进程的创建 5.2 子进程执行新任务          本实验为课设内容,博客内容为

    2024年01月18日
    浏览(51)
  • Linux操作系统——第五章 进程信号

          目录 信号概念 用kill -l命令可以察看系统定义的信号列表 信号处理常见方式概览 产生信号 1. 通过终端按键产生信号 2. 调用系统函数向进程发信号 3. 由软件条件产生信号 4. 硬件异常产生信号 阻塞信号 1. 信号其他相关常见概念 2. 在内核中的表示 3. sigset_t 4. 信号集操作

    2024年02月11日
    浏览(47)
  • 【Linux】操作系统与进程的概念

    目录 冯诺依曼体系 注意 为什么CPU不直接访问输入或输出设备? 跨主机间数据的传递 操作系统 管理 进程 描述进程 进程的查看和终止  bash 通过系统调用创建子进程 fork的辨析 🥖冯·诺依曼结构也称普林斯顿结构,是一种 将程序指令存储器和数据存储器合并在一起的存储器

    2024年01月18日
    浏览(47)
  • 【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解

    1、概念 (1)什么是冯诺伊曼体系结构? 数学家冯·诺伊曼于 1946 年提出存储程序原理,把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式储存。 冯·诺伊曼理论的要点是:计算机的数制采用二进制逻辑;计算机应该按照程序顺序执行。人们把冯·诺伊曼的

    2024年02月22日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包