先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
线程pthread结构内存
在介绍线程本地变量存储时,就不得不介绍一下pthread结构的内存,它定义了线程的重要数据结构,描述了用户状态线程的完整信息。
pthread 结构非常复杂,通过 specific_1stblock 数组和特定的辅助数组与 TLS 相关。
#define PTHREAD\_KEY\_2NDLEVEL\_SIZE 32
#define PTHREAD\_KEY\_1STLEVEL\_SIZE \
((PTHREAD\_KEYS\_MAX + PTHREAD\_KEY\_2NDLEVEL\_SIZE - 1) \
/ PTHREAD\_KEY\_2NDLEVEL\_SIZE)
struct pthread
{
union
{
#if !TLS\_DTV\_AT\_TP
/\* This overlaps the TCB as used for TLS without threads (see tls.h). \*/
tcbhead\_t header;
#else
struct
{
int multiple_threads;
int gscope_flag;
} header;
#endif
void \*__padding[24];
};
list\_t list;
pid\_t tid;
...
struct pthread\_key\_data
{
/\* Sequence number. We use uintptr\_t to not require padding on
32- and 64-bit machines. On 64-bit machines it helps to avoid
wrapping, too. \*/
uintptr\_t seq;
/\* Data pointer. \*/
void \*data;
} specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
/\* Two-level array for the thread-specific data. \*/
struct pthread\_key\_data \*specific[PTHREAD_KEY_1STLEVEL_SIZE];
/\* Flag which is set when specific data is set. \*/
bool specific_used;
...
}
__thread 关键字
该关键字可用于在 GCC/Clang 编译环境中声明 TLS 变量, 该关键字不是 C 标准,并且因编译器不同而有差异;
原理介绍
使用 __thread关键字声明的变量存储在线程的pthred 结构与堆栈空间之间,也就是说,在内存布局方面,从高地址到底层地址的内存分布为:pthred结构、可变区和堆栈区(堆栈的底部和可变区的顶部是连续的);
在这种方式下的线程本地变量,变量的类型不能是复杂的类型,如C++的class类型,而且动态申请的变量空间,需要主动释放,线程结束时,只是对变量空间回收,而对应的动态内存则会泄漏。
代码举例
/\*
\* created by senllang 2024/1/1
\* mail : study@senllang.onaliyun.com
\* Copyright (C) 2023-2024, senllang
\*/
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define THREAD\_NAME\_LEN 32
__thread char threadName[THREAD_NAME_LEN];
__thread int delay = 0;
typedef struct ThreadData
{
char name[THREAD_NAME_LEN];
int delay;
}ThreadData;
void \*threadEntry(void \*arg)
{
int ret = 0;
int i = 0;
ThreadData \* data = (ThreadData \*)arg;
printf("[%lu] thread entered \n", pthread\_self());
strncpy(threadName, data->name, THREAD_NAME_LEN);
delay = data->delay;
for(i = 0; i < delay; i++)
{
usleep(10);
}
printf("[%lu] %s exiting after delay %d.\n", pthread\_self(), threadName, delay);
pthread\_exit(&ret);
}
int main(int argc, char \*argv[])
{
pthread\_t thid1,thid2,thid3;
void \*ret;
ThreadData args1 = {"thread 1", 50000}, args2 = {"thread 2", 25000}, args3 = {"thread 3", 12500};
strncpy(threadName, "Main Thread", THREAD_NAME_LEN);
if (pthread\_create(&thid1, NULL, threadEntry, &args1) != 0)
{
perror("pthread\_create() error");
exit(1);
}
if (pthread\_create(&thid2, NULL, threadEntry, &args2) != 0)
{
perror("pthread\_create() error");
exit(1);
}
if (pthread\_create(&thid3, NULL, threadEntry, &args3) != 0)
{
perror("pthread\_create() error");
exit(1);
}
if (pthread\_join(thid1, &ret) != 0)
{
perror("pthread\_create() error");
exit(3);
}
if (pthread\_join(thid2, &ret) != 0)
{
perror("pthread\_create() error");
exit(3);
}
if (pthread\_join(thid3, &ret) != 0)
{
perror("pthread\_create() error");
exit(3);
}
printf("[%s]all thread exited delay:%d .\n", threadName, delay);
}
每个线程定义了两个线程本地变量 threadName, delay,在线程处理函数中,对它们赋值后,再延迟一段时间,然后输出这两个变量值,结果可以看到每个线程的本地变量值都不一样,可以独立使用。
运行结果:
[senllang@hatch example_04]$ gcc -lpthread threadLocalStorage_gcc.c
[senllang@hatch example_04]$ ./a.out
[139945977145088] thread entered
[139945960359680] thread entered
[139945968752384] thread entered
[139945960359680] thread 3 exiting after delay 12500.
[139945968752384] thread 2 exiting after delay 25000.
[139945977145088] thread 1 exiting after delay 50000.
[Main Thread]all thread exited delay:0 .
线程API方式
另一种使用线程本地变量的方式,是使用线程key相关的API,它分为两类,一是创建和销毁接口,另一类是变量的设置与获取接口。
这种方式下,线程的本地数据存储在 pthread结构中,其中specific_1stblock,specific两个数组按key值索引,并存储对应的线程本地数据;
线程本地数据的数量,在这种方式下是有限的。
创建与销毁接口
#include <pthread.h>
int pthread\_key\_create(pthread\_key\_t \*key, void(\*destructor)(void\*));
int pthread\_key\_delete(pthread\_key\_t key);
创建接口,获取一个 pthread_key_t变量的值,其实就是内存获取一个键值来存储数据,第二个参数destructor传递一个销毁数据的方法,当本地数据为复杂数据类型,或者动态申请内存时,在线程退出时进行清理调用。
在线程使用完后,需要释放对应的key。
设置本地变量值接口
#include <pthread.h>
int pthread\_setspecific(pthread\_key\_t key, const void \* value);
void \* pthread\_getspecific(pthread\_key\_t key);
这里设置线程的本地变量值,和获取线程本地变量值;
在不同线程中设置时,就会只设置当前线程的本地变量,不影响其它线程。
代码示例
/\*
\* created by senllang 2024/1/1
\* mail : study@senllang.onaliyun.com
\* Copyright (C) 2023-2024, senllang
\*/
#include <stdio.h>
#include <pthread.h>
// 定义一个 TLS 键
pthread\_key\_t tls_key;
void ShowThreadLocalData(char \*prompt, pthread\_t thid)
{
// 获取 TLS 存储的值
int \*value = (int \*) pthread\_getspecific(tls_key);
if (value == NULL)
{
printf("[%s]Thread: %ld, Value: NULL\n", prompt, thid);
} else
{
printf("[%s]Thread: %ld, Value: %d\n", prompt, thid, \*value);
}
}
// 线程函数
void \*thread\_func(void \*arg)
{
ShowThreadLocalData("pre", pthread\_self());
pthread\_setspecific(tls_key, (void \*) arg);
ShowThreadLocalData("after", pthread\_self());
return NULL;
}
int main()
{
// 创建 2 个线程
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
最全的Linux教程,Linux从入门到精通
======================
1. **linux从入门到精通(第2版)**
2. **Linux系统移植**
3. **Linux驱动开发入门与实战**
4. **LINUX 系统移植 第2版**
5. **Linux开源网络全栈详解 从DPDK到OpenFlow**
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**