| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C中进程与线程的基本使用(结合代码讲解) -> 正文阅读 |
|
[C++知识库]C中进程与线程的基本使用(结合代码讲解) |
目录 (6)example(pthread_join主线程阻塞等待后释放资源) (7)example(pthread_detach子线程结束后自动释放资源) 零、前言? ? ? ? 一个简单的总结,内容也比较简单,不是很完整,其他的待日后补充,比如进程间的数据通讯方式、多线程的其他锁的实现和条件变量等等。文章中可能出现内容有异议的,欢迎评论区讨论。下面的内容每部分都结合了demo进行介绍,希望你能从中受益。文章中的内容主要来源于 《unix网络编程卷一》。 一、进程?1、基本介绍与基本使用?????????使用fork函数创建了一个新的进程,新进程(子进程)与原有的进程(父进程)一模一样。子进程和父进程使用相同的代码段;子进程拷贝了父进程的堆栈段和数据段。子进程一旦开始运行,它复制了父进程的一切数据,各自运行,互不影响。而且由于子进程复制了父进程的堆栈段,所以子进程也复制了父进程的代码执行进度。
?????????fork 函数返回两个值,对于调用进程(父进程)返回新派生进程的进程 ID 号;对于子进程返回 0。使用 getpid 函数可以查看当前进程的 ID 号。 ????????子进程可以通过 getppid 函数来获取父进程的进程 ID 号;相反创建子进程后父进程无法再获得子进程的 ID号,唯一的方法就是在调用 fork 函数的时候保存返回值。父进程调用 fork 函数之前打开的所有描述符在 fork 函数返回后由子进程分享。 ????????进程间相互独立,互不影响。每个进程都有自己的地址空间,所以可能会出现,不同进程的变量虚拟地址相同的现象,其实他们指向的物理地址不同。
2、僵尸进程的产生与解决(1)原因? ? ? ? 在linux系统中可以通过 top 这个工具查看僵尸进程,如下图右上角的 zombie 即为僵尸进程的数量。 ????????a. 在子进程退出前父进程先退出,则系统会让init进程接管子进程; ????????b. 当子进程先于父进程终止,而父进程又没有调用wait函数等待子进程结束,子进程进入僵尸状态,并且会一直保持下去除非主进程退出。子进程处于僵尸状态时,内核只保存该进程的一些必要信息以备父进程所需。此时子进程始终占用着资源,同时也减少了系统可以创建的最大进程数; ????????c. 如果子进程先于父进程终止,且父进程调用了 wait 或 waitpid 函数,则父进程会等待子进程结束(阻塞等待)。 (2)解决办法????????a.? 在Linux下,可以简单地将 SIGCHLD 信号的操作设为 SIG_IGN,这样当子进程结束时就不会称为僵尸进程。
????????b. 主进程可以通过调用 pid_t wait(int *statloc) 来阻塞的等待子进程的退出。wait 函数将子进程终止时传递的参数值保存到 statloc 所指向的内存空间。然后通过宏 WIFEXITED(status) 确定子进程是否正常终止,通过宏 WEXITSTATUS(status) 获得子进程的返回值。
????????c.? 使用 waitpid,例如:waitpid(-1, &status, WNOHANG)?; -1 表示可以等待任意子进程终止,WNOHANG 表示子进程没有终止也不会进入阻塞状态,而是返回0并退出函数。
?二、线程1、进程的不足????????(1)、不断的生成子进程占用大量资源,因为每个子进程都要把父进程的内存映像复制到子进程中去,并在子进程中复制所有的描述符等。也可以说子进程和父进程完全一样,连程序的执行进度都完全一样,拥有独立的内存空间。 ????????(2)、子进程生成后会复制父进程的所有数据,包括调用fork之前的数据。所以父进程向尚未创建的子进程传递信息很容易,但子进程向父进程传递返回消息十分的吃力,需要借助进程间通讯机制。 2、线程的基本介绍????????线程是轻量级的进程,创建速度更快。同一个进程内的线程共享相同的全局内存,这使得线程间共享信息十分方便,但要面临同步的问题。 ????????下面是线程共享与独有的资源。
3、线程的五个基本操作(1)创建线程
????????程序正常启动后会自动创建主线程,其余线程才由 pthread_create 创建。每个线程由线程ID(thread ID)标识,其数据类型是 pthread_t(unsigned int)。 ????????每个线程都有很多属性:优先级、初始栈大小、是否是守护进程等,可以通过 attr 这个参数传递,默认情况下传递空指针。 ????????最后指导线程的执行函数 func 和该函数的唯一调用参数 arg,如果需要传递多个参数可以打包成结构体传值。func 传入参数和返回值都是通用指针(void *)。 ????????pthread_create 成功创建线程返回 0,不成功返回 非0(正数)。 (2)关闭线程????????线程退出的两种方式,一种是子线程执行函数的退出(隐式、显示);另一种是主线程的退出(程序进程结束,其附属的线程自然结束)。 ????????子线程的退出分为显示和隐式退出,隐式退出即线程的执行函数执行 return 返回;显示的退出即调用 pthread_exit。
(3)获取自身线程的 ID?
(4)阻塞等待线程的退出并释放资源????????通过给定线程 ID,阻塞的等待指定线程的终止,并释放该线程的资源。例如主线程阻塞的等待子线程的关闭,待子线程退出后释放其资源。
(5)子线程脱离? ? ? ? pthread_detach 函数,unix网络编程中解释是变为脱离状态(detach),脱离后该线程执行完毕会自动释放资源。如果是可汇合状态(joinable),该线程结束后需要另一个线程执行 pthread_join 来释放其资源。 ????????线程有两个状态:joinable 状态和 detach 状态。这个状态可以在 pthread_create 创建线程时设置,默认是 joinable。也就是默认需要你执行 pthread_join() 函数来阻塞的等待子线程的退出,以释放其资源。或者你可以在子线程中使用 pthread_detach(pthread_self()) 函数来改变自身线程的状态为 detach,这样当子线程执行结束后会自动的释放资源。 (6)example(pthread_join主线程阻塞等待后释放资源)
(7)example(pthread_detach子线程结束后自动释放资源)
4、多线程的数据共享????????为了保护多线程共享的数据,可以使用互斥锁。任何线程使用共享的数据时必须持有该锁(上锁),其他线程再试图上锁时会被阻塞,直到该数据被持有线程使用完后解锁。 ????????互斥锁的类型是 pthread_metux_t,互斥锁变量存在两种初始化方式:静态分配和动态分配。 ????????静态分配
? ? ? ? 动态分配
(1)互斥锁的基本使用
(2)example(注意两种初始化互斥锁的方法)
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 11:12:29- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |