Linux 进程详解

news2024/11/29 0:31:54

目录

一、进程创建

二、进程API 

1. 进程创建 fork() 

2. 等待 wait()

3.执行 exec() 

3.1 execlp函数

3.2 execl函数

三、其他API 


一、进程创建

上文讲述了进程的概念,现在大家对于进程的定义已经有所了解了,本文主要介绍一下进程的基本信息,例如进程是怎么创建和结束的,怎么用操作系统提供的API去自己创建一个进程?

创建:在平时我们打开一个软件只需要双击图标,软件就会自己运行,或者在shell中输入命令就可以创建一个进程来运行程序,那么程序是如何转化为进程的呢?

 上图直观的显示出了这个过程,程序运行时首先操作系统会将程序运行需要的数据存入到内存,存入到进程的地址空间中。此时已经将程序的运行代码存到了进程的地址空间中,还需要分配一些堆栈空间用于程序执行,此时就完成了准备工作,最后就是启动程序运行,OS将CPU的控制权转移给进程,从而程序开始执行。

操作系统为每个进程分配独立的地址空间,确保进程之间的内存空间相互隔离,不会相互干扰或访问彼此的数据。,所以我们可以运行多个程序并且他们互不干扰

二、进程API 

1. 进程创建 fork() 

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

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // fork() 出错
        fprintf(stderr, "Fork failed\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()返回的值是不同的。fork() 调用返回两次,一次在父进程中返回子进程的进程 ID(PID),一次在子进程中返回0。通过这种方式,父进程和子进程可以根据返回值来确定自己的身份。

2. 等待 wait()

上述代码如果你多次运行后会发现运行后产生的结果不是固定的,有的情况下父进程会早于子进程被打印出来,这种不确定性是因为CPU调度程序来决定哪个进程先被执行,感兴趣可以了解一下系统调度算法

wait()是一个系统调用(或函数),用于父进程等待其子进程的结束。它允许父进程暂停执行,直到子进程完成执行为止。

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

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // fork() 出错
        fprintf(stderr, "Fork failed\n");
        return 1;
    } 
    else if (pid == 0) {
        // 子进程
        printf("This is the child process\n");
        sleep(2);  // 模拟子进程执行一段时间
        return 42;
    }
    else {
        // 父进程
        printf("This is the parent process\n");
        int status;
        pid_t child_pid = wait(&status);
        
        if (WIFEXITED(status)) {
            int exit_status = WEXITSTATUS(status);
            printf("Child process %d exited with status %d\n", child_pid, exit_status);
        } 
        else {
            printf("Child process %d did not exit normally\n", child_pid);
        }
    }

    return 0;
}

wait() 函数会阻塞父进程的执行,直到一个子进程结束。在子进程结束后,父进程会继续执行,并从 wait() 调用中返回。

wait() 函数的参数 status 是一个指向整型变量的指针,用于存储子进程的退出状态信息。可以使用宏函数 WIFEXITED(status)、WEXITSTATUS(status) 等来检查和获取子进程的退出状态。

wait() 函数可以等待任意一个子进程结束,也可以使用 waitpid() 函数等待指定的子进程。

3.执行 exec() 

给我可执行程序的名称及需要的参数后,exec()会从可执行程序中加载代码和静态数据,并用它覆写自己的代码段(以及静态数据)堆、栈及其他内存空间也会被重新初始化。然后操作系统就执行该程序,将参数通过argv传递给该进程。因此,它并没有创建新进程,而是直接将当前运行的程序替换为不同的运行程序

exec 系列的函数有多个变体,包括 execl、execv、execle、execve 等,每个变体在使用上略有不同,但它们的基本目标都是相同的:加载并执行一个新的程序。

我们主要介绍其中的两个:

3.1 execlp函数

成功无返回,失败返回-1。 

#include <unistd.h>

int execlp(const char *file, const char *arg0, ..., (char *) NULL);

execlp 函数接受可执行文件的名称(不需要完整路径)和一系列参数,以及一个以 NULL 结束的参数列表。它会在系统的路径中搜索与提供的文件名称匹配的可执行文件,找到后将加载并执行该程序。

3.2 execl函数

 成功无返回,失败返回-1。 

#include <unistd.h>

int execl(const char *path, const char *arg0, ..., (char *) NULL);

 加载一个进程,通过路径和程序名来加载

4.结束进程

  • exit() :在程序的任何地方调用 exit() 函数将导致程序立即退出。一般约定,状态码为 0 表示程序正常退出,非零状态码表示程序异常退出或出错。
  • 通过信号终止进程:kill <进程ID>
  • 强制终止进程: kill -9 <进程ID>

三、其他API 

 除了上面提到的 fork()、wait()和 exec()之外,还有其他许多与进程交互的方
式。比如可以通过 kill()系统调用向进程发送信号,包括要求进程睡眠、终止或其
他有用的指令。实实上,整个信号子系统提供了一套丰富的向进程传递外部事件的途径。

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

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

相关文章

Java基于微信小程序的乐室预约小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

15.隐式转换函数的封装

目录 概述实践代码测试 结束 概述 隐式转换函数 类似 java 中的切面编程&#xff0c;对原有类功能做增加。 实践 代码 封装代码如下 package com.fun.scala.demoimport java.io.File/*** 类似java切面的东东*/ object ImplicitAspect {implicit def man2SuperMan(man: Man):…

前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 第十二章 常用工具函数 (Utils配置)

前言 在项目开发中&#xff0c;我们经常会使用一些工具函数&#xff0c;也经常会用到例如loadsh等工具库&#xff0c;但是这些工具库的体积往往比较大&#xff0c;如果项目本身已经引入了这些工具库&#xff0c;那么我们就没有必要再引入一次&#xff0c;所以我们需要自己封装…

计算机网络基础入门指南

文章目录 网络分层模型OSI七层模型及其作用TCP/IP四层模型及作用为什么网络需要分层&#xff1f; 常见的网络协议应用层常见的协议传输层常见的协议网络层常见协议 从输入URL到页面展示的过程HTTP常见的状态码HTTP与HTTPS的区别HTTP是不保存状态的协议&#xff0c;如何保存用户…

DoRA(权重分解低秩适应):一种新颖的模型微调方法

来自&#xff1a;小互 DoRA&#xff08;权重分解低秩适应&#xff09;&#xff1a;一种新颖的模型微调方法 DoRA在LoRA的基础上进一步发展&#xff0c;通过将预训练权重分解为“幅度”和“方向”两个部分进行微调。 这种权重分解方法允许DoRA更精细地控制模型的学习过程&…

腾讯云助力酒店IT系统上云,实现出海业务的双重优势

潮起潮涌&#xff0c;随着时代浪潮的翻涌&#xff0c;生活处处可见是巨大的变化&#xff0c;衣食住行都有了更多更大的需求&#xff0c;出门旅游观赏当地风景品尝特色美食的前提是要住好&#xff0c;只有休息好了才有更多的精力去游玩。酒店系统的升级上云让登记变得更加便捷&a…

MAC电脑系统清理空间免费版软件CleanMyMac X2024

大家好&#xff0c;我是那个总是被苹果电脑“内存已满”提示搞得焦头烂额的专业博主。如果你也像我一样&#xff0c;在使用Mac时经常遭遇卡顿、慢吞吞的情况&#xff0c;那么今天的Mac清理空间妙招分享绝对适合你&#xff01; CleanMyMac X全新版下载如下: https://wm.makedi…

JVS智能BI的ETL数据集实践:数据自动化分析的秘诀

数据集是JVS-智能BI中承载数据、使用数据、管理数据的基础&#xff0c;同样也是构建数据分析的基础。可以通俗地将其理解为数据库中的普通的表&#xff0c;它来源于智能的ETL数据加工工具&#xff0c;可以将数据集进行分析图表、统计报表、数字大屏、数据服务等制作。 数据集管…

C++中对变量进行初始化的3种方法

1.用""&#xff1a;copy initialization&#xff0c;这种初始化形式是从C继承的。此种方式(拷贝初始化)的初始化在现代C中已不再受欢迎&#xff0c;因为对于某些复杂类型来说&#xff0c;此种方式初始化的效率低于其它形式的初始化。 每当隐式拷贝或转换值时&a…

【c语言】c语言转义字符详解

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;c语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

如何将OpenAI Sora生成的普通AI视频转化为Vision Pro的空间视频,沉浸式体验

【基于AI的Vision Pro空间视频】工作流:这个工作流程用于将2D视频转换为适用于 Vision Pro的Spatial视频: 1、使用Deep3D将2D视频转换为3D SBS: 使用Deep3D工具将2D视频转换为3D SBS格式: 转换例子:Prediction– lucataco/deep3d – Replicatehttps://replicate.com/…

文件上传之大文件分块上传之断点续传操作

断点续传概念&#xff1a; 断点续传是一种网络的传输机制&#xff0c;用于在文件传输过程中出现中断或错误时&#xff0c;能够恢复传输而不必重新开始&#xff0c;它解决了网络不稳定连续中断或大文件传输时时间过长等问题。提高了文件传输时可靠和效率性。 断点续传需求&…

浅谈js事件机制

事件是什么&#xff1f;事件模型&#xff1f; 原始事件模型&#xff08;DOM0级&#xff09; HTML代码中指定属性值&#xff1a;在js代码中指定属性值&#xff1a;优点&#xff1a;缺点&#xff1a; IE 事件模型DOM2事件模型 对事件循环的理解 宏任务&#xff08;Macrotasks&…

【Linux】软件包管理器 yum | vim编辑器

前言: 软件包管理器 yum和vim编辑器讲解 文章目录 软件包管理器 yum编辑器-vim四种模式普通模式批量化注释和批量化去注释末行模式临时文件 软件包管理器 yum yum&#xff08;Yellowdog Updater, Modified&#xff09;是一个在基于 RPM&#xff08;管理软件包的格式和工具集合&…

电影《社交网络》带来的深层次的思考

《社交网络》是由大卫芬奇执导&#xff0c;杰西艾森伯格、安德鲁加菲尔德、贾斯汀汀布莱克等主演的剧情片&#xff0c;于2010年10月8日在美国上映。该片讲述了马克扎克伯格和埃德华多萨瓦林两人如何建立和发展Facebook的故事。 学习关键点&#xff1a; 创业精神&#xff1a;电…

C++opencv图像算数操作-加减乘除

quick_opencv.h #include<opencv2\opencv.hpp> using namespace cv; class QuickDemo{public:void operators_demo(Mat &image);//图像算数操作 };QuickDemo.cpp #include<quick_opencv.h>//图像算数操作 void QuickDemo::operators_demo(Mat &image) {M…

八、计算机视觉-边界填充

文章目录 前言一、原理二、具体的实现 前言 在Python中使用OpenCV进行边界填充&#xff08;也称为zero padding&#xff09;是一种常见的图像处理操作&#xff0c;通常用于在图像周围添加额外的像素以便进行卷积或其他操作。下面是使用OpenCV进行边界填充的基本原理和方法 一…

解决elementUI固定列后,下方多了一条横线的问题

最近遇到一个bug,如下图,el-table的操作列使用fixed属性固定后,下方多了一条横线: 我们将样式设置高优先,以覆盖内联样式,如下是less里使用穿透样式解决的办法: <style lang="less" scoped> /deep/ .el-table__fixed-right {height: 100

vulvhub-----Hacker-KID靶机

打靶详细教程 1.网段探测2.端口服务扫描3.目录扫描4.收集信息burp suite抓包 5.dig命令6.XXE漏洞读取.bashrc文件 7.SSTI漏洞8.提权1.查看python是否具备这个能力2.使用python执行exp.py脚本&#xff0c;如果提权成功&#xff0c;靶机则会开放5600端口 1.网段探测 ┌──(root…

用户中心 -- 快捷键使用

一、后端&#xff0c;软件 idea 1.1 代码如何写出 网址&#xff1a;用户管理 --汇总 -- 明细-CSDN博客 1.2 一键调整代码格式的快捷键 网址&#xff1a; 用户管理第2节课 -- idea 2023.2 创建表--【本人】-CSDN博客