Linux オペレーティング システムを使用する過程で、ストレージ デバイスの管理と構成が必要になることがよくあります。その中でも、ストレージ デバイスの解決とパーティション分割は、一般的な管理タスクの 1 つです。ストレージの解析とパーティショニングを実行する方法を理解すると、ストレージ リソースをより有効に活用し、システムのパフォーマンスを向上させることができます。この記事では、Linux システムにおけるストレージ デバイスの解析とパーティショニングに関する関連知識を紹介します。
Linux システムでマルチスレッド プログラミングに C/C を使用する場合、最も一般的な問題は、同じ変数のマルチスレッドの読み取りと書き込みです。ほとんどの場合、このような問題はロック メカニズムによって処理されますが、これはもちろん、システムがネイティブにアトミック操作をサポートしているデータ型については、アトミック操作を使用して処理することができ、これによりプログラムのパフォーマンスがある程度向上します。では、システムがアトミック操作をサポートしていないカスタム データ型の場合、ロックを使用せずにスレッド セーフを実現するにはどうすればよいでしょうか?この記事では、この種のスレッド セーフティの問題にスレッド ローカル ストレージの観点から対処する方法を簡単に説明します。
1.データ型
C/C プログラムには、グローバル変数、関数内で定義された静的変数、およびローカル変数が存在することがよくありますが、ローカル変数については、スレッド セーフの問題がないため、この記事の対象外です。関数内で定義されたグローバル変数と静的変数は、同じプロセス内のすべてのスレッドからアクセスできる共有変数であるため、マルチスレッドの読み取りおよび書き込みの問題が発生します。 1 つのスレッドで変数の内容が変更されると、他のスレッドは変更された内容を認識して読み取ることができます。これはデータ交換にとって非常に高速です。ただし、マルチスレッドの存在により、同じ変数に対して異なる内容が存在する可能性があります。 2 つ以上のスレッドが変数のメモリ内容を同時に変更し、変数が変更されるときにメモリ値を読み取る複数のスレッドが存在します。メモリを保護するために対応する同期メカニズムが使用されていない場合、読み取られたデータはすべてこれは予測不可能であり、プログラムのクラッシュを引き起こす可能性もあります。
スレッド内の各関数呼び出しではアクセスでき、他のスレッドではアクセスできない変数が必要な場合、それを実装するための新しいメカニズムが必要になります。これをスレッドに対してローカルな静的メモリ (スレッド ローカル静的変数) と呼びます。スレッド固有データ (TSD: Thread-Specific Data) またはスレッドローカル ストレージ (TLS: Thread-Local Storage) とも呼ばれます。このタイプのデータの場合、プログラム内の各スレッドは変数のコピーを維持し、そのスレッド内に長期間存在します。このような変数に対する操作は他のスレッドに影響を与えません。以下に示すように:
2. ワンタイム初期化
スレッド固有のデータを説明する前に、まず 1 回限りの初期化について理解しましょう。マルチスレッド プログラムには、作成されるスレッドの数に関係なく、一部のデータの初期化は 1 回しか実行できないという要件がある場合があります。例: C プログラムでは、特定のクラスは、プロセスのライフサイクル全体を通じて 1 つのインスタンス オブジェクトのみを持つことができます。マルチスレッドの場合、オブジェクトを安全に初期化できるようにするために、ワンタイム初期化メカニズムが使用されます。は特に重要です。 ——デザインパターンでは、この実装はシングルトンパターン(Singleton)と呼ばれることが多いです。 Linux では、1 回限りの初期化を実現するために次の関数が提供されています。 リーリー
さらに、パラメータ Once_control は、PTHRAD_ONCE_INIT に初期化された静的変数を指す、pthread_once_t 型変数へのポインタである必要があります。同様の機能を持つ関数 std::call_once() が C 0x の後に提供されており、使い方は本関数と同様です。
3. スレッド ローカル データ API
Linuxではスレッドローカルデータを操作するために以下の関数が提供されていますリーリー
関数 pthread_key_create() は、スレッドローカル データの新しいキーを作成し、key を介して新しく作成されたキー バッファーを指します。すべてのスレッドが返された新しいキーを使用できるため、パラメータ キーをグローバル変数にすることができます (グローバル変数は通常、C マルチスレッド プログラミングでは使用されませんが、スレッドローカル データをカプセル化するために別のクラスが使用され、各変数は独立した pthread_key_t)。デストラクターは、次の形式のカスタム関数を指します:
void Dest (void *value) { // Release storage pointed to by 'value' }
只要线程终止时与key关联的值不为NULL,则destructor所指的函数将会自动被调用。如果一个线程中有多个线程局部存储变量,那么对各个变量所对应的destructor函数的调用顺序是不确定的,因此,每个变量的destructor函数的设计应该相互独立。
函数pthread_key_delete()并不检查当前是否有线程正在使用该线程局部数据变量,也不会调用清理函数destructor,而只是将其释放以供下一次调用pthread_key_create()使用。在Linux线程中,它还会将与之相关的线程数据项设置为NULL。
由于系统对每个进程中pthread_key_t类型的个数是有限制的,所以进程中并不能创建无限个的pthread_key_t变量。Linux中可以通过PTHREAD_KEY_MAX(定义于limits.h文件中)或者系统调用sysconf(_SC_THREAD_KEYS_MAX)来确定当前系统最多支持多少个键。Linux中默认是1024个键,这对于大多数程序来说已经足够了。如果一个线程中有多个线程局部存储变量,通常可以将这些变量封装到一个数据结构中,然后使封装后的数据结构与一个线程局部变量相关联,这样就能减少对键值的使用。
函数pthread_setspecific()用于将value的副本存储于一数据结构中,并将其与调用线程以及key相关联。参数value通常指向由调用者分配的一块内存,当线程终止时,会将该指针作为参数传递给与key相关联的destructor函数。当线程被创建时,会将所有的线程局部存储变量初始化为NULL,因此第一次使用此类变量前必须先调用pthread_getspecific()函数来确认是否已经于对应的key相关联,如果没有,那么pthread_getspecific()会分配一块内存并通过pthread_setspecific()函数保存指向该内存块的指针。
参数value的值也可以不是一个指向调用者分配的内存区域,而是任何可以强制转换为void的变量值,在这种情况下,先前的pthread_key_create()函数应将参数
destructor设置为NULL
函数pthread_getspecific()正好与pthread_setspecific()相反,其是将pthread_setspecific()设置的value取出。在使用取出的值前最好是将void转换成原始数据类型的指针。
四、深入理解线程局部存储机制
\1. 深入理解线程局部存储的实现有助于对其API的使用。在典型的实现中包含以下数组:
pthread_key_create()返回的pthread_key_t类型值只是对全局数组的索引,该全局数组标记为pthread_keys,其格式大概如下:
数组的每个元素都是一个包含两个字段的结构,第一个字段标记该数组元素是否在用,第二个字段用于存放针对此键、线程局部存储变的解构函数的一个副本,即destructor函数。
\2. 在常见的存储pthread_setspecific()函数参数value的实现中,大多数都类似于下图的实现。图中假设pthread_keys[1]分配给func1()函数,pthread API为每个函数维护指向线程局部存储数据块的一个指针数组,其中每个数组元素都与图线程局部数据键的实现(上图)中的全局pthread_keys中元素一一对应。
五、总结
使用全局变量或者静态变量是导致多线程编程中非线程安全的常见原因。在多线程程序中,保障非线程安全的常用手段之一是使用互斥锁来做保护,这种方法带来了并发性能下降,同时也只能有一个线程对数据进行读写。如果程序中能避免使用全局变量或静态变量,那么这些程序就是线程安全的,性能也可以得到很大的提升。如果有些数据只能有一个线程可以访问,那么这一类数据就可以使用线程局部存储机制来处理,虽然使用这种机制会给程序执行效率上带来一定的影响,但对于使用锁机制来说,这些性能影响将可以忽略。更高性能的线程局部存储机制就是使用__thread,这个以后再讨论。
需要C/C++ Linux服务器开发学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
本文介绍了Linux系统中存储设备解析和分区的相关知识,包括使用fdisk命令、使用parted命令、使用mkfs命令等。了解这些知识,可以帮助我们更好地管理和配置存储设备,优化系统性能。希望读者能够根据实际需求选择适合自己的方法,并加以应用。
以上がLinux ストレージの解析とパーティショニングのスキルを簡単にマスターの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。