【C语言】进程和线程详解

LuckiBit

目录

  • C语言进程和线程详解
    • 1. 进程和线程的对比
    • 2. 进程的基本概念
      • 2.1 进程的定义
      • 2.2 进程的特点
      • 2.3 进程的生命周期
    • 3. 进程管理
      • 3.1 进程创建
      • 3.2 进程间通信(IPC)
        • 3.2.1 管道(Pipe)
    • 4. 线程的基本概念
      • 4.1 线程的定义
      • 4.2 线程的特点
    • 5. POSIX线程库
      • 5.1 引用头文件
      • 5.2 创建线程
        • 示例:
      • 创建线程步骤表格
      • 5.3 等待线程结束
      • 5.4 线程同步
        • 5.4.1 互斥锁
        • 示例:
        • 5.4.2 条件变量
        • 示例:
    • 6. 实战:生产者-消费者问题
      • 6.1 问题描述
      • 6.2 解决方案
    • 7. 进程和线程在应用中的选择
    • 8. 总结
    • 9. 结束语
    • 相关文章:

C语言进程和线程详解

1. 进程和线程的对比

在现代操作系统中,进程和线程是实现并发执行的两种主要方式。理解它们的区别和各自的应用场景对于编写高效的并发程序至关重要。

特性进程线程
定义进程是操作系统中独立运行的基本单位,有自己的地址空间和资源。线程是进程中的一个执行单元,多个线程共享同一个进程的资源。
地址空间每个进程有独立的地址空间。线程共享进程的地址空间。
资源开销进程切换开销较大,需保存和恢复全部上下文。线程切换开销较小,只需保存和恢复部分上下文。
通信方式进程间通信(IPC)机制,如管道、消息队列、共享内存等。线程间可以直接通信,共享全局变量和内存。
创建和销毁创建和销毁进程开销较大。创建和销毁线程开销较小。
适用场景适用于需要高隔离性和安全性的独立任务。适用于需要高并发和低开销的任务。

2. 进程的基本概念

2.1 进程的定义

进程是操作系统中独立运行的基本单位,一个进程通常由程序代码、数据段、堆、栈和相关资源(如文件描述符等)组成。

2.2 进程的特点

  • 独立性:每个进程有独立的地址空间。
  • 隔离性:进程之间的数据是隔离的,通常需要通过进程间通信(IPC)进行数据交换。
  • 资源拥有:进程拥有自己的资源,如内存、文件描述符等。

2.3 进程的生命周期

进程的生命周期包括创建、执行、阻塞、唤醒和终止等状态转换。

3. 进程管理

3.1 进程创建

在C语言中,可以使用fork系统调用来创建一个新进程。fork会创建一个与原进程(父进程)几乎相同的新进程(子进程),子进程会从fork调用的地方开始执行。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid;pid = fork(); // 创建子进程if (pid < 0) { // 创建失败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;
}

3.2 进程间通信(IPC)

进程间通信是指在不同进程之间传递数据和信号的机制。常见的IPC方式包括管道、消息队列和共享内存等。

3.2.1 管道(Pipe)

管道是一种单向的通信机制,一个进程可以通过管道将数据发送给另一个进程。

#include <stdio.h>
#include <unistd.h>int main() {int fd[2]; // 文件描述符数组char buffer[30];pipe(fd); // 创建管道if (fork() == 0) { // 子进程close(fd[0]); // 关闭读取端write(fd[1], "Hello, parent!", 15); // 写入数据close(fd[1]); // 关闭写入端} else { // 父进程close(fd[1]); // 关闭写入端read(fd[0], buffer, sizeof(buffer)); // 读取数据printf("Received: %s\n", buffer);close(fd[0]); // 关闭读取端}return 0;
}

4. 线程的基本概念

4.1 线程的定义

线程是进程中的一个执行单元,多个线程共享同一个进程的地址空间和资源。线程是实现并发执行的基本单位。

4.2 线程的特点

  • 并发执行:线程可以并发执行,提高程序的响应性和处理能力。
  • 共享资源:线程共享进程的内存和资源,通信和数据共享更方便。
  • 轻量级:线程的创建和切换开销较小。

5. POSIX线程库

POSIX线程库(pthreads)是一个广泛使用的跨平台线程库,适用于Unix和类Unix系统,如Linux和MacOS。通过pthreads库,C语言可以方便地进行多线程编程。

5.1 引用头文件

使用pthreads库时,需要包含pthread.h头文件。

#include <pthread.h>

5.2 创建线程

创建线程可以使用pthread_create函数,该函数原型如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
  • thread:指向线程标识符的指针。
  • attr:线程属性,通常设置为NULL
  • start_routine:线程执行的函数。
  • arg:传递给线程函数的参数。
示例:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>// 线程函数,打印传递的消息
void* print_message(void* arg) {char* message = (char*)arg;printf("%s\n", message);return NULL;
}int main() {pthread_t thread; // 线程标识符const char* message = "Hello, pthread!"; // 线程参数// 创建线程if (pthread_create(&thread, NULL, print_message, (void*)message)) {fprintf(stderr, "Error creating thread\n");return 1;}// 等待线程结束pthread_join(thread, NULL);return 0;
}

创建线程步骤表格

步骤说明代码示例
1包含头文件#include <pthread.h>
2定义线程函数void* print_message(void* arg) { ... }
3声明线程标识符pthread_t thread;
4创建线程并指定线程函数和参数pthread_create(&thread, NULL, ...);
5等待线程结束pthread_join(thread, NULL);

5.3 等待线程结束

使用pthread_join函数可以等待线程结束,原型如下:

int pthread_join(pthread_t thread, void **retval);
  • thread:线程标识符。
  • retval:指向线程返回值的指针。

5.4 线程同步

线程同步是多线程编程中的一个重要问题,pthreads库提供了多种同步机制,如互斥锁(mutex)、条件变量(condition variable)和读写锁(read-write lock)。

5.4.1 互斥锁

互斥锁用于保护共享资源,防止多个线程同时访问,导致数据不一致。

  • 初始化互斥锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  • 锁定互斥锁
pthread_mutex_lock(&lock);
  • 解锁互斥锁
pthread_mutex_unlock(&lock);
示例:
#include <pthread.h>
#include <stdio.h>pthread_mutex_t lock; // 互斥锁
int counter = 0; // 共享资源// 线程函数,增加计数器并打印
void* increment_counter(void* arg) {pthread_mutex_lock(&lock); // 锁定互斥锁counter++;printf("Counter: %d\n", counter);pthread_mutex_unlock(&lock); // 解锁互斥锁return NULL;
}int main() {pthread_t thread1, thread2;pthread_mutex_init(&lock, NULL); // 初始化互斥锁pthread_create(&thread1, NULL, increment_counter, NULL); // 创建线程1pthread_create(&thread2, NULL, increment_counter, NULL); // 创建线程2// 等待两个线程结束pthread_join(thread1, NULL);pthread_join(thread2, NULL);pthread_mutex_destroy(&lock); // 销毁互斥锁return 0;
}
5.4.2 条件变量

条件变量用于线程间的条件同步,一个线程可以等待某个条件满足,另一个线程可以通知条件的变化。

  • 初始化条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  • 等待条件变量
pthread_cond_wait(&cond, &mutex);
  • 发送条件信号
pthread_cond_signal(&cond);
示例:
#include <pthread.h>
#include <stdio.h>pthread_mutex_t lock;
pthread_cond_t cond;
int ready = 0; // 条件变量的条件// 线程函数,等待条件满足
void* wait_for_condition(void* arg) {pthread_mutex_lock(&lock);while (!ready) {pthread_cond_wait(&cond, &lock); // 等待条件变量}printf("Condition met, proceeding...\n");pthread_mutex_unlock(&lock);return NULL;
}// 线程函数,改变条件并通知
void* signal_condition(void* arg) {pthread_mutex_lock(&lock);ready = 1;pthread_cond_signal(&cond); // 发送条件信号pthread_mutex_unlock(&lock);return NULL;
}int main() {pthread_t thread1, thread2;pthread_mutex_init(&lock, NULL);pthread_cond_init(&cond, NULL);pthread_create(&thread1, NULL, wait_for_condition, NULL);pthread_create(&thread2, NULL, signal_condition, NULL);pthread_join(thread1, NULL);pthread_join(thread2, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&cond);return 0;
}

6. 实战:生产者-消费者问题

生产者-消费者问题是多线程编程中的经典问题,生产者线程生成数据,消费者线程消费数据,两者通过缓冲区进行通信,需要使用互斥锁和条件变量来确保线程同步。

6.1 问题描述

  • 生产者:生产数据并放入缓冲区,如果缓冲区满则等待。
  • 消费者:从缓冲区取出数据并消费,如果缓冲区空则等待。

6.2 解决方案

使用互斥锁和条件变量解决生产者-消费者问题:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#define BUFFER_SIZE 10int buffer[BUFFER_SIZE]; // 缓冲区
int count = 0; // 缓冲区中的数据量pthread_mutex_t lock;
pthread_cond_t not_empty;
pthread_cond_t not_full;void* producer(void* arg) {int i = 0;while (1) {pthread_mutex_lock(&lock);while (count == BUFFER_SIZE) {pthread_cond_wait(&not_full, &lock); // 缓冲区满,等待}buffer[count++] = i;printf("Produced: %d\n", i++);pthread_cond_signal(&not_empty); // 通知消费者缓冲区不空pthread_mutex_unlock(&lock);sleep(1); // 模拟生产时间}return NULL;
}void* consumer(void* arg) {int item;while (1) {pthread_mutex_lock(&lock);while (count == 0) {pthread_cond_wait(&not_empty, &lock); // 缓冲区空,等待}item = buffer[--count];printf("Consumed: %d\n", item);pthread_cond_signal(&not_full); // 通知生产者缓冲区不满pthread_mutex_unlock(&lock);sleep(1); // 模拟消费时间}return NULL;
}int main() {pthread_t prod, cons;pthread_mutex_init(&lock, NULL);pthread_cond_init(&not_empty, NULL);pthread_cond_init(&not_full, NULL);pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&not_empty);pthread_cond_destroy(&not_full);return 0;
}

在这个示例中,我们创建了一个生产者线程和一个消费者线程,生产者线程不断生成数据并放入缓冲区,而消费者线程不断从缓冲区取出数据并消费。通过互斥锁和条件变量,确保了生产者和消费者之间的正确同步。

7. 进程和线程在应用中的选择

在实际应用中,选择使用进程还是线程取决于具体的需求和场景。

  • 进程适用于需要高隔离性和安全性的任务,如独立的服务或后台进程。
  • 线程适用于需要高并发和低开销的任务,如多线程服务器或实时数据处理。

通过合理地使用进程和线程,可以提高程序的效率和性能,实现更高效的并发执行。

8. 总结

进程和线程是操作系统中实现并发执行的两种主要方式,各有优缺点和适用场景。通过理解它们的基本概念和特点,以及掌握相关的编程技巧和同步机制,可以编写出高效的并发程序,充分利用多核处理器的计算能力。

  • 进程具有独立的地址空间和资源,适用于需要高隔离性和安全性的任务。
  • 线程共享进程的地址空间和资源,适用于需要高并发和低开销的任务。
  • POSIX线程库(pthreads)提供了强大的多线程编程接口,可以方便地创建和管理线程,实现线程间的同步和通信。

通过上述详解,相信你对C语言中的进程和线程有了更深入的理解,并能够在实际编程中灵活运用。

9. 结束语

  1. 本节内容已经全部介绍完毕,希望通过这篇文章,大家对C语言进程和线程详解有了更深入的理解和认识。
  2. 感谢各位的阅读和支持,如果觉得这篇文章对你有帮助,请不要吝惜你的点赞和评论,这对我们非常重要。再次感谢大家的关注和支持!点我关注❤️

相关文章:

  • 指针的神秘探险:从入门到精通的奇幻之旅 !

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

正则表达式匹配成对括号

匹配一对括号&#xff0c;用于在一个html文本中提取JSon 文本。例如 { “duration”:7599,"minBufferTime{second bracket }{third bracket} } 一对加粗的{} &#xff0c;而不要中间的{}。简单写法会出现错误匹配。 在.Net Framework的正则表达式中&#xff0c;提供了”…

大数据-100 Spark 集群 Spark Streaming DStream转换 黑名单过滤的三种实现方式

喜大普奔&#xff01;破百了&#xff01; 点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&a…

Java框架Shiro、漏洞工具利用、复现以及流量特征分析

Shiro流量分析 前言 博客主页&#xff1a; 靶场&#xff1a;Vulfocus 漏洞威胁分析平台 Shiro&#xff08;Apache Shiro&#xff09;是一个强大且灵活的开源安全框架&#xff0c;专为Java应用程序提供安全性解决方案。它由Apache基金会开发和维护&#xff0c;广泛应用于企业级…

毛利率承压连亏三年后一季度业绩暴增,百利天恒谋求A+H双上市

《港湾商业观察》施子夫 7月10日&#xff0c;四川百利天恒药业股份有限公司&#xff08;以下简称&#xff0c;百利天恒&#xff09;递表港交所主板&#xff0c;联席保荐机构高盛、摩根大通和中信证券。 此次递表港交所系百利天恒第二次谋求上市&#xff0c;若上市成功&#x…

PyTorch升级之旅——安装与基本知识

目录 一、安装 二、张量 创建tensor 张量的操作 广播机制 三、自动求导 四、并行计算 &#xff08;一&#xff09;网络结构分布到不同的设备中(Network partitioning) &#xff08;二&#xff09;同一层的任务分布到不同数据中(Layer-wise partitioning) &#xff08;…

GoModule

GOPATH 最早的就是GOPATH构建模式&#xff0c; go get下载的包都在path中的src目录下 src目录是源代码存放目录。 package mainimport ("net/http""github.com/gorilla/mux" )func main() {r : mux.NewRouter()r.HandleFunc("/hello", func(w h…

解决使用matplotlib不显示中文的问题

某季度某城市某天11点到12点气温变化图 import random x range(60) y_BeiJing [random.uniform(15,18) for i in x] plt.figure(figsize(20,8),dpi80) plt.plot(x,y_BeiJing) x_label ["11点{}分".format(i) for i in x] plt.xticks(x[::5],x_label[::5]) plt.yt…

【精选】基于微信小程序的地铁站点查询系统(全网独一无二,阿龙原创设计)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

C# x Unity面向对象补全计划 设计模式 之 实现一个简单的有限状态机

一个简单的有限状态机可以有如下内容 1.状态基类&#xff08;定义基本状态的方法&#xff0c;如进入&#xff08;Enter&#xff09;、执行&#xff08;Execute&#xff09;和退出&#xff08;Exit&#xff09;&#xff0c;同时可以在此声明需要被管理的对象&#xff09; 2.具体…

【精选】基于python的影片数据爬取与数据分析

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

软件设计师教程(第5版)第5章 软件工程基础知识(更新中)

5.1 软件工程概述 【软件工程】是指应用计算机科学、数学及管理科学等原理,以工程化的原则和方法来解决软件问题的工程&#xff0c;其目的是提高软件生产率、提高软件质量、降低软件成本。P239 5.1.1 计算机软件 计算机软件是指计算机系统中的【程序】及其【文档】。P240 【…

一文解决---IDEA汉化问题(含中英文切换)

一、英文->中文&#xff1a; ①.下载汉化包插件&#xff1a; 操作顺序&#xff1a;File->Settings->Plugins 在搜索框输入Chinese&#xff0c;然后找到 Chinese (Simplified) Language &#xff08;汉化插件&#xff09;&#xff0c;等待下载完→Install (安装)&…

OpenCV几何图像变换(9)仿射变换函数warpAffine()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 函数是应用一个仿射变换到图像上。 warpAffine 函数使用指定的矩阵对源图像进行仿射变换&#xff1a; dst ( x , y ) src ( M 11 x M 12 y M…

《机器学习》 决策树剪枝、树模型参数及案例演示

目录 一、决策树剪枝 1、什么是决策树剪枝&#xff1f; 2、如何剪枝 3、剪枝剪哪个位置的叶子结点 二、树模型参数及用法 1、参数种类 2、参数解释 1&#xff09;criterion&#xff1a;gini or entropy 2&#xff09;splitter&#xff1a;best or random 3&#xff0…

从心理学的角度,探究一下人类为什么爱玩游戏。(缓解压力、社交需求、 获得成就感)

文章目录 引言I 游戏中的美学和文化元素,是影响玩家心理状态的关键因素。音乐美工文化背景II 成年人对游戏的心理需求获得成就感社交需求缓解压力III 心流理论(Flow Theory)解释玩家虽受虐,但也其乐无穷的现象知识扩展: 心流知识扩展: 心流活动知识扩展:得性乐观(Learne…

新版本 | GreatSQL 8.0.32-26全新发布 增强“四高”诸多新特性

近日&#xff0c;GreatSQL开源数据库社区正式发布 GreatSQL 8.0.32-26新版本&#xff0c;在高可用、高性能、高兼容、高安全等诸多方面进行了特性增强&#xff0c;修复多个缺陷&#xff0c;并详细说明了多个典型应用场景下&#xff0c;升级/降级到GreatSQL 8.0.32-26的操作策略…

Linux自旋锁和读写锁

在前面的文章中我们已经介绍了有关互斥锁的概念与使用&#xff0c;本篇将开始介绍在 Linux 中的自旋锁和读写锁。这三种锁分别用于在不同的应用场景之中&#xff0c;其中互斥锁最为常用&#xff0c;但是我们需要了解一下其他的锁。 对于自旋锁和读写锁都介绍了其原理以及接口使…

游戏如何对抗 IL2cppDumper逆向分析

众所周知&#xff0c;Unity引擎中有两种脚本编译器&#xff0c;分别是 Mono 和 IL2CPP 。相较于Mono&#xff0c;IL2CPP 具备执行效率高、跨平台支持等优势&#xff0c;已被大多数游戏采用。 IL2CPP 模式下&#xff0c;可以将游戏 C# 代码转换为 C 代码&#xff0c;然后编译为…

GPT-4o System Card is released

GPT-4o System Card is released, including red teaming, frontier risk evaluations, and other key practices for industrial-strength Large Language Models. https://openai.com/index/gpt-4o-system-card/ 报告链接 企业级生成式人工智能LLM大模型技术、算法及案例实战…

UE5用蓝图实现物体A始终朝向物体B |Find Look at Rotation|

非常常用的蓝图节点 |Find Look at Rotation|&#xff1a;获取 物体A 到 物体B 的Rotator。 Tick中将算出的Rotator设置给物体A&#xff0c;即可实现永远朝向物体B