Linux(多进程与多线程)

news2024/9/22 19:35:30

目录

1、进程与线程概念

1.1 进程

1.2 线程

1.3 进程与线程区别

2、多进程

2.1多进程概念

2.2 进程相关API

2.3 多进程编程

3、多线程

3.1 多线程概念

3.2 多线程相关API

3.3 多线程编程


1、进程与线程概念

1.1 进程

在计算机科学中,进程是正在执行中的程序的实例。一个进程包括程序的代码、数据、执行上下文和操作系统分配的资源。进程是操作系统中的最小执行单位,操作系统通过管理和调度进程来实现多任务处理。

以下是关于进程的一些关键概念:

  1. 程序 vs. 进程

    • 程序(Program):是一个静态的代码文件,包含了计算机指令。程序本身并没有在计算机上执行,而只是一组指令的集合。
    • 进程(Process):是程序在计算机上实际运行的实例。进程拥有自己的内存空间、寄存器、执行状态等。
  2. 进程特点

    • 独立性:每个进程都是独立运行的实体,不受其他进程的影响。
    • 并发性:多个进程可以同时执行,操作系统通过时间分片等机制实现并发。
    • 动态性:进程可以创建、运行和结束,具有生命周期。
  3. 进程状态

    • 就绪(Ready):进程已准备好执行,等待分配处理器资源。
    • 运行(Running):进程正在执行指令。
    • 阻塞(Blocked):进程等待某个事件(如输入输出完成)发生。
    • 终止(Terminated):进程执行完毕或被终止。
  4. 进程间通信: 进程可能需要相互通信和协作。常用的进程间通信方式包括管道、信号、共享内存、消息队列和套接字等。

  5. 进程调度: 操作系统负责管理和调度进程的执行。调度算法决定了哪个进程将获得处理器资源,并控制进程之间的切换。

  6. 进程控制块(PCB): PCB 是操作系统用于管理和描述进程的数据结构,包含了进程的状态、程序计数器、寄存器值、内存指针等信息。

进程是操作系统的基础概念,操作系统通过对进程的管理和调度,实现了计算机的多任务处理和资源共享。

1.2 线程

线程(Thread)是操作系统中最小的调度单位,它是进程的一个执行流程,是在进程内部进行调度和执行的基本单元。线程在同一进程内共享该进程的内存空间和资源,但每个线程拥有自己的栈空间和寄存器状态。

以下是关于线程的一些关键概念:

  1. 线程特点

    • 线程是在进程内部创建和管理的。一个进程可以包含多个线程,这些线程共享进程的资源。
    • 线程之间的切换开销较小,因为它们共享同一进程的内存空间和上下文。
    • 线程的创建和销毁通常比进程更快,因为线程共享进程的资源,不需要为每个线程都创建独立的资源。
    • 线程可以用于实现并发执行,提高系统的响应性和资源利用率。
  2. 线程与进程的关系

    • 一个进程可以包含多个线程,这些线程共享进程的代码、数据和资源。
    • 多个线程在同一进程内运行,它们之间可以进行通信和同步。
    • 多个进程则是相互独立的,拥有各自独立的内存空间和资源。
  3. 线程调度: 操作系统负责管理和调度线程的执行。不同的线程调度算法决定了哪个线程将获得处理器资源。

  4. 线程同步: 在多线程编程中,线程之间可能会互相干扰或冲突。线程同步机制,如互斥锁、信号量和条件变量,用于协调线程之间的操作,以确保数据一致性和正确性。

  5. 用户级线程和内核级线程

    • 用户级线程:线程的创建、调度和管理完全由用户程序控制,操作系统对线程无感知。
    • 内核级线程:线程的创建、调度和管理由操作系统控制,操作系统直接管理线程。

线程是操作系统中的基本调度单位,适用于需要并发执行的任务。通过多线程编程,可以充分利用多核处理器的能力,提高程序的性能和响应性。但同时,多线程编程也需要考虑到线程安全和同步的问题。

1.3 进程与线程区别

  1. 资源分配: 进程有独立的资源(内存、文件句柄等),而线程共享所属进程的资源。
  2. 切换开销: 进程之间的切换开销较大,线程之间切换开销较小。
  3. 隔离性: 进程之间相互隔离,一个进程的错误不会影响其他进程;线程共享内存,一个线程的错误可能会影响其他线程。
  4. 通信与同步: 进程通信较复杂,线程之间共享内存,通信和同步更方便但也更容易出错。

通常来说,多线程编程更轻量,可以更好地利用多核处理器,但需要更仔细地处理并发访问共享资源的问题。多进程编程相对来说更安全,但开销较大。选择使用进程还是线程取决于你的应用需求和对多任务处理的优先级。

2、多进程

2.1多进程概念

多个独立的进程在不同的地址空间中运行,相对安全但开销较大。

多进程编程是一种并发编程的方式,它利用操作系统的多进程能力来实现多个任务的并行执行。在多进程编程中,每个任务被封装为一个独立的进程,它们在不同的内存空间中运行,相互之间相对独立。这种方法可以有效利用多核处理器,提高程序的性能和响应性。

2.2 进程相关API

  1. fork() 函数:

    • 作用:创建一个新的子进程,子进程是父进程的副本,执行相同的程序代码。
    • 返回值:在父进程中,返回子进程的 PID;在子进程中,返回 0;如果失败,返回 -1。
    • 头文件:<unistd.h>
  2. exec 函数族(如 execl, execv, execle, execve 等):

    • 作用:用于在当前进程中加载并执行一个新的程序。
    • 使用不同的函数名和参数,支持不同的参数传递方式。
    • 返回值:只在出错时返回 -1,成功执行后不会返回。
  3. wait()waitpid() 函数

    • 作用:等待子进程结束,以获取子进程的退出状态。
    • wait() 阻塞调用进程,直到任意子进程退出。
    • waitpid() 允许指定要等待的子进程的 PID,可以非阻塞等待。
    • 返回值:退出的子进程 PID 或 -1(出错时)。
    • 头文件:<sys/wait.h>
  4. exit() 函数

    • 作用:终止调用进程,并返回一个状态码给父进程。
    • 参数:传递给父进程的状态码。
    • 没有返回值,直接终止进程。
  5. getpid() 函数:

    • 作用:获取当前进程的 PID(进程标识符)。
    • 返回值:当前进程的 PID。
    • 头文件:<unistd.h>
  6. getppid() 函数:

    • 作用:获取当前进程的父进程的 PID。
    • 返回值:父进程的 PID。
    • 头文件:<unistd.h>
  7. kill() 函数:

    • 作用:向指定进程发送信号。
    • 参数:目标进程的 PID 和信号编号。
    • 返回值:成功返回 0,失败返回 -1。
  8. getuid()getgid() 函数:

    • 作用:获取当前进程的用户 ID 和组 ID。
    • 返回值:用户 ID 和组 ID。
    • 头文件:<unistd.h>
  9. setuid()setgid() 函数:

    • 作用:设置当前进程的用户 ID 和组 ID。
    • 参数:要设置的用户 ID 和组 ID。
    • 返回值:成功返回 0,失败返回 -1。
  10. sleep() 函数:

    • 作用:让当前进程休眠一段指定的时间。
    • 参数:休眠时间(秒)。
    • 返回值:休眠完毕后返回剩余休眠时间(0 表示完整休眠,-1 表示休眠被中断)。

2.3 多进程编程

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h> // 包含用于等待子进程的头文件

int main() {
    // 创建第一个子进程
    // 在父进程中,fork() 函数返回子进程的 PID,而在子进程中,fork() 返回 0。
    pid_t child1_pid = fork();

    if (child1_pid == -1) {
        // fork() 失败时返回 -1,输出错误信息并退出程序
        perror("Error creating child process");
        return 1;
    }

    if (child1_pid == 0) {
        // 子进程 1 逻辑
        printf("Child 1: My PID is %d\n", getpid());
        // 子进程 1 执行完毕
        return 0;
    }

    // 创建第二个子进程
    pid_t child2_pid = fork();

    if (child2_pid == -1) {
        // fork() 失败时返回 -1,输出错误信息并退出程序
        perror("Error creating child process");
        return 1;
    }

    if (child2_pid == 0) {
        // 子进程 2 逻辑
        printf("Child 2: My PID is %d\n", getpid());
        // 子进程 2 执行完毕
        return 0;
    }

    // 父进程逻辑
    printf("Parent: My PID is %d\n", getpid());
    printf("Parent: Child 1 PID is %d, Child 2 PID is %d\n", child1_pid, child2_pid);

    // 等待两个子进程执行完毕
    wait(NULL); // 等待第一个子进程
    wait(NULL); // 等待第二个子进程

    return 0;
}

运行结果

3、多线程

3.1 多线程概念

同一进程内的多个线程共享同一地址空间,更轻量但需要注意同步和共享数据。多线程编程可以提高程序的并发性和效率。然而,多线程编程需要注意处理并发访问共享资源的问题,如线程安全和竞态条件。

多线程编程是在同一个进程内创建和管理多个线程,使得这些线程可以并发执行不同的任务。每个线程共享进程的内存空间和资源,但每个线程有自己的栈空间和执行上下文。

3.2 多线程相关API

  1. pthread_create() 函数:

    • 作用:创建一个新线程。
    • 参数:新线程的引用、线程属性、线程函数和参数。
    • 返回值:成功创建线程时返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  2. pthread_join() 函数:

    • 作用:等待一个线程终止,并获取它的退出状态。
    • 参数:要等待的线程的引用、线程退出状态的指针。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  3. pthread_exit() 函数:

    • 作用:终止当前线程,可指定线程退出状态。
    • 参数:线程退出状态。
    • 没有返回值,直接终止线程。
    • 头文件:<pthread.h>
  4. pthread_self() 函数:

    • 作用:获取当前线程的线程 ID。
    • 返回值:当前线程的线程 ID。
    • 头文件:<pthread.h>
  5. pthread_mutex_init() 函数:

    • 作用:初始化互斥锁。
    • 参数:互斥锁引用和互斥锁属性(可为 NULL)。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  6. pthread_mutex_lock()pthread_mutex_unlock() 函数:

    • 作用:锁定和解锁互斥锁。
    • 参数:互斥锁引用。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  7. pthread_mutex_destroy() 函数:

    • 作用:销毁互斥锁。
    • 参数:互斥锁引用。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  8. pthread_cond_init() 函数:

    • 作用:初始化条件变量。
    • 参数:条件变量引用和条件变量属性(可为 NULL)。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  9. pthread_cond_wait()pthread_cond_signal() 函数:

    • 作用:等待和唤醒条件变量。
    • 参数:条件变量引用和互斥锁引用。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>
  10. pthread_cond_destroy() 函数:

    • 作用:销毁条件变量。
    • 参数:条件变量引用。
    • 返回值:成功返回 0,否则返回错误码。
    • 头文件:<pthread.h>

3.3 多线程编程

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NUM_THREADS 4 //创建线程数量

// 共享资源
int shared_counter = 0;
pthread_mutex_t mutex; // 互斥锁

// 增加计数器的函数,多个线程会同时调用这个函数
void* increment_counter(void* arg) {
    for (int i = 0; i < 100000; ++i) {
        pthread_mutex_lock(&mutex); // 加锁,开始临界区
        shared_counter++; // 对共享资源进行操作
        pthread_mutex_unlock(&mutex); // 解锁,结束临界区
    }
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS]; // 存储线程的数组
    
    pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
    
    // 创建多个线程
    for (int i = 0; i < NUM_THREADS; ++i) {
        pthread_create(&threads[i], NULL, increment_counter, NULL);
    }
    
    // 等待所有线程执行完毕
    for (int i = 0; i < NUM_THREADS; ++i) {
        pthread_join(threads[i], NULL);
    }

    pthread_mutex_destroy(&mutex); // 销毁互斥锁

    printf("Final counter value: %d\n", shared_counter);
    
    return 0;
}

运行结果(为啥输出了三次?

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

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

相关文章

【PyQt】QGraphicsView场景导出为图片

1 需求 需要将用户绘制的场景导出为图片。即 QGraphicsView中的Scene导出为图片。 2 代码 # 提示&#xff1a;此函数应能访问 QGraphicsView 对象。 # 参考&#xff1a;作者的项目中&#xff0c;此函数在某个QMainWindow类中&#xff0c;作为导出按钮的槽函数。import sys …

QGIS学习2-QGIS设置中文界面、导出地图、修改显示投影、自定义投影等

1、设置中文界面 参照官方给的提示&#xff1a; https://qgis.org/en/site/getinvolved/translate.html 2、QGIS功能介绍 QGIS支持功能还是很全面的。 而且提供了很全面的插件库 https://plugins.qgis.org/plugins/ 3、工程文档介绍 可以直接从菜单栏对工程文档进行操作…

SpringBoot在IDEA里实现热部署

使用步骤 1.引入依赖 <!--devtools热部署--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional><scope>true</scope><versi…

QChart——折线

Qchart的图形显示依附于QChartView&#xff0c;创建一个QChartView继承类&#xff0c;通过窗口部件的提升进行图表的显示 一、简单认识QLineSeries QLineSeries属于折线类&#xff0c;它继承于QXYSeries类&#xff0c;可以使用QXYSeries类所有方法&#xff0c;对折线进行属性设…

Jmeter(二十八):beanshell的使用

Beanshell 是一种轻量级的 Java 脚本,纯 Java 编写的,能够动态的执行标准 java 语法及一些扩展脚本语法,类似于 javaScript,在工作中可能用的多的就是: Beanshell 取样器:跟Http取样器并列Beanshell前置处理器:一般放在Http请求下,在请求前处理一些数据Beanshell后置处…

Spring Boot进阶(59):【实战教程】使用Spring Boot集成InfluxDB时序数据库,打造高效数据监控系统!

1. 前言&#x1f525; 前几期我们陆续讲解了Mysql、Redis、PostgreSQL、MongoDB等数据库集成及使用案例&#xff0c;接下来&#xff0c;bug菌继续给同学们介绍一种特殊的数据库&#xff0c;到底是什么数据库呢&#xff1f;它就是InfluxDB(时序数据库)&#xff0c;InfluxDB是一款…

Docker vs. Podman: 选择容器技术的智慧之选

嗨&#xff0c;各位亲爱的程序员小伙伴们&#xff01;当我们步入容器技术的世界&#xff0c;往往会在众多选择中迷茫。两个备受瞩目的容器工具&#xff0c;Docker 和 Podman&#xff0c;都在业界掀起了一股风潮。今天&#xff0c;我将带你深入探索&#xff0c;为什么在 Docker …

day 40 | 139. 单词拆分

139. 单词拆分 首先要明确这个是求排列数&#xff0c;所以是先遍历背包&#xff0c;再遍历物品。 func wordBreak(s string, wordDict []string) bool {dp : make([]bool, len(s) 1)dp[0] truefor j : 1; j < len(s); j{for i : 0; i < len(wordDict); i{if j - len…

Sloare flare网卡信息

详细的安装信息 https://github.com/Xilinx-CNS/onload/tree/master/scripts 进行下载 Solarflare网卡开发:openonload 安装与调试_openonload安装_Erice_s的博客-CSDN博客 cns-sfnettest测试 cns-sfnettest 下载

李沐pytorch学习-BatchNormalization

一、意义 在使用较深的网络时&#xff0c;BatchNormalization&#xff08;批量归一化&#xff09;几乎是必需的&#xff0c;可以加速收敛。 对于图1所示的全连接层神经网络&#xff0c;输出节点的GroundTruth为&#xff0c;损失函数为&#xff0c;则损失对权重的梯度为&#xf…

char *str 与char str[]的区别与联系

char *str 与char str[]的区别与联系 常用以下两种方式定义字符串&#xff1a;一种是字符数组&#xff0c;另一种是指向字符串的指针。 文章目录 char *str 与char str[]的区别与联系一、基本概念区别二、名称含义区别三、底层属性区别1.char *str "abcdefgh"2.cha…

MDK 5.xx.0 + STM32F10x 笔记

天才脑袋比不上烂笔头, 写给自己看, 自用资料。 安装MDK STM32环境 Download MDK安装 MDK -> c:\keil_v5 用默认路径下载 ARMCC V5.06 Update 7 (build960) <- 长期稳定支持版本安装至 c:\keil_v5\arm\ARMCC开启 uVision.设定 预设编译程序版本 : V5.06 Update 7 (bui…

C# 学习笔记--个人学习使用 <1>

C# 学习笔记 Chapter 1 C# 比较软的基础部分Section 1 类与命名空间Part 1 命名空间 NameSpacePart 2 类 Class Section 2 基本元素Section 3 数据类型Part 1 什么是类型&#xff1f;Part 2 类型在 C Sharp 中的作用Part 3 C Sharp 中的数据类型 Section 4 变量、对象与内存Par…

GIthub 无法访问使用Watt Toolkit加速

一、使用 Watt Toolkit Watt Toolkit 是一款加速软件&#xff0c;原名是 Steam&#xff0c;后来改名为 Watt Toolkit&#xff0c;其可以让原本无法访问的 Steam 游戏社区、 GitHub 、谷歌验证码等国内难以访问的网页正常访问。 三种下载方式&#xff1a; Watt Toolkit 官网下…

STM32的时钟系统

今天&#xff0c;学习了STM32的时钟系统&#xff0c;如下为stm32的时钟树。

[牛客复盘] 牛客周赛 Round 9 20230827

[牛客复盘] 牛客周赛 Round 9 20230827 总结小美的外卖订单编号1. 题目描述2. 思路分析3. 代码实现 小美的加法1. 题目描述2. 思路分析3. 代码实现 小美的01串翻转1. 题目描述2. 思路分析3. 代码实现 小美的数组操作1. 题目描述2. 思路分析3. 代码实现 六、参考链接 总结 又是…

Linux c++开发-02-g++命令行编译

有如下的文件目录结构 格式一 swap.h swap.cpp main.cpp 编译方法和结果如下&#xff1a; 格式二 swap.cpp main.cpp 使用命令&#xff1a;g main.cpp src/swap.cpp -o main.exe 解决方法使用参数 -I 格式三-将swap.cpp生成一个静态库然后链接到main.cpp中 生成…

某人事系统架构搭建设计记录

首发博客地址 https://blog.zysicyj.top/ 先大致列一下基础情况 架构必须是微服务 场景上涉及大量查询操作&#xff0c;分析操作 并发并不高 对高可用要求较高&#xff0c;不能挂掉 对安全要求高 要能过等保测试等三方测试 使用人数并不多&#xff0c;十万内 涉及很多在线编辑&…

多线程学习之解决线程同步的实现方法

一、卖票的多线程实现 需求&#xff1a;共有100张票&#xff0c;而它有3个窗口卖票&#xff0c;请设计一个程序模拟该电影院卖票 代码实现&#xff1a; /*** Author&#xff1a;kkoneone11* name&#xff1a;SellTicket1* Date&#xff1a;2023/8/26 11:32*/ public class S…

mit s0681 lab2 Trace系统调用实现

实验一 实现一个用户级别的程序&#xff0c;功能为&#xff0c;指定系统调用后&#xff0c;跟踪程序的系统调用情况 分析实验 实验目标为实现一个程序去跟踪指定程序的系统调用。因此目标有两个 实现一个程序跟踪目标程序的系统调用 实现1&#xff0c;就需要在用户这边实…