Linux学习记录十四----------线程的创建和回收

news2024/9/20 18:39:53

文章目录

  • 五、Linux线程
      • 1.守护进程
        • 1.1.守护进程的特点
        • 1.2.进程组
        • 1.3会话
        • 1.4创建守护进程模型
      • 2.线程的概念
      • 3.线程的创建及相关函数
        • 3.1.创建线程‐‐pthread_create
        • 3.2.单个线程退出 --pthread_exit
        • 3.3.阻塞等待线程退出,获取线程退出状态--pthread_join
        • 3.4.线程分离函数--pthread_detach
        • 3.5.杀死(取消)线程--pthread_cancel
        • 3.6.比较两个线程ID是否相等(预留函数) --pthread_equal
      • 4.线程的分离属性


五、Linux线程

1.守护进程

守护进程是一种长期运行的进程(守护进程的生存期不一定长,但一般应该这样做),一般是操作系统启动的时候它就启动,操作系统关闭的时候它才关闭。守护进程跟终端无关联,也就是说它们没有控制终端,所以控制终端退出,也不会导致守护进程退出。守护进程是在后台运行的,不会占着终端,终端可以执行其他命令。Linux 操作系统本身是有很多的守护进程在默默地运行,维持着系统的日常活动。

1.1.守护进程的特点
  • 后台服务进程

  • 独立于控制终端

  • 周期性执行某任务

  • 不受用户登录注销影响

  • 一般采用以d结尾的名字(服务)

1.2.进程组
  • 进程的组长
    • 组里边的第一进程
    • 进程组的ID==进程中的组长的ID
  • 进程中组长的选择
    • 进程中的第一个进程
  • 进程组ID的设定
    • 进程组的ID就是组长的进程ID
1.3会话
  • 创建一个会话注意事项

    • 不能是进程组长
    • 创建会话的进程成为新进程组的组长
    • 有些lInux版本需要root权限执行此操作
    • 创建出的新会话会丢弃原有的控制终端 一般步骤;fork ,父亲死,儿子执行创建会话操作(setsid)
  • 获取进程所属的会话ID

    • pid_t getsid(pid_t pid);
  • 创建一个会话

    • pid_t setsid(void);
1.4创建守护进程模型
  • fork子进程,父进程退出 ----必须

  • 子进程创建新会话 -------必须

  • 改变当前工作目录chdir —非必须

  • 重设文件掩码 --非必须

  • 关闭文件描述符 --非必须

  • 执行核心工作----必须

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


int main()
{
        pid_t pid;
        pid = fork();
        if(pid == 0)
        {
                pid_t sid;

                sid = setsid();//创建会话
           
                while(1){//执行核心工作
        			sleep(1);
        		}
        }
        else if(pid > 0)
        {
                exit(0);//父进程退出
        }
        return 0;
}

在这里插入图片描述

2.线程的概念

在Linux下: 线程就是进程-轻量级进程 对于内核来货,线程就是进程 多进程和多线程的区别:

多进程: 始终共享的资源 代码、文件描述符、内存映射区–mmap

多线程:始终共享的资源:堆、全局变量,节省资源

  • 主线程和子线程

    • 共享: .text .bss .data 堆 动态加载区 环境变量 命令行参数
  • 通信:全局变量,堆

  • 不共享栈

    • eg一共五个线程,栈区被平均分成五块

在这里插入图片描述

  • 查看指定线程的LWP号:

    • 线程号和线程ID是有区别的
      • 线程号是给内核看的
  • 查看方式

    • 找到程序的进程ID

      • ps -Lf pid
      • top -p tid(线程状态动态显示)
        在这里插入图片描述

3.线程的创建及相关函数

3.1.创建线程‐‐pthread_create
int pthread_create( pthread_t *thread), //线程ID = 无符号长整型
					const pthread_attr_t *attr, //线程属性,NULL
					void *(*start_routine)(void *), //线程处理函数
					void *arg); //线程处理函数
/*@param:
 *		pthread:传出参数,线程创建成功之后,会被设置一个合适的值
 *		attr:默认传NULL
 *		start_routine:子线程的处理函数
 *		arg: 回调函数的参数
 *@return:成功:0,错误:错误号 //perror不能使用该函数打印错误信息
 */
注意:
	主线程先退出,子线程会被强制结束
	验证线程直接共享全局变量

创建线程

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

int i = 0;

void * pthread_son(void *arg)
{
	
	printf("create pthread successed pthid is %ld\n",pthread_self());
	while(i++)
	{
		printf("i = %d\n",i);
		sleep(1);
	}

}

int main()
{
	pthread_t pthid;
	int ret;
	ret = pthread_create(&pthid,NULL,pthread_son,NULL);
	if(ret != 0)
	{
		printf("error num is %d\n",ret);
        printf("%s\n",strerror(ret));
		return -1;
	}
	printf("create pthread successed parent pthid is %ld\n",pthread_self());

	for(;i < 5;i++)
	{
		printf("i = %d\n",i);
	}
	sleep(3);
	return 0;
}

在这里插入图片描述

3.2.单个线程退出 --pthread_exit

不论是主线程还是子线程调用exit(0)后整个所以线程都会结束,而调用pthread_exit()只会退出当前进程

函数原型: void pthread‐exit(void *retval);
retval指针:必须指向全局,堆
3.3.阻塞等待线程退出,获取线程退出状态–pthread_join
函数原型:
int pthread_join(pthread_t pthread, void **retval)
/*参数:
 *		pthread:要回收的子线程的ID
 *		retval:读取线程退出的携带信息
 *	传出参数
 *		void* ptr;
 */
     	pthread_join(pthid,&ptr);
 		指向的内存和pthread_exit参数指向地址一致

单个线程退出并回收

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

int i = 0;
int num = 100;
void * pthread_son(void *arg)
{
	
	printf("create pthread successed pthid is %ld\n",pthread_self());
	while(i++)
	{
		printf("i = %d\n",i);
		sleep(1);
		if(i == 10)
		{
			printf("exit pthread_son\n");
			pthread_exit(&num);//退出子线程
		}
	}

}

int main()
{
	pthread_t pthid;
	int ret;
	ret = pthread_create(&pthid,NULL,pthread_son,NULL);
	if(ret != 0)
	{
		printf("error num is %d\n",ret);
        printf("%s\n",strerror(ret));
		return -1;
	}
	printf("create pthread successed parent pthid is %ld\n",pthread_self());

	for(;i < 5;i++)
	{
		printf("i = %d\n",i);
	}
	void *ptr;
	pthread_join(pthid,&ptr);//回收线程ID为pthid的子线程
	printf("join child pthread  num is %d\n",*(int *)ptr);
	return 0;
}

在这里插入图片描述

3.4.线程分离函数–pthread_detach
函数原型:int pthread_datach(pthread_t thread);
调用该函数之后不需要 pthread_join
子线程会自动回收自己的PCB
3.5.杀死(取消)线程–pthread_cancel
函数原型: int pthread_cancel(pthread_t pthread);

pthread_testcancel();设置取消点—在取消点时就会杀死该线程

注:

  • 使用注意事项:

    • 在要杀死的子线程对应的处理的函数的内部,必须做过一次系统调用 (阻塞调用)
    • write read printf
    • int a = 2; int b = a+3;
    • 否则需要手动设置取消点
    int pthread_setcanceltype(int type,int *oldtype)
    PTHREAD_CANCEL_DEFERRED//等待目标点才会取消
    PTHREAD——CANCEL_ASYNCHRONOUS//目标线程会立即取消
    
3.6.比较两个线程ID是否相等(预留函数) --pthread_equal
函数原型:
int pthread_equal(pthread_t t1,pthread_t t2);

4.线程的分离属性

如果不回收线程资源会造成内存泄漏,且join不能完全回收线程资源

通过属性设置线程的分离

1.线程属性类型: pthread_attr_t attr;

2.线程属性操作函数:

  • 对线程属性变量的初始化
    • int pthread_attr_init(pthread_attr_t* attr);
  • 设置线程分离属性
    • int pthread_attr_setdetachstate( pthread_attr_t* attr, int detachstate );
    • 参数:
      • attr : 线程属性
      • detachstate PTHREAD_CREATE_DETACHED(分离) PTHREAD_CREATE_JOINABLE(非分离)
  • 释放线程资源函数 int pthread_attr_destroy(pthread_attr_t* attr);

设置分离属性

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

int i = 0;
int num = 100;
void * pthread_son(void *arg)
{
	
	printf("create pthread successed pthid is %ld\n",pthread_self());
	while(i++)
	{
		printf("i = %d\n",i);
		sleep(1);
		if(i == 10)
		{
			printf("exit pthread_son\n");
			pthread_exit(&num);
		}
	}

}

int main()
{
	pthread_t pthid;
	int ret;
	pthread_attr_t attr;
	pthread_attr_init(&attr);//初始化线程属性变量
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//设置线程属性
	ret = pthread_create(&pthid,&attr,pthread_son,NULL);
	if(ret != 0)
	{
		printf("error num is %d\n",ret);
        printf("%s\n",strerror(ret));
		return -1;
	}
	printf("create pthread successed parent pthid is %ld\n",pthread_self());

	for(;i < 5;i++)
	{
		printf("i = %d\n",i);
	}
	sleep(15);
	pthread_attr_destroy(&attr);//释放线程资源函数
	return 0;
}

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

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

相关文章

python怎么运行cmd命令

使用os.system(“cmd”) 该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0100,换算为10进制得到256。 …

JavaScript web API完结篇---多案例

BOM window对象 >包含docment Browser Object Model 定时器–延时函数 之前学的是间歇函数 让代码延迟执行 仅执行一次 setTimeout(回调函数&#xff0c;等待毫秒数) 消除 clearTimeout(timer) > 用于递归时需要进行去除 JS执行机制 单线程 > 一个任务结束&…

ROS组合导航笔记2:使用外部定位系统

在上一单元中&#xff0c;我们了解了如何合并不同传感器的数据以生成机器人的姿势估计。因此&#xff0c;基本上&#xff0c;我们介绍了图表的以下部分&#xff0c;其中向 robot_localization 节点提供了不同的传感器&#xff0c;以便通过卡尔曼滤波器进行合并。 但是...图表的…

【浅水模型MATLAB】尝试复刻SCI论文中的溃坝流算例

【浅水模型MATLAB】尝试复刻SCI论文中的溃坝流算例 前言问题描述控制方程及数值方法浅水方程及其数值计算方法边界条件的实现 代码框架与关键代码模拟结果 更新于2024年9月17日 前言 这篇博客算是学习浅水方程&#xff0c;并利用MATLAB复刻Liang (2004)1中溃坝流算例的一个记录…

【FreeRL】Rainbow_DQN的实现和测试

文章目录 前言环境1 PER note2 C51 note3 Noisy note4 Rainbow note其他 前言 具体代码实现见&#xff1a;https://github.com/wild-firefox/FreeRL/blob/main/DQN_file/DQN_with_tricks.py 将其中所有的trick都用上即为Rainbow_DQN。 效果如下&#xff1a;&#xff08;学习曲…

word文档的写入(1)

Word文档的写入 我们手动复制Excel信息&#xff0c;再粘贴进Word&#xff0c;进行文件保存的整个操作。属于机械性的重复劳动&#xff0c;并不能带来太大价值。在Excel和Word的操作内&#xff0c;也没有能很好解决此类问题的方法。如果遇到信息一多&#xff0c;几十上百个文件&…

Win11小技巧之调节音量

无意中发现&#xff0c;鼠标悬停在喇叭&#x1f508;处可通过滚轮调节音量&#xff0c;无需每次都点开音量面板&#xff0c;再悬停在音量滚动条处通过滚轮调节&#xff01;&#xff08;设计师……怎么不早告诉我……&#xff09; 不用点开&#xff0c;之前一直都是这么调节音量…

c++—多态【万字】【多态的原理】【重写的深入学习】【各种继承关系下的虚表查看】

目录 C—多态1.多态的概念2.多态的定义及实现2.1多态的构成条件2.2虚函数的重写2.2.1虚函数重写的两个例外&#xff1a;2.2.1.1协变2.2.1.2析构函数的重写 2.3 c11的override和final2.3.1final2.3.2override 2.4 重载、重写、重定义的对比 3.抽象类3.1抽象类的概念3.2接口继承和…

5款录屏软件电脑版,哪一款更适合你?

身边不少做行政的小伙伴&#xff0c;经常需要制作一些培训视频、会议记录或是演示文稿。这就要求他们必须掌握一款好用的录屏软件。作为一个经常搜索各种办公软件的人&#xff0c;今天&#xff0c;我就来分享一下我使用过的五款录屏软件在录制电脑屏幕时的表现。 1、福昕录屏大…

枚举类题目练习心得

两数之和 题目如下&#xff1a; 一点思路&#xff1a;该题目仅限于数据量少的情况使用枚举&#xff0c;从题目分析来看&#xff0c;需求是给定一个数字&#xff0c;要求在给定数组中找到两个数字并使这两个数字和为给定数字且返回目标数字下标。参考题解思路结合本身思路代码…

Leetcode—环形链表||

题目描述 思路 快慢指针 结论 我们需要用到一个重要的结论&#xff1a;让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。 画图解释 1.利用快慢指针找到相遇点 2. 定义两个…

java138-异常处理_java 138错误

//异常 public class test79 { //定义方法声明定义异常&#xff0c;在满足条件时抛出异常对象&#xff0c;程序转向异常处理 public double count(double n,double m)throws Exception { if (m 0) {//如果除数等于0.则抛出异常实例 throw new Ex…

day03 - Java集合和常用类

第一章 Collection集合 1. Collection概述 集合&#xff1a;java中提供的一种容器&#xff0c;可以用来存储多个数据 集合和数组既然都是容器&#xff0c;它们有啥区别呢&#xff1f; 数组的长度是固定的。集合的长度是不固定的。集合可以随时增加元素&#xff0c;其大小也随…

kubeadm方式安装k8s+基础命令的使用

一、安装环境 二、前期准备 1.设置免密登录 [rootk8s-master ~]# ssh-keygen [rootk8s-master ~]# ssh-copy-id root192.168.2.77 [rootk8s-master ~]# ssh-copy-id root192.168.2.88 2.yum源配置 3.清空创建缓存 4.主机映射&#xff08;三台主机都要设置&#xff09; 5.安装…

vivado中选中bd文件后generate output product是什么用,create HDL wrapper是什么用

vivado中选中bd文件后generate output product是什么用 在Vivado中&#xff0c;“Generate Output Products” 是一个重要的步骤&#xff0c;它用于生成IP核的输出产品&#xff0c;这些产品是将IP核集成到设计中所需的文件。这些输出产品包括&#xff1a; 综合文件&#xff…

多线程下的共享变量访问数据竞争的问题

多线程下对共享变量的写存在数据竞问题可导致数据与预期不一致。最近在研究race conditions漏洞&#xff0c;用以下python 代码记录一下&#xff0c;以此论证&#xff0c;如下&#xff1a; from concurrent.futures import ThreadPoolExecutor globalNum 5 def test():global…

微积分-反函数6.1(反函数)

表1提供了一项实验的数据&#xff0c;其中细菌培养物在有限营养基中以100个细菌开始&#xff1b;在定时记录下细菌数量随时间的变化。细菌数量 N N N 是时间 t t t 的函数&#xff1a; N f ( t ) N f(t) Nf(t)。 然而&#xff0c;假设生物学家改变了她的观点&#xff0c;开…

京东App秒级百G日志传输存储架构设计与实战

本文作者&#xff1a;平台业务研发部-武伟峰&#xff0c;数据与智能部-李阳 背景 在日常工作中&#xff0c;我们通常需要存储一些日志&#xff0c;譬如用户请求的出入参、系统运行时打印的一些info、error之类的日志&#xff0c;从而对系统在运行时出现的问题有排查的依据。 …

作为研发部门的负责人,如何助力产品在市场竞争中胜出?浅谈 CTQ

在激烈的市场竞争中&#xff0c;产品研发团队如何帮助企业的产品脱颖而出&#xff1f;成功的产品往往不仅依赖于强大的功能和技术创新&#xff0c;还需要通过高效的研发效能&#xff0c;包括效率、质量和创新&#xff0c;来提升产品的市场竞争力。在本文中&#xff0c;我们将探…

文档内容识别系统源码分享

文档内容识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…