【11】Strongswan processor 详解1

processor_t结构体,声明了一些公用方法:

get_total_threads获取总的线程数量;

get_idle_threads获取空闲线程数量;

get_working_threads按指定的优先级获取处理该优先级的job的线程数量;

get_job_load 或取指定优先级job队列中的job数量;

queue_job 添加job到指定job优先级对应的队列中;

execute_job直接调用一个空闲线程处理job,如果没有空闲线程则直接由调用该接口的线程直接处理job。

set_threads 设置线程池中的线程数量,这可能导致线程池的扩大或缩小。

cancel 线程数量设置为0,取消线程池,直到所有job处理完毕。

destroy 销毁processor对象。

private_processor_t 结构体继承processor_t结构体,

processor_create函数创建一个processor_t对象,其中挂载公有函数初始化processor_t对象,除此之外,private_processor_t还有私有的成员:

total_threads 正在运行的工作线程数量,他们可能处于等待job_added条件变量中或正在处理job;

desired_threads 用户指定的线程数量;set_threads 设置的线程数量会保存。

working_threads数组,每个优先级的线程数量;

threads 链表,保存线程池中所有的线程;

jobs数组,每个优先级的job链表;

prio_threads数组,每个优先级指定的线程数量;

mutex互斥锁

job_added条件变量,加入job通知,线程从条件变量处继续执行,从队列中取job执行。

thread_terminated 线程结束条件变量。线程函数退出时发送该信号,上述cancel函数接收该信号。

worker_thread_t结构体描述一个工作线程:

processor 指向实例化的processor对象;

thread 指向工作线程;

job 指向将要被该线程处理的job;

priority job的优先级。

get_idle_threads_nolock函数:

total_threads 总的线程数减去正在执行job的线程数量。

get_job函数:

值越小,优先级越高,从最高优先级的job开始,避让算法,prio_threads[i]大于working_threads[i]说明该i级别的job处理线程不够,reserved保存缺口数量,在for循环执行到下一个优先级的job时,reserved >= idle的化就直接退出不处理,优先高级别的job。跳过这些能get了,就remove_first从该优先级的job链表中取出第一个job。

process_jobs函数:

是线程池多有线程的执行函数。

while (this->desired_threads >= this->total_threads)决定是否跳出循环结束线程,当不成立时说明desired_threads 变小了,线程池缩小了,要把执行完job的线程退出。否则则取出worker线程优先级一致的job,调用process_job处理job,注意互斥锁的加锁与解锁,入时解锁处理job,出时加锁继续下一次的保护。没有job则条件等待。由于条件等待不超时,所以线程池的缩放需要加入job的信号激活。

那么当此线程退出时,发生了线程池缩小,total_threads线程数减少,发送thread_terminated条件信号。在cancel函数中接收判断线程是否都已经释放了:

c 复制代码
	while (this->total_threads > 0)
	{
		this->job_added->broadcast(this->job_added);
		this->thread_terminated->wait(this->thread_terminated, this->mutex);
	}

process_job函数处理job:

(1) working_threads++ 增加总的在处理job数

(2) 由于thread_cleanup_pop(FALSE);纯如false,不必理会

(3)调用job->execute的处理job,返回值的几种类型:

若是JOB_REQUEUE_TYPE_NONE,则!= JOB_REQUEUE_TYPE_DIRECT,跳出循环,后续to_destroy = worker->job; 进而to_destroy->destroy(to_destroy);销毁job。

若是JOB_REQUEUE_TYPE_DIRECT,则是再直接执行job->execute,前提是worker->job->cancel不为空,也即可取消,否则while中一直执行不可取消了。

若是JOB_REQUEUE_TYPE_FAIR,后续插入job队列。

若是JOB_REQUEUE_TYPE_SCHEDULE,则...

JOB_REQUEUE_TYPE_DIRECT:

(4)调用job->execute后,working_threads--

(5)如果在job->execute时,worker->job->status 设置为 JOB_STATUS_CANCELED,则销毁job。

queue_job函数:

按不同的优先级插入job,并向线程发送条件变量信号激发处理。

execute_job:

如果有空闲线程,插入和job相同优先级的队列的首部,唤醒等待此条件变量的线程,

如果插入队列没有成功,则由调用此函数的线程直接处理job的execute函数

set_threads:

(1)根据配置预设各优先级job的处理线程数量。

(2)根据要设置的count线程数,扩充或缩小线程池。

(3)缩小,则this->desired_threads = count;,在process_jobs函数中,处理完job后会while条件判断失败,退出循环,退出该线程,达到减少目的。

(4)扩大,则thread_create创建新的线程。

线程局部存储变量private_thread_t :

c 复制代码
//每个线程的id、cleanup_handlers之类在不同的存储空间,互不影响。
thread_t *thread_current()
{
	private_thread_t *this;

	this = (private_thread_t*)current_thread->get(current_thread);
	if (!this)
	{
		this = thread_create_internal();
		this->id = get_thread_id();
		current_thread->set(current_thread, (void*)this);
	}
	return &this->public;
}

u_int thread_current_id()
{
	private_thread_t *this = (private_thread_t*)thread_current();

	return this ? this->id : 0;
}

void thread_cleanup_push(thread_cleanup_t cleanup, void *arg)
{
	private_thread_t *this = (private_thread_t*)thread_current();
	cleanup_handler_t *handler;

	INIT(handler,
		.cleanup = cleanup,
		.arg = arg,
	);

	this->cleanup_handlers->insert_last(this->cleanup_handlers, handler);
}

(1)在多线程编程中,pthread_setspecific 和 pthread_getspecific 是两个用于处理线程局部存储(TLS)的函数,

(2)它们允许线程存储和访问线程特定的数据。这些函数提供了一种在同一线程中不同函数间共享数据的方法,这对于创建线程安全的程序至关重要。

(3)线程局部存储是一种允许数据在多个线程间独立存在的机制。每个线程都有自己的数据副本,因此对这些数据的操作不会影响其他线程。

(4)这种机制在处理不支持原子操作的自定义数据类型时尤其有用,因为它可以在不使用锁的情况下实现线程安全。

(5)要使用这些函数,首先需要通过 pthread_key_create 创建一个 pthread_key_t 类型的键。这个键用于标识线程特定的数据。

(6)然后,可以使用 pthread_setspecific 将数据与键关联,使用 pthread_getspecific 获取与键关联的数据。

(7)在上述代码中,pthread_setspecific 用于设置线程特定的数据,而 pthread_getspecific 用于获取这些数据。

(8)每个线程都有自己的数据副本,因此即使是使用相同的键,不同线程中的数据也是独立的。

相关推荐
达斯维达的大眼睛11 分钟前
Linux网络多进程并发服务器和多线程并发服务器
linux·服务器·网络
Lilith的AI学习日记1 小时前
LangChain高阶技巧:动态配置Runnable组件的原理剖析与实战应用
大数据·网络·人工智能·架构·langchain
安科瑞刘鸿鹏1 小时前
智能配电保护:公共建筑安全的新 “防火墙”
运维·网络·物联网·算法·安全·能源
czhc11400756631 小时前
网络5 TCP/IP 虚拟机桥接模式、NAT、仅主机模式
网络·tcp/ip·桥接模式
逆水寻舟1 小时前
尚硅谷2019版Java网络编程笔记
java·网络·笔记
邪恶的贝利亚10 小时前
FFMEPG常见命令查询
linux·运维·网络·ffmpeg
只会写Bug的程序员11 小时前
面试之《websocket》
网络·websocket·网络协议
christine-rr11 小时前
【25软考网工笔记】第二章 数据通信基础(1)信道特性 奈奎斯特 香农定理
网络·信息与通信·信号处理·软考
挣扎的蓝藻12 小时前
使用 Python 扫描 Windows 下的 Wi-Fi 网络实例演示
网络·windows·python
无名之逆12 小时前
[特殊字符] Hyperlane:为现代Web服务打造的高性能Rust文件上传解决方案
服务器·开发语言·前端·网络·后端·http·rust