Кіріспе

Компьютерлік жадыны басқару әдісі

Компьютерлік бағдарламалауда, жиекке (thread) жергілікті сақтау (TLS) – жиекке жергілікті статикалық немесе жаһандық жадты пайдаланатын жадты басқару әдісі. Бұл ұғым жеке жиектері бар жүйеде жаһандық көрінетін деректерді сақтауға мүмкіндік береді. Көптеген жүйелер жиекке жергілікті жад блогының мөлшеріне шектеу қояды, көбінесе бұл шектеулер өте қатаң болады. Дегенмен, егер жүйе кем дегенде жад мекенжайы (көрсеткіш) мөлшеріндегі айнымалы жиекке жергілікті жадты қамтамасыз ете алса, онда бұл кез келген мөлшердегі жад блоктарын жиекке жергілікті түрде пайдалануға мүмкіндік береді, мұндай жад блогын динамикалық түрде бөліп, осы блоктың жад мекенжайын жиекке жергілікті айнымалыда сақтау арқылы. RISC машиналарында шақыру конвенциясы көбінесе осы мақсат үшін жиек көрсеткіш тіркелімін резервтейді.

Қолданылуы

Қазіргі заманғы бағдарламалауда жалпы айнымалыларды қолдану көбінесе ұсынылмайды, бірақ UNIX сияқты кейбір ескі операциялық жүйелер бастапқыда бір процессорлы аппараттық құралдар үшін жасалған және маңызды мәндерді сақтау үшін жиі жалпы айнымалыларды пайдаланады. Мысалы, C кітапханасының көптеген функциялары қолданатын `errno`. Қазіргі заманғы машинада, егер бірнеше жіп `errno` айнымалысын өзгерте алса, бір жіптегі жүйелік функцияны шақыру, басқа жіптегі жүйелік функцияны шақыру арқылы бұрын орнатылған мәнді жойып жіберуі мүмкін, тіпті осы басқа жіптегі код қате жағдайын тексеруге үлкермес бұрын. Шешім – `errno` айнымалысы глобалды сияқты көрініп тұрса да, физикалық жағынан әр жіпке арналған жад жинағында, яғни жіптік жергілікті сақтау орнында сақталуы керек. Екінші жағдай – бірнеше жіптің ақпаратты жалпы айнымалыға жинақтауы. Жарыс жағдайын болдырмау үшін, осы жалпы айнымалыға кез келген қолжетімділік mutex арқылы қорғалуы тиіс. Оның орнына, әр жіп жеке жіптік жергілікті айнымалыға жинақтауы мүмкін, осылайша жарыс жағдайын тудыру мүмкіндігін жойып, құлыптау қажеттілігін де жояды. Содан кейін жіптер тек өздерінің жеке жіптік жергілікті айнымалыларынан бір ғана жалпы айнымалыға соңғы жинақтауды синхронизациялауы керек.

Windows-ты іске асыру

Қолданбалы бағдарламалау интерфейсі (API) функциясы TlsAlloc қолданылмаған TLS слот индексін алу үшін пайдаланылуы мүмкін; бұл кезде TLS слот индексі «қолданылған» деп есептеледі. TlsGetValue және TlsSetValue функциялары TLS слот индексімен сәйкестендірілген, жіпке арналған жергілікті айнымалыға жад адресін оқу және жазу үшін қолданылады. TlsSetValue тек ағымдағы жіп үшін ғана айнымалыға әсер етеді. TLS слот индексін босату үшін TlsFree функциясын шақыруға болады. Әрбір жіп үшін Win32 жіп ақпарат блогы болады. Бұл блок ішіндегі жазбалардың бірі – сол жіпке арналған жіпке арналған жергілікті сақтау кестесі. TlsAlloc әр шақыру үшін адрес кеңістігіне сәйкес келетін, осы кестеге бірегей индекс қайтарады. Әрбір жіптің өз жеке жіпке арналған жергілікті сақтау кестесінің көшірмесі болады. Сондықтан, әрбір жіп TlsSetValue(индекс) функциясын тәуелсіз түрде пайдалана алады және TlsGetValue(индекс) арқылы көрсетілген мәнді ала алады, себебі бұл функциялар жіптің өзінің кестесінде жазуды орнату және іздеуді жүзеге асырады. TlsXxx функциялар тобынан басқа, Windows атқарылатын файлдары процестің әрбір жіпі үшін әртүрлі бетке бейімделген бөлімді анықтай алады. TlsXxx мәндерінен айырмашылығы, бұл беттер кез келген және жарамды адрестерді қамтуы мүмкін. Дегенмен, бұл адрестер әрбір атқарылатын жіп үшін әртүрлі болады, сондықтан оларды асинхронды функцияларға (басқа жіпте орындалуы мүмкін) немесе виртуалды адрестің бүкіл процесс ішінде бірегей деп есептейтін кодқа жібермеу керек. TLS бөлімдері жадты беттеу арқылы басқарылады және олардың мөлшері бет мөлшеріне дейін квантталады (x86 машиналарын үшін 4кБ). Мұндай бөлімдерді бағдарламаның негізгі атқарылатын файлында ғана анықтауға болады, себебі олар LoadLibrary арқылы жүктелгенде дұрыс инициализацияланбайды.

P3 тармақтарды іске асыру

Pthreads API-де, жіпке жергілікті жад, "жіпке тән деректер" терминімен белгіленеді. `pthread key create` және `pthread key delete` функциялары сәйкесінше, жіпке тән деректерге кілт жасау және жою үшін қолданылады. Кілттің түрі нақты түрде жасырын қалдырылған және `pthread key t` деп аталады. Бұл кілтты барлық жіптер көре алады. Әрбір жіпте кілтты `pthread setspecific` арқылы жіпке тән деректермен байланыстыруға болады. Деректерді кейіннен `pthread getspecific` көмегімен алуға болады. Сонымен қатар, `pthread key create` опциялық түрде деструктор функциясын қабылдауы мүмкін, егер жіпке тән деректер NULL болмаса, жіп аяқталғанда автоматты түрде шақырылады. Деструктор параметр ретінде кілтқа байланысты мәнді қабылдайды, сондықтан ол тазалау әрекеттерін (қосылыстарды жабу, жадты босату және т.б.) орындай алады. Деструктор көрсетілген кезде де, бағдарлама процестік деңгейде жіпке тән деректерді босату үшін `pthread key delete` шақыруы керек (деструктор тек жіпке жергілікті деректерді ғана босатады).

Тілге тән іске асыру

Бағдарламашылардың тиісті API функцияларын шақыруына сүйенуден басқа, бағдарламалау тілін жіптік жергілікті сақтауды (TLS) қолдау үшін кеңейту де мүмкін.